WeDeen Login
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Premium Video Player</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #000;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
touch-action: manipulation;
}
.video-list {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
-webkit-overflow-scrolling: touch;
scroll-behavior: smooth;
}
.video-item {
height: 100vh;
scroll-snap-align: start;
position: relative;
display: flex;
justify-content: center;
align-items: center;
background-color: #000;
}
.video-wrapper {
position: relative;
width: 100%;
max-height: 100vh;
display: flex;
justify-content: center;
}
.video-player {
max-width: 100%;
max-height: 100vh;
object-fit: contain;
}
.loading-spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
border: 3px solid rgba(4, 115, 111, 0.3);
border-radius: 50%;
border-top-color: #04736F;
animation: spin 1s ease-in-out infinite;
display: none;
z-index: 10;
}
.play-pause-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 5;
cursor: pointer;
opacity: 0;
transition: opacity 0.3s ease;
background: rgba(0, 0, 0, 0.3);
}
.play-pause-btn {
width: 80px;
height: 80px;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.play-pause-btn:hover {
transform: scale(1.05);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
background: rgba(0, 0, 0, 0.8);
}
.play-icon,
.pause-icon {
color: #FFFFFF;
font-size: 0;
position: relative;
}
.play-icon::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-30%, -50%);
width: 0;
height: 0;
border-top: 15px solid transparent;
border-bottom: 15px solid transparent;
border-left: 25px solid #04736F;
}
.pause-icon::before,
.pause-icon::after {
content: "";
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 8px;
height: 30px;
background: #04736F;
}
.pause-icon::before {
left: 35%;
}
.pause-icon::after {
right: 35%;
}
.pause-icon {
display: none;
}
.play-pause-btn.playing .play-icon {
display: none;
}
.play-pause-btn.playing .pause-icon {
display: block;
}
.play-pause-overlay.visible {
opacity: 1;
}
.play-pause-btn:active {
transform: scale(0.95);
}
@keyframes spin {
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
/* Progress bar style */
.progress-container {
position: absolute;
bottom: 20px;
left: 20px;
right: 20px;
height: 4px;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
overflow: hidden;
z-index: 10;
opacity: 0;
transition: opacity 0.3s ease;
}
.video-wrapper:hover .progress-container {
opacity: 1;
}
.progress-bar {
height: 100%;
background: #04736F;
width: 0%;
transition: width 0.1s linear;
}
</style>
</head>
<body>
<div class="video-list" id="videoContainer">
<!-- Videos will be loaded dynamically here -->
</div>

<script>
document.addEventListener('DOMContentLoaded', function () {
const videoContainer = document.getElementById('videoContainer');
const apiToken = 'K41eS0BkLT623nxObXwEEgxXgtSDLB2l';
const apiUrl = 'https://api.baserow.io/api/database/rows/table/599037/?user_field_names=true';

function createVideoItem(videoUrl, index) {
if (videoUrl.includes("kinescope.io")) {
let embedUrl = videoUrl.replace("https://kinescope.io/", "https://kinescope.io/embed/");
return `
<div class="video-item" data-video-id="${index}">
<div class="video-wrapper">
<iframe src="${embedUrl}" frameborder="0" allowfullscreen
style="width: 100%; height: 100vh; background: black;">
</iframe>
</div>
</div>
`;
} else {
return `
<div class="video-item" data-video-id="${index}">
<div class="video-wrapper">
<video class="video-player" loop playsinline preload="${index === 0 ? 'auto' : 'none'}">
<source src="${videoUrl}" type="video/mp4">
</video>
<div class="loading-spinner" id="spinner${index + 1}"></div>
<div class="play-pause-overlay">
<div class="play-pause-btn">
<div class="play-icon"></div>
<div class="pause-icon"></div>
</div>
</div>
<div class="progress-container">
<div class="progress-bar"></div>
</div>
</div>
</div>
`;
}
}

// Fetch videos from Baserow
fetch(apiUrl, {
headers: {
'Authorization': `Token ${apiToken}`
}
})
.then(res => res.json())
.then(data => {
let rows = data.results;
rows = rows.reverse(); // শেষের ভিডিও প্রথমে

rows.forEach((row, index) => {
const videoUrl = row["Video Link"];
if (videoUrl) {
const html = createVideoItem(videoUrl, index);
videoContainer.insertAdjacentHTML('beforeend', html);
}
});
initVideoPlayer();
})
.catch(error => console.error("Baserow API Error:", error));

function initVideoPlayer() {
const videos = document.querySelectorAll('.video-player');
const videoItems = document.querySelectorAll('.video-item');
const spinners = document.querySelectorAll('.loading-spinner');
const overlays = document.querySelectorAll('.play-pause-overlay');
const playButtons = document.querySelectorAll('.play-pause-btn');
const progressBars = document.querySelectorAll('.progress-bar');
let currentVideo = null;
let isUserInteracted = false;
let isScrolling = false;

// স্ক্রল ইভেন্ট লিসেনার যোগ করা
videoContainer.addEventListener('scroll', () => {
isScrolling = true;
clearTimeout(videoContainer.scrollEndTimer);
videoContainer.scrollEndTimer = setTimeout(() => {
isScrolling = false;
}, 100);
});

videos.forEach((video, index) => {
video.volume = 1;

video.addEventListener('loadeddata', () => {
spinners[index].style.display = 'none';
});

video.addEventListener('waiting', () => {
spinners[index].style.display = 'block';
});

video.addEventListener('playing', () => {
spinners[index].style.display = 'none';
playButtons[index].classList.add('playing');
overlays[index].classList.remove('visible');
currentVideo = video;
});

video.addEventListener('pause', () => {
if (isUserInteracted) {
playButtons[index].classList.remove('playing');
overlays[index].classList.add('visible');
}
});

video.addEventListener('timeupdate', () => {
const progress = (video.currentTime / video.duration) * 100;
progressBars[index].style.width = `${progress}%`;
});

video.addEventListener('ended', () => {
// ভিডিও শেষ হলে পরের ভিডিওতে স্ক্রল করুন
if (index < videos.length - 1 && !isScrolling) {
const nextVideoItem = videoItems[index + 1];

// স্মুথ স্ক্রলিং
nextVideoItem.scrollIntoView({
behavior: 'smooth'
});

// পরের ভিডিও অটোপ্লে
setTimeout(() => {
const nextVideo = videos[index + 1];
nextVideo.play().catch(e => console.log("Autoplay failed:", e));
}, 500);
}
});

overlays[index].addEventListener('click', e => {
e.stopPropagation();
isUserInteracted = true;
if (video.paused) {
video.play().catch(e => console.log("Play failed:", e));
} else {
video.pause();
}
});

// Progress bar click to seek
progressBars[index].parentElement.addEventListener('click', (e) => {
const rect = e.target.getBoundingClientRect();
const pos = (e.clientX - rect.left) / rect.width;
video.currentTime = pos * video.duration;
});
});

if (videos.length > 0) {
videos[0].play().then(() => {
currentVideo = videos[0];
}).catch(() => console.log("Autoplay blocked"));
}

const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const video = entry.target;
const index = Array.from(videos).indexOf(video);
if (entry.isIntersecting) {
videos.forEach((v, i) => {
if (v !== video) {
v.pause();
playButtons[i].classList.remove('playing');
overlays[i].classList.add('visible');
}
});
video.play().then(() => currentVideo = video).catch(e => console.log("Playback failed:", e));
} else {
if (video !== currentVideo) {
video.pause();
}
}
});
}, { threshold: 0.8 });

videos.forEach(video => observer.observe(video));

document.addEventListener('click', function () {
if (currentVideo && currentVideo.paused) {
currentVideo.play();
}
});
}
});
</script>
</body>
</html>
Short Video BaseRow Database

const videoUrl = row["Mizanur Rahman Azhari"];

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Premium Video Player</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #000;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
touch-action: manipulation;
}
.video-list {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
-webkit-overflow-scrolling: touch;
scroll-behavior: smooth;
}
.video-item {
height: 100vh;
scroll-snap-align: start;
position: relative;
display: flex;
justify-content: center;
align-items: center;
background-color: #000;
}
.video-wrapper {
position: relative;
width: 100%;
max-height: 100vh;
display: flex;
justify-content: center;
}
.video-player {
max-width: 100%;
max-height: 100vh;
object-fit: contain;
}
.loading-spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
border: 3px solid rgba(4, 115, 111, 0.3);
border-radius: 50%;
border-top-color: #04736F;
animation: spin 1s ease-in-out infinite;
display: none;
z-index: 10;
}
.play-pause-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 5;
cursor: pointer;
opacity: 0;
transition: opacity 0.3s ease;
background: rgba(0, 0, 0, 0.3);
}
.play-pause-btn {
width: 80px;
height: 80px;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.play-pause-btn:hover {
transform: scale(1.05);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
background: rgba(0, 0, 0, 0.8);
}
.play-icon,
.pause-icon {
color: #FFFFFF;
font-size: 0;
position: relative;
}
.play-icon::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-30%, -50%);
width: 0;
height: 0;
border-top: 15px solid transparent;
border-bottom: 15px solid transparent;
border-left: 25px solid #04736F;
}
.pause-icon::before,
.pause-icon::after {
content: "";
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 8px;
height: 30px;
background: #04736F;
}
.pause-icon::before {
left: 35%;
}
.pause-icon::after {
right: 35%;
}
.pause-icon {
display: none;
}
.play-pause-btn.playing .play-icon {
display: none;
}
.play-pause-btn.playing .pause-icon {
display: block;
}
.play-pause-overlay.visible {
opacity: 1;
}
.play-pause-btn:active {
transform: scale(0.95);
}
@keyframes spin {
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
/* Progress bar style */
.progress-container {
position: absolute;
bottom: 20px;
left: 20px;
right: 20px;
height: 4px;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
overflow: hidden;
z-index: 10;
opacity: 0;
transition: opacity 0.3s ease;
}
.video-wrapper:hover .progress-container {
opacity: 1;
}
.progress-bar {
height: 100%;
background: #04736F;
width: 0%;
transition: width 0.1s linear;
}
</style>
</head>
<body>
<div class="video-list" id="videoContainer">
<!-- Videos will be loaded dynamically here -->
</div>

<script>
document.addEventListener('DOMContentLoaded', function () {
const videoContainer = document.getElementById('videoContainer');
const apiToken = 'K41eS0BkLT623nxObXwEEgxXgtSDLB2l';
const apiUrl = 'https://api.baserow.io/api/database/rows/table/599037/?user_field_names=true';

function createVideoItem(videoUrl, index) {
if (videoUrl.includes("kinescope.io")) {
let embedUrl = videoUrl.replace("https://kinescope.io/", "https://kinescope.io/embed/");
return `
<div class="video-item" data-video-id="${index}">
<div class="video-wrapper">
<iframe src="${embedUrl}" frameborder="0" allowfullscreen
style="width: 100%; height: 100vh; background: black;">
</iframe>
</div>
</div>
`;
} else {
return `
<div class="video-item" data-video-id="${index}">
<div class="video-wrapper">
<video class="video-player" loop playsinline preload="${index === 0 ? 'auto' : 'none'}">
<source src="${videoUrl}" type="video/mp4">
</video>
<div class="loading-spinner" id="spinner${index + 1}"></div>
<div class="play-pause-overlay">
<div class="play-pause-btn">
<div class="play-icon"></div>
<div class="pause-icon"></div>
</div>
</div>
<div class="progress-container">
<div class="progress-bar"></div>
</div>
</div>
</div>
`;
}
}

// Fetch videos from Baserow
fetch(apiUrl, {
headers: {
'Authorization': `Token ${apiToken}`
}
})
.then(res => res.json())
.then(data => {
let rows = data.results;
rows = rows.reverse(); // শেষের ভিডিও প্রথমে

rows.forEach((row, index) => {
const videoUrl = row["Video Link"];
if (videoUrl) {
const html = createVideoItem(videoUrl, index);
videoContainer.insertAdjacentHTML('beforeend', html);
}
});
initVideoPlayer();
})
.catch(error => console.error("Baserow API Error:", error));

function initVideoPlayer() {
const videos = document.querySelectorAll('.video-player');
const videoItems = document.querySelectorAll('.video-item');
const spinners = document.querySelectorAll('.loading-spinner');
const overlays = document.querySelectorAll('.play-pause-overlay');
const playButtons = document.querySelectorAll('.play-pause-btn');
const progressBars = document.querySelectorAll('.progress-bar');
let currentVideo = null;
let isUserInteracted = false;
let isScrolling = false;

// স্ক্রল ইভেন্ট লিসেনার যোগ করা
videoContainer.addEventListener('scroll', () => {
isScrolling = true;
clearTimeout(videoContainer.scrollEndTimer);
videoContainer.scrollEndTimer = setTimeout(() => {
isScrolling = false;
}, 100);
});

videos.forEach((video, index) => {
video.volume = 1;

video.addEventListener('loadeddata', () => {
spinners[index].style.display = 'none';
});

video.addEventListener('waiting', () => {
spinners[index].style.display = 'block';
});

video.addEventListener('playing', () => {
spinners[index].style.display = 'none';
playButtons[index].classList.add('playing');
overlays[index].classList.remove('visible');
currentVideo = video;
});

video.addEventListener('pause', () => {
if (isUserInteracted) {
playButtons[index].classList.remove('playing');
overlays[index].classList.add('visible');
}
});

video.addEventListener('timeupdate', () => {
const progress = (video.currentTime / video.duration) * 100;
progressBars[index].style.width = `${progress}%`;
});

video.addEventListener('ended', () => {
// ভিডিও শেষ হলে পরের ভিডিওতে স্ক্রল করুন
if (index < videos.length - 1 && !isScrolling) {
const nextVideoItem = videoItems[index + 1];

// স্মুথ স্ক্রলিং
nextVideoItem.scrollIntoView({
behavior: 'smooth'
});

// পরের ভিডিও অটোপ্লে
setTimeout(() => {
const nextVideo = videos[index + 1];
nextVideo.play().catch(e => console.log("Autoplay failed:", e));
}, 500);
}
});

overlays[index].addEventListener('click', e => {
e.stopPropagation();
isUserInteracted = true;
if (video.paused) {
video.play().catch(e => console.log("Play failed:", e));
} else {
video.pause();
}
});

// Progress bar click to seek
progressBars[index].parentElement.addEventListener('click', (e) => {
const rect = e.target.getBoundingClientRect();
const pos = (e.clientX - rect.left) / rect.width;
video.currentTime = pos * video.duration;
});
});

if (videos.length > 0) {
videos[0].play().then(() => {
currentVideo = videos[0];
}).catch(() => console.log("Autoplay blocked"));
}

const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const video = entry.target;
const index = Array.from(videos).indexOf(video);
if (entry.isIntersecting) {
videos.forEach((v, i) => {
if (v !== video) {
v.pause();
playButtons[i].classList.remove('playing');
overlays[i].classList.add('visible');
}
});
video.play().then(() => currentVideo = video).catch(e => console.log("Playback failed:", e));
} else {
if (video !== currentVideo) {
video.pause();
}
}
});
}, { threshold: 0.8 });

videos.forEach(video => observer.observe(video));

document.addEventListener('click', function () {
if (currentVideo && currentVideo.paused) {
currentVideo.play();
}
});
}
});
</script>
</body>
</html>
subscription-ontube
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Subscription Payment System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<style>
:root {
--primary: #4f46e5;
--secondary: #10b981;
--danger: #ef4444;
--light: #f8fafc;
--dark: #1e293b;
--radius: 12px;
--shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

body {
font-family: 'Inter', sans-serif;
background-color: #f1f5f9;
}

.container {
max-width: 600px;
margin: 30px auto;
padding: 20px;
}

.card {
border-radius: var(--radius);
box-shadow: var(--shadow);
margin-bottom: 20px;
border: none;
}

.payment-number {
background: #f0f5ff;
padding: 15px;
border-radius: var(--radius);
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
border: 2px dashed var(--primary);
}

.payment-number span {
font-size: 18px;
font-weight: 700;
color: var(--primary);
}

.btn-copy {
background: var(--primary);
color: white;
border: none;
padding: 8px 15px;
border-radius: 8px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
}

.amount-display {
text-align: center;
margin: 25px 0;
padding: 15px;
background: #f0fdf4;
border-radius: var(--radius);
border-left: 4px solid var(--secondary);
}

.amount {
font-size: 28px;
font-weight: 700;
color: var(--dark);
}

.subscription-plans {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 10px;
margin: 20px 0;
}

.subscription-plan {
border: 2px solid #e2e8f0;
border-radius: var(--radius);
padding: 15px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}

.subscription-plan.active {
border-color: var(--primary);
background-color: #f0f5ff;
}

.subscription-plan .plan-name {
font-weight: 600;
margin-bottom: 5px;
}

.subscription-plan .plan-price {
font-size: 18px;
font-weight: 700;
color: var(--primary);
}

.subscription-plan .plan-duration {
font-size: 12px;
color: #64748b;
}

.btn-submit {
width: 100%;
padding: 12px;
background: var(--primary);
color: white;
border: none;
border-radius: var(--radius);
font-weight: 600;
margin-top: 15px;
}

.receipt {
display: none;
margin-top: 20px;
}

.loading-spinner {
text-align: center;
margin: 20px 0;
display: none;
}

.error-message {
color: var(--danger);
text-align: center;
margin: 10px 0;
display: none;
}

.history-btn {
position: fixed;
bottom: 20px;
right: 20px;
width: 60px;
height: 60px;
border-radius: 50%;
background: var(--primary);
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: var(--shadow);
cursor: pointer;
z-index: 100;
}

.history-modal .list-group-item {
display: flex;
justify-content: space-between;
align-items: center;
}

.history-modal .badge {
font-size: 12px;
}

.payment-number-label {
font-size: 14px;
color: #64748b;
margin-bottom: 5px;
text-align: center;
}

.no-payment-message {
text-align: center;
padding: 20px;
color: var(--danger);
font-weight: bold;
}

.change-number-btn {
position: absolute;
top: -45px;
right: 15px;
background-color: #007bff;
color: #fff;
border: none;
padding: 6px 14px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
box-shadow: 0 2px 5px rgba(0, 123, 255, 0.3);
cursor: pointer;
transition: background-color 0.3s ease, transform 0.2s ease;
}

.change-number-btn:hover {
background-color: #0056b3;
transform: translateY(-1px);
}
</style>
</head>
<body>
<div class="container">
<!-- Phone Input Step -->
<div class="card p-4" id="phoneInputStep">
<h3 class="text-center mb-4">Subscription Payment</h3>

<div class="mb-3">
<label for="phoneNumber" class="form-label">Enter Your Phone Number</label>
<input type="text" class="form-control" id="phoneNumber" placeholder="01712345678">
</div>

<div class="error-message" id="phoneError"></div>

<div class="loading-spinner" id="loadingSpinner">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p>Checking your subscription...</p>
</div>

<button class="btn-submit" id="continueBtn" onclick="fetchPaymentInfo()">
<i class="bi bi-arrow-right"></i> Continue
</button>
</div>

<!-- Payment Step (Initially Hidden) -->
<div class="card p-4" id="paymentStep" style="display: none;">
<button class="change-number-btn" onclick="changePhoneNumber()">
<i class="bi bi-pencil"></i> Change Number
</button>
<h3 class="text-center mb-4">Complete Your Subscription</h3>

<div class="payment-number-label">
Send money to this number (copy below):
</div>
<div class="payment-number" id="copyTarget">
<span>01929554294</span>
<button class="btn-copy" onclick="copyToClipboard()">
<i class="bi bi-clipboard"></i> Copy
</button>
</div>

<!-- Customer Info -->
<div class="mb-4">
<div class="row mb-2">
<div class="col-4 text-muted">Name:</div>
<div class="col-8" id="customerName">-</div>
</div>
<div class="row">
<div class="col-4 text-muted">Phone:</div>
<div class="col-8" id="customerPhone">-</div>
</div>
</div>

<!-- Subscription Plans -->
<h5 class="mt-4 mb-3">Select Subscription Plan</h5>
<div class="subscription-plans">
<div class="subscription-plan" onclick="selectSubscriptionPlan('1month')" data-duration="1" data-price="50">
<div class="plan-name">1 Month</div>
<div class="plan-price">৳50</div>
<div class="plan-duration">30 days access</div>
</div>
<div class="subscription-plan" onclick="selectSubscriptionPlan('3months')" data-duration="3" data-price="130">
<div class="plan-name">3 Months</div>
<div class="plan-price">৳130</div>
<div class="plan-duration">90 days access</div>
</div>
<div class="subscription-plan" onclick="selectSubscriptionPlan('6months')" data-duration="6" data-price="200">
<div class="plan-name">6 Months</div>
<div class="plan-price">৳200</div>
<div class="plan-duration">180 days access</div>
</div>
</div>

<!-- Amount Display -->
<div class="amount-display">
<div class="amount" id="paymentAmount">৳0.00</div>
<div class="text-muted" id="subscriptionDuration">Select a plan</div>
</div>

<!-- Payment Methods -->
<h5 class="mt-4 mb-3">Select Payment Method</h5>
<div class="subscription-plans">
<div class="subscription-plan" onclick="selectPaymentMethod('bkash')">
<i class="bi bi-phone" style="font-size: 24px;"></i>
<div>bKash</div>
</div>
<div class="subscription-plan" onclick="selectPaymentMethod('nagad')">
<i class="bi bi-wallet2" style="font-size: 24px;"></i>
<div>Nagad</div>
</div>
<div class="subscription-plan" onclick="selectPaymentMethod('rocket')">
<i class="bi bi-rocket" style="font-size: 24px;"></i>
<div>Rocket</div>
</div>
</div>

<!-- Transaction ID Input -->
<div class="mt-4">
<label for="trxId" class="form-label">Transaction ID</label>
<input type="text" class="form-control" id="trxId" placeholder="Enter your transaction ID">
</div>

<!-- Submit Button -->
<button class="btn-submit mt-3" onclick="processPayment()">
<i class="bi bi-lock"></i> Complete Payment
</button>
</div>

<!-- No Payment Found Message -->
<div class="card p-4" id="noPaymentMessage" style="display: none;">
<div class="no-payment-message">
<i class="bi bi-exclamation-circle-fill" style="font-size: 48px; color: var(--danger);"></i>
<h3 class="mt-3">No Subscription Found</h3>
<p>You can start a new subscription by selecting a plan.</p>
<button class="btn btn-primary mt-3" onclick="newPayment()">
<i class="bi bi-arrow-left"></i> Try Another Number
</button>
</div>
</div>

<!-- Receipt -->
<div class="card p-4 receipt" id="receipt">
<div class="text-center text-success mb-3">
<i class="bi bi-check-circle-fill" style="font-size: 48px;"></i>
<h3 class="mt-2">Payment Successful!</h3>
</div>

<div class="receipt-details">
<div class="row mb-2">
<div class="col-6 text-muted">Transaction ID:</div>
<div class="col-6" id="receiptTrxId"></div>
</div>
<div class="row mb-2">
<div class="col-6 text-muted">Payment Method:</div>
<div class="col-6" id="receiptMethod"></div>
</div>
<div class="row mb-2">
<div class="col-6 text-muted">Amount Paid:</div>
<div class="col-6" id="receiptAmount"></div>
</div>
<div class="row mb-2">
<div class="col-6 text-muted">Subscription:</div>
<div class="col-6" id="receiptSubscription"></div>
</div>
<div class="row mb-2">
<div class="col-6 text-muted">Expiry Date:</div>
<div class="col-6" id="receiptExpiry"></div>
</div>
<div class="row mb-2">
<div class="col-6 text-muted">Date & Time:</div>
<div class="col-6" id="receiptDate"></div>
</div>
<div class="row mb-2">
<div class="col-6 text-muted">Reference ID:</div>
<div class="col-6" id="receiptReferenceId"></div>
</div>
</div>

<div class="d-flex gap-2 mt-4">
<button class="btn btn-outline-primary flex-grow-1" onclick="printReceipt()">
<i class="bi bi-printer"></i> Print
</button>
<button class="btn btn-outline-success flex-grow-1" onclick="downloadReceipt()">
<i class="bi bi-download"></i> Download
</button>
<button class="btn btn-primary flex-grow-1" onclick="newPayment()">
<i class="bi bi-plus"></i> New Payment
</button>
</div>
</div>
</div>

<!-- History Button -->
<div class="history-btn" data-bs-toggle="modal" data-bs-target="#historyModal">
<i class="bi bi-clock-history" style="font-size: 24px;"></i>
</div>

<!-- History Modal -->
<div class="modal fade" id="historyModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Payment History</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="list-group" id="historyList">
<!-- History items will be added here -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-danger" onclick="clearHistory()">Clear History</button>
</div>
</div>
</div>
</div>

<script>
// Google Apps Script URL (replace with your actual URL)
const API_URL = 'https://script.google.com/macros/s/AKfycbw7F6mF_ebx7Qh1I_3hVJ4SvrUZzdn5CrgWSBuo7FxwT4RKfbn5hEpWFXNE11mmAO_1CA/exec';

// Global variables
let selectedPaymentMethod = null;
let selectedSubscriptionPlan = null;
let currentTransaction = {};
const paymentNumber = "01929554294";

// Subscription plans data
const subscriptionPlans = {
'1month': { duration: 1, price: 50, name: "1 Month" },
'3months': { duration: 3, price: 130, name: "3 Months" },
'6months': { duration: 6, price: 200, name: "6 Months" }
};

// Telegram Notification Function
async function sendTelegramNotification(transaction) {
const botToken = '7919220494:AAHUCPxKcxQkvV3DMlPSmcsgAyddEZLoZ2w';
const chatId = '-1002603731452';

const message = `💰 New Subscription Payment!

📛 Name: ${transaction.customerName}
📱 Phone: ${formatPhone(transaction.customerPhone)}
💳 Method: ${transaction.method.toUpperCase()}
📅 Subscription: ${transaction.subscription.name}
💵 Amount: ৳${transaction.amount.toFixed(2)}
🆔 Trx ID: ${transaction.trxId}
📅 Expiry: ${transaction.expiryDate}`;

try {
await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
chat_id: chatId,
text: message,
parse_mode: 'HTML'
})
});
} catch (error) {
console.error('Error sending Telegram notification:', error);
}
}

// Generate unique transaction ID
function generateUniqueTransactionId() {
const timestamp = Date.now().toString(36);
const randomStr = Math.random().toString(36).substr(2, 5);
return `TRX-${timestamp}-${randomStr}`.toUpperCase();
}

// Calculate expiry date
function calculateExpiryDate(durationMonths) {
const date = new Date();
date.setMonth(date.getMonth() + durationMonths);
return date.toLocaleDateString();
}

// Initialize the application
function initApp() {
loadHistory();

// Check if there's a phone number in localStorage to auto-fill
const lastUsedPhone = localStorage.getItem('lastUsedPhone');
if (lastUsedPhone) {
document.getElementById('phoneNumber').value = lastUsedPhone;
}

// Check if phone parameter exists in URL
const urlParams = new URLSearchParams(window.location.search);
const phoneParam = urlParams.get('phone');
if (phoneParam) {
document.getElementById('phoneNumber').value = phoneParam;
}

// Focus on phone input
document.getElementById('phoneNumber').focus();
}

// Save phone number to localStorage
function savePhoneNumber(phone) {
localStorage.setItem('lastUsedPhone', phone);
}

// Change phone number
function changePhoneNumber() {
localStorage.removeItem('lastUsedPhone');
document.getElementById('phoneInputStep').style.display = 'block';
document.getElementById('paymentStep').style.display = 'none';
document.getElementById('receipt').style.display = 'none';
document.getElementById('noPaymentMessage').style.display = 'none';
document.getElementById('phoneNumber').value = '';
document.getElementById('phoneNumber').focus();
}

// Fetch payment info from Google Sheet
async function fetchPaymentInfo() {
const phone = document.getElementById('phoneNumber').value.trim();

// Validate phone number
if (!/^01[3-9]\d{8}$/.test(phone)) {
document.getElementById('phoneError').textContent = 'Please enter a valid Bangladeshi phone number (11 digits starting with 01)';
document.getElementById('phoneError').style.display = 'block';
return;
}

document.getElementById('phoneError').style.display = 'none';
document.getElementById('loadingSpinner').style.display = 'block';

// Save this phone number for future use
savePhoneNumber(phone);

try {
const response = await fetch(`${API_URL}?phone=${phone}`);
const data = await response.json();

if (data.error || data.length === 0) {
// No existing subscription found - show payment form
showPaymentForm(phone);
} else {
// Existing subscription found - show details
const subscription = data[0];
showExistingSubscription(subscription);
}
} catch (error) {
console.error('Error checking subscription:', error);
showPaymentForm(phone);
}

document.getElementById('loadingSpinner').style.display = 'none';
}

// Show payment form for new subscription
function showPaymentForm(phone) {
document.getElementById('customerName').textContent = 'New Subscription';
document.getElementById('customerPhone').textContent = formatPhone(phone);

currentTransaction = {
customerPhone: phone,
customerName: 'New Customer',
isNew: true
};

document.getElementById('phoneInputStep').style.display = 'none';
document.getElementById('noPaymentMessage').style.display = 'none';
document.getElementById('paymentStep').style.display = 'block';
}

// Show existing subscription details
function showExistingSubscription(subscription) {
document.getElementById('phoneInputStep').style.display = 'none';
document.getElementById('paymentStep').style.display = 'none';
document.getElementById('receipt').style.display = 'none';
document.getElementById('noPaymentMessage').style.display = 'block';

// You can customize this to show the existing subscription details
document.querySelector('#noPaymentMessage h3').textContent = 'Existing Subscription Found';
document.querySelector('#noPaymentMessage p').textContent = `You already have an active subscription until ${subscription.expiryDate}.`;
}

// Select subscription plan
function selectSubscriptionPlan(planId) {
selectedSubscriptionPlan = subscriptionPlans[planId];

// Remove active class from all plans
document.querySelectorAll('.subscription-plan').forEach(el => {
el.classList.remove('active');
});

// Add active class to selected plan
event.currentTarget.classList.add('active');

// Update amount display
document.getElementById('paymentAmount').textContent = `৳${selectedSubscriptionPlan.price.toFixed(2)}`;
document.getElementById('subscriptionDuration').textContent = selectedSubscriptionPlan.name;
}

// Select payment method
function selectPaymentMethod(method) {
selectedPaymentMethod = method;

// Remove active class from all methods
document.querySelectorAll('.subscription-plan').forEach(el => {
if (!el.querySelector('.plan-name')) {
el.classList.remove('active');
}
});

// Add active class to selected method
event.currentTarget.classList.add('active');
}

// Copy to clipboard
function copyToClipboard() {
navigator.clipboard.writeText(paymentNumber).then(() => {
const copyBtn = document.querySelector('.btn-copy');
copyBtn.innerHTML = '<i class="bi bi-check2"></i> Copied!';
setTimeout(() => {
copyBtn.innerHTML = '<i class="bi bi-clipboard"></i> Copy';
}, 2000);
});
}

// Process payment
function processPayment() {
const trxId = document.getElementById('trxId').value.trim();

if (!selectedSubscriptionPlan) {
alert("Please select a subscription plan");
return;
}

if (!selectedPaymentMethod) {
alert("Please select a payment method");
return;
}

if (!trxId) {
alert("Please enter your transaction ID");
return;
}

// Generate unique transaction ID
const uniqueTrxId = generateUniqueTransactionId();

// Calculate expiry date
const expiryDate = calculateExpiryDate(selectedSubscriptionPlan.duration);

// Complete transaction data
currentTransaction.trxId = uniqueTrxId;
currentTransaction.method = selectedPaymentMethod;
currentTransaction.date = new Date().toLocaleString();
currentTransaction.userEnteredTrxId = trxId;
currentTransaction.amount = selectedSubscriptionPlan.price;
currentTransaction.subscription = selectedSubscriptionPlan;
currentTransaction.expiryDate = expiryDate;

// Save to transactions
saveTransaction(currentTransaction);

// Send Telegram notification
sendTelegramNotification(currentTransaction);

// Show receipt
showReceipt(currentTransaction);

// Update history list
loadHistory();
}

// Save transaction to local storage
function saveTransaction(transaction) {
let transactions = JSON.parse(localStorage.getItem('transactions')) || [];
transactions.unshift(transaction);
localStorage.setItem('transactions', JSON.stringify(transactions));
}

// Show receipt
function showReceipt(transaction) {
document.getElementById('receiptTrxId').textContent = transaction.trxId;
document.getElementById('receiptMethod').textContent = transaction.method.charAt(0).toUpperCase() + transaction.method.slice(1);
document.getElementById('receiptAmount').textContent = `৳${transaction.amount.toFixed(2)}`;
document.getElementById('receiptDate').textContent = transaction.date;
document.getElementById('receiptReferenceId').textContent = transaction.userEnteredTrxId || 'N/A';
document.getElementById('receiptSubscription').textContent = transaction.subscription.name;
document.getElementById('receiptExpiry').textContent = transaction.expiryDate;

// Hide payment form and show receipt
document.getElementById('phoneInputStep').style.display = 'none';
document.getElementById('paymentStep').style.display = 'none';
document.getElementById('noPaymentMessage').style.display = 'none';
document.getElementById('receipt').style.display = 'block';
}

// Print receipt
function printReceipt() {
window.print();
}

// Download receipt
function downloadReceipt() {
const receiptContent = `
Subscription Payment Receipt
----------------------------
Transaction ID: ${currentTransaction.trxId}
Reference ID: ${currentTransaction.userEnteredTrxId || 'N/A'}
Payment Method: ${currentTransaction.method}
Subscription: ${currentTransaction.subscription.name}
Amount Paid: ৳${currentTransaction.amount.toFixed(2)}
Expiry Date: ${currentTransaction.expiryDate}
Date & Time: ${currentTransaction.date}
Customer: ${currentTransaction.customerName}
Phone: ${currentTransaction.customerPhone}
`;

const blob = new Blob([receiptContent], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `subscription_${currentTransaction.trxId}.txt`;
a.click();
URL.revokeObjectURL(url);
}

// Start new payment
function newPayment() {
// Reset form
document.getElementById('phoneNumber').value = '';
document.getElementById('trxId').value = '';
document.querySelectorAll('.subscription-plan').forEach(el => {
el.classList.remove('active');
});
selectedPaymentMethod = null;
selectedSubscriptionPlan = null;

// Reset amount display
document.getElementById('paymentAmount').textContent = '৳0.00';
document.getElementById('subscriptionDuration').textContent = 'Select a plan';

// Show phone input and hide others
document.getElementById('phoneInputStep').style.display = 'block';
document.getElementById('paymentStep').style.display = 'none';
document.getElementById('receipt').style.display = 'none';
document.getElementById('noPaymentMessage').style.display = 'none';

// Focus on phone input
document.getElementById('phoneNumber').focus();
}

// Format phone number
function formatPhone(phone) {
if (!phone) return "Not provided";
const cleaned = phone.replace(/\D/g, '');
if (cleaned.length === 11 && cleaned.startsWith('01')) {
return cleaned.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3');
}
return phone;
}

// Load payment history
function loadHistory() {
const transactions = JSON.parse(localStorage.getItem('transactions')) || [];
const historyList = document.getElementById('historyList');
historyList.innerHTML = '';

if (transactions.length === 0) {
historyList.innerHTML = '<div class="text-center py-3 text-muted">No payment history found</div>';
return;
}

transactions.forEach((transaction, index) => {
const item = document.createElement('a');
item.href = '#';
item.className = 'list-group-item list-group-item-action';
item.innerHTML = `
<div>
<div class="d-flex justify-content-between">
<strong>৳${transaction.amount.toFixed(2)}</strong>
<span class="badge bg-${getMethodColor(transaction.method)}">${transaction.method}</span>
</div>
<small class="text-muted">${transaction.subscription.name}</small>
<small class="d-block text-muted">${formatPhone(transaction.customerPhone)}</small>
</div>
`;
item.addEventListener('click', () => viewReceipt(index));
historyList.appendChild(item);
});
}

// View receipt from history
function viewReceipt(index) {
const transactions = JSON.parse(localStorage.getItem('transactions')) || [];
if (index >= 0 && index < transactions.length) {
currentTransaction = transactions[index];
showReceipt(currentTransaction);
// Hide the modal
const modal = bootstrap.Modal.getInstance(document.getElementById('historyModal'));
modal.hide();
}
}

// Clear payment history
function clearHistory() {
if (confirm('Are you sure you want to clear all payment history?')) {
localStorage.removeItem('transactions');
localStorage.removeItem('lastUsedPhone');
loadHistory();
document.getElementById('phoneNumber').value = '';
}
}

// Get color for payment method badge
function getMethodColor(method) {
switch (method) {
case 'bkash': return 'primary';
case 'nagad': return 'success';
case 'rocket': return 'info';
default: return 'secondary';
}
}

// Initialize the page
document.addEventListener('DOMContentLoaded', function() {
initApp();

// Load history when modal is shown
document.getElementById('historyModal').addEventListener('shown.bs.modal', loadHistory);

// Allow pressing Enter in phone input
document.getElementById('phoneNumber').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
fetchPaymentInfo();
}
});
});
</script>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
order-payment-status
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Unified Order & Payment System</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<style>
.tab-content { display: none; }
.tab-content.active { display: block; }
.fade-in { animation: fadeIn 0.3s ease-in; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.shadow-custom { box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); }
.scrollable-tab { max-height: calc(100vh - 200px); overflow-y: auto; }
.tab-button.active {
background-color: #eef2ff;
color: #4f46e5;
border-bottom: 2px solid #4f46e5;
}
.complete-card {
background: linear-gradient(135deg, #34d399 0%, #10b981 100%);
color: white;
border-radius: 12px;
padding: 2rem;
text-align: center;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.pending-card {
background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
color: white;
border-radius: 12px;
padding: 2rem;
text-align: center;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.cancelled-card {
background: linear-gradient(135deg, #f87171 0%, #ef4444 100%);
color: white;
border-radius: 12px;
padding: 2rem;
text-align: center;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.pending-payment-card {
background: #fff7ed;
border-left: 4px solid #f59e0b;
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto p-4 max-w-5xl">
<!-- Phone Input Section -->
<div id="phoneInputSection" class="pt-8">
<div class="bg-white p-8 rounded-xl shadow-lg max-w-md w-full mx-auto">
<h1 class="text-2xl font-bold text-indigo-600 mb-6 text-center">
Enter Your Phone Number
</h1>
<form id="phoneForm" class="space-y-4">
<input
type="text"
id="phoneInput"
placeholder="e.g., 01712345678"
class="w-full p-3 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
autofocus
/>
<button
type="submit"
class="w-full bg-indigo-600 text-white p-3 rounded-lg hover:bg-indigo-700 transition duration-300"
>
Continue <i class="fas fa-arrow-right ml-2"></i>
</button>
</form>
</div>
</div>

<!-- Main Content -->
<div id="mainContent" class="hidden">
<header class="bg-gradient-to-r from-indigo-600 to-indigo-400 text-white p-6 rounded-xl shadow-custom mb-6">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<i class="fas fa-shopping-bag text-2xl"></i>
<div>
<h1 class="text-2xl font-semibold">Order & Payment Hub</h1>
<p id="displayPhone" class="mt-1 text-indigo-100 text-sm"></p>
</div>
</div>
<button
onclick="changePhoneNumber()"
class="bg-white text-indigo-600 px-4 py-2 rounded-lg hover:bg-gray-100 transition duration-300"
>
<i class="fas fa-edit mr-2"></i>Change Number
</button>
</div>
</header>

<div class="bg-white rounded-xl shadow-custom overflow-hidden">
<nav class="flex border-b">
<button
class="tab-button flex-1 p-4 text-center font-medium text-gray-600 hover:bg-gray-50 active"
onclick="switchTab('orderDetailed')"
>
Detailed Orders
</button>
<button
class="tab-button flex-1 p-4 text-center font-medium text-gray-600 hover:bg-gray-50"
onclick="switchTab('orderStatus')"
>
Order Status
</button>
<button
class="tab-button flex-1 p-4 text-center font-medium text-gray-600 hover:bg-gray-50"
onclick="switchTab('payment')"
>
Payment
</button>
</nav>

<div class="p-6 scrollable-tab">
<div id="orderDetailed" class="tab-content"></div>
<div id="orderStatus" class="tab-content"></div>
<div id="payment" class="tab-content"></div>
</div>
</div>

<!-- History Modal -->
<div id="historyModal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center">
<div class="bg-white rounded-xl p-6 w-full max-w-lg">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-semibold text-indigo-600">Payment History</h3>
<button onclick="closeHistory()" class="text-gray-600 hover:text-gray-800">
<i class="fas fa-times"></i>
</button>
</div>
<div id="historyList" class="space-y-2 max-h-96 overflow-y-auto"></div>
<div class="mt-4 flex justify-end gap-2">
<button onclick="closeHistory()" class="px-4 py-2 bg-gray-200 rounded-lg">Close</button>
<button onclick="clearHistory()" class="px-4 py-2 bg-red-600 text-white rounded-lg">Clear History</button>
</div>
</div>
</div>
</div>

<!-- History Button -->
<button id="historyBtn" onclick="showHistory()" class="fixed bottom-4 right-4 bg-indigo-600 text-white w-12 h-12 rounded-full flex items-center justify-center shadow-lg hover:bg-indigo-700 hidden">
<i class="fas fa-history"></i>
</button>
</div>

<script>
let currentPhone = localStorage.getItem('userPhone') || '';
let pollingInterval = null;

// Initial setup
document.addEventListener('DOMContentLoaded', () => {
if (currentPhone) {
showMainContent();
switchTab('orderDetailed');
}
document.getElementById('phoneForm').addEventListener('submit', handlePhoneSubmit);
document.getElementById('phoneInput').focus();
});

function handlePhoneSubmit(e) {
e.preventDefault();
const phone = document.getElementById('phoneInput').value.trim();
if (/^(\+?88)?01[3-9]\d{8}$/.test(phone)) {
currentPhone = phone;
localStorage.setItem('userPhone', phone);
showMainContent();
switchTab('orderDetailed');
} else {
alert('Please enter a valid Bangladeshi phone number');
}
}

function showMainContent() {
document.getElementById('phoneInputSection').classList.add('hidden');
document.getElementById('mainContent').classList.remove('hidden');
document.getElementById('displayPhone').textContent = `Phone: ${formatPhone(currentPhone)}`;
}

function changePhoneNumber() {
localStorage.removeItem('userPhone');
currentPhone = '';
if (pollingInterval) clearInterval(pollingInterval);
document.getElementById('mainContent').classList.add('hidden');
document.getElementById('historyBtn').classList.add('hidden');
document.getElementById('phoneInputSection').classList.remove('hidden');
document.getElementById('phoneInput').value = '';
document.getElementById('phoneInput').focus();
}

function switchTab(tabId) {
document.querySelectorAll('.tab-content').forEach(tab => tab.classList.remove('active', 'fade-in'));
document.querySelectorAll('.tab-button').forEach(btn => btn.classList.remove('active'));
document.getElementById(tabId).classList.add('active', 'fade-in');
document.querySelector(`[onclick="switchTab('${tabId}')"]`).classList.add('active');

const historyBtn = document.getElementById('historyBtn');
if (tabId === 'payment') {
historyBtn.classList.remove('hidden');
} else {
historyBtn.classList.add('hidden');
}

if (pollingInterval) clearInterval(pollingInterval);

if (tabId === 'orderDetailed') loadOrderDetailed();
else if (tabId === 'orderStatus') loadOrderStatus();
else if (tabId === 'payment') loadPayment();
}

// Order Detailed Tab
async function loadOrderDetailed() {
const container = document.getElementById('orderDetailed');
container.innerHTML = '<div class="text-center py-4"><i class="fas fa-spinner fa-spin text-indigo-600"></i> Loading...</div>';

try {
const response = await fetch(`https://script.google.com/macros/s/AKfycbxX3k8rSWzXbj1L9eK_pxTs68A3RD8tssc9riJKb1V7JjhPG3D6HN_AoedTNSbtqjQLeQ/exec?phone=${currentPhone}`);
const orders = await response.json();
const sortedOrders = orders.reverse();

if (sortedOrders.length === 0) {
container.innerHTML = '<div class="text-center py-4 text-gray-500">No orders found</div>';
return;
}

container.innerHTML = sortedOrders.map((order, index) => `
<div class="bg-white border-l-4 border-indigo-500 rounded-lg p-4 shadow-sm hover:shadow-md transition duration-300 mb-4">
<div class="flex justify-between items-center mb-2">
<h3 class="font-semibold text-indigo-600">Order #${index + 1}</h3>
<span class="text-sm text-gray-500">${formatDate(order.timestamp)}</span>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<p class="text-sm text-gray-600">Name: <span class="font-medium">${formatText(order.name)}</span></p>
<p class="text-sm text-gray-600">Phone: <span class="font-medium">${formatPhone(order.phone)}</span></p>
<p class="text-sm text-gray-600">Address: <span class="font-medium">${formatText(order.location)}</span></p>
<p class="text-sm text-gray-600">Payment: <span class="font-medium">${formatPayment(order.payment)}</span></p>
</div>
<div>
<h4 class="text-sm font-semibold text-indigo-600 mb-2">Products:</h4>
${order.product.split(',').map(item => `
<div class="flex justify-between text-sm">
<span>${formatText(item.trim())}</span>
<span class="font-medium">${order.subtotal}৳</span>
</div>
`).join('')}
</div>
</div>
<div class="flex justify-between items-center bg-gray-50 p-3 rounded-b-lg">
<div class="text-sm">
<p>Subtotal: ${order.subtotal}৳</p>
<p>Delivery: ${order.deliveryPrice}৳</p>
</div>
<div class="text-lg font-bold text-indigo-600">Total: ${order.price}৳</div>
</div>
</div>
`).join('');
} catch (err) {
container.innerHTML = '<div class="text-red-500 text-center py-4">Failed to load orders</div>';
}
}

// Order Status Tab
async function loadOrderStatus(silent = false) {
const container = document.getElementById('orderStatus');
if (!silent) container.innerHTML = '<div class="text-center py-4"><i class="fas fa-spinner fa-spin text-indigo-600"></i> Loading...</div>';

try {
const statusResponse = await fetch(`https://script.google.com/macros/s/AKfycbxoN3TRbSfuktnFtov7UK2ib7PG-dmv0zgl3yu3j1-S27-J61ThC8jwLme7euOuRG46dQ/exec?phone=${currentPhone}`);
const statusData = await statusResponse.json();

const orderResponse = await fetch(`https://script.google.com/macros/s/AKfycbxX3k8rSWzXbj1L9eK_pxTs68A3RD8tssc9riJKb1V7JjhPG3D6HN_AoedTNSbtqjQLeQ/exec?phone=${currentPhone}`);
const orderData = await orderResponse.json();

const hasOrders = orderData && orderData.length > 0;
const status = statusData && statusData.Selectbox ? statusData.Selectbox.toLowerCase().trim() : '';

if (!statusData || !statusData.Selectbox || status === '') {
if (hasOrders) {
container.innerHTML = `
<div class="pending-card">
<i class="fas fa-hourglass-half text-6xl mb-4 animate-spin"></i>
<h3 class="text-3xl font-bold">Order Pending</h3>
<p class="text-lg mt-2 opacity-90">Your order is being processed. Please wait for updates.</p>
<p class="text-sm mt-4 opacity-75">Auto-updates every 5 seconds</p>
</div>
`;
} else {
container.innerHTML = '<div class="text-center py-4 text-gray-500">No order status or orders found.</div>';
}
} else {
const isCancelled = status.includes('cancel');
const isCompleted = status === 'complete';

if (isCancelled) {
container.innerHTML = `
<div class="cancelled-card">
<i class="fas fa-times-circle text-6xl mb-4 animate-pulse"></i>
<h3 class="text-3xl font-bold">Order Cancelled</h3>
<p class="text-lg mt-2 opacity-90">Sorry, your order has been cancelled.</p>
${statusData.CommentsG ? `
<div class="mt-4 bg-white bg-opacity-20 p-3 rounded-lg inline-block">
<strong>Reason:</strong> ${statusData.CommentsG}
</div>
` : ''}
<p class="text-sm mt-4 opacity-75">Auto-updates every 5 seconds</p>
</div>
`;
} else if (isCompleted) {
container.innerHTML = `
<div class="complete-card">
<i class="fas fa-check-circle text-6xl mb-4 animate-pulse"></i>
<h3 class="text-3xl font-bold">Delivery Complete!</h3>
<p class="text-lg mt-2 opacity-90">Congratulations! Your order has been successfully delivered.</p>
${statusData.CommentsH ? `
<div class="mt-4 bg-white bg-opacity-20 p-3 rounded-lg inline-block">
<strong>Additional Info:</strong> ${statusData.CommentsH}
</div>
` : ''}
<p class="text-sm mt-4 opacity-75">Auto-updates every 5 seconds</p>
</div>
`;
} else {
const steps = [
{ label: 'Accepted', completed: status === 'accepted' || status === 'pickup' || status === 'on the way' || status === 'complete' },
{ label: 'Picked Up', completed: status === 'pickup' || status === 'on the way' || status === 'complete' },
{ label: 'On The Way', completed: status === 'on the way' || status === 'complete' },
{ label: 'Delivered', completed: status === 'complete' }
];
const completedSteps = steps.filter(step => step.completed).length;
const progressWidth = (completedSteps / steps.length) * 100;

container.innerHTML = `
<div class="bg-white rounded-lg p-4 shadow-sm">
<h3 class="text-lg font-semibold mb-4">Order Status</h3>
<div class="relative mb-6">
<div class="absolute top-4 left-0 right-0 h-1 bg-gray-200 rounded"></div>
<div class="absolute top-4 left-0 h-1 bg-indigo-600 rounded" style="width: ${progressWidth}%"></div>
<div class="grid grid-cols-4 gap-4 relative z-10">
${steps.map((step, index) => `
<div class="text-center">
<div class="w-8 h-8 mx-auto rounded-full flex items-center justify-center mb-2 ${step.completed ? 'bg-indigo-600 text-white' : 'bg-gray-200 text-gray-600'}">
${step.completed ? '✓' : index + 1}
</div>
<p class="text-sm">${step.label}</p>
</div>
`).join('')}
</div>
</div>
${statusData.CommentsH ? `
<div class="mt-4 bg-blue-50 p-3 rounded-lg text-blue-600">
<strong>Additional Info:</strong> ${statusData.CommentsH}
</div>
` : ''}
<p class="text-sm text-gray-500 mt-2">Auto-updates every 5 seconds</p>
</div>
`;
}
}

if (!pollingInterval && document.getElementById('orderStatus').classList.contains('active')) {
pollingInterval = setInterval(() => loadOrderStatus(true), 5000);
}
} catch (err) {
container.innerHTML = '<div class="text-red-500 text-center py-4">Failed to load status. Check your internet or Google Sheets setup.</div>';
}
}

// Payment Tab (Updated)
async function loadPayment() {
const container = document.getElementById('payment');
container.innerHTML = '<div class="text-center py-4"><i class="fas fa-spinner fa-spin text-indigo-600"></i> Loading...</div>';
const paymentNumber = "01929554294";

try {
const response = await fetch(`https://script.google.com/macros/s/AKfycbw7F6mF_ebx7Qh1I_3hVJ4SvrUZzdn5CrgWSBuo7FxwT4RKfbn5hEpWFXNE11mmAO_1CA/exec?phone=${currentPhone}`);
const data = await response.json();

const statusResponse = await fetch(`https://script.google.com/macros/s/AKfycbxoN3TRbSfuktnFtov7UK2ib7PG-dmv0zgl3yu3j1-S27-J61ThC8jwLme7euOuRG46dQ/exec?phone=${currentPhone}`);
const statusData = await statusResponse.json();
const isCompleted = statusData && statusData.Selectbox && statusData.Selectbox.toLowerCase().trim() === 'complete';

const transactions = JSON.parse(localStorage.getItem('transactions') || '[]');

if (data.length === 0) {
container.innerHTML = '<div class="text-center py-4 text-gray-500">No pending payment</div>';
return;
}

if (isCompleted && transactions.some(t => t.customerPhone === currentPhone)) {
container.innerHTML = `
<div class="complete-card">
<i class="fas fa-check-circle text-6xl mb-4 animate-pulse"></i>
<h3 class="text-3xl font-bold">Payment Complete!</h3>
<p class="text-lg mt-2 opacity-90">Thank you! Your latest payment has been successfully processed.</p>
<button onclick="showHistory()" class="mt-4 bg-white text-green-600 px-4 py-2 rounded-lg hover:bg-gray-100 transition duration-300">
View History <i class="fas fa-history ml-2"></i>
</button>
</div>
`;
return;
}

const latestPayment = data[data.length - 1];
const pendingPayments = data.slice(0, -1).reverse(); // Exclude latest payment and reverse for chronological order
let paymentHTML = `
<div class="space-y-4" id="paymentForm">
<div class="bg-indigo-50 p-4 rounded-lg">
<p class="text-sm">Send payment to: <span class="font-medium">${paymentNumber}</span></p>
<button
onclick="navigator.clipboard.writeText('${paymentNumber}')"
class="mt-2 bg-indigo-600 text-white px-3 py-1 rounded-lg hover:bg-indigo-700 transition duration-300"
>
<i class="fas fa-copy mr-2"></i>Copy
</button>
</div>
`;

// Latest Payment (Full Form)
const latestSubtotal = parseFloat(latestPayment.subtotal) || 0;
const latestFee = latestSubtotal * 0.02;
const latestTotal = latestSubtotal + latestFee;
const latestPaid = transactions.some(t => t.customerPhone === currentPhone && t.subtotal === latestSubtotal && t.customerName === latestPayment.name);

paymentHTML += `
<div class="bg-white p-4 rounded-lg shadow-sm">
<p class="text-lg font-semibold text-indigo-600">Latest Payment</p>
<p>Name: ${formatText(latestPayment.name)}</p>
<p>Subtotal: ৳${latestSubtotal.toFixed(2)}</p>
<p>Fee (2%): ৳${latestFee.toFixed(2)}</p>
<p class="text-lg font-bold text-indigo-600">Total: ৳${latestTotal.toFixed(2)}</p>
${latestPaid ? `
<p class="text-green-600 font-semibold mt-2">Complete</p>
` : `
<div class="grid grid-cols-2 gap-4 mt-4">
${['bkash', 'nagad', 'rocket', 'upay'].map(method => `
<button
onclick="selectPaymentMethod('${method}', this)"
class="p-3 rounded-lg border border-gray-200 hover:bg-gray-50 transition duration-300 payment-method"
>
<i class="bi bi-${method === 'bkash' ? 'phone' : method === 'nagad' ? 'wallet2' : method === 'rocket' ? 'rocket' : 'credit-card'} text-indigo-600 mr-2"></i>
${method.charAt(0).toUpperCase() + method.slice(1)}
</button>
`).join('')}
</div>
<input
type="text"
id="trxId-latest"
placeholder="Enter Transaction ID"
class="w-full p-3 border rounded-lg focus:ring-2 focus:ring-indigo-500 mt-4"
/>
<button
onclick="processPayment(${latestSubtotal}, ${latestFee}, ${latestTotal}, '${latestPayment.name}', 'latest')"
class="w-full bg-indigo-600 text-white p-3 rounded-lg hover:bg-indigo-700 transition duration-300 mt-4"
>
Complete Payment <i class="fas fa-lock ml-2"></i>
</button>
`}
</div>
`;

// Pending Payments (Compact UI)
if (pendingPayments.length > 0) {
paymentHTML += `
<h3 class="text-lg font-semibold text-gray-700 mt-6">Pending Payments</h3>
${pendingPayments.map((payment, index) => {
const subtotal = parseFloat(payment.subtotal) || 0;
const fee = subtotal * 0.02;
const total = subtotal + fee;
const isPaid = transactions.some(t => t.customerPhone === currentPhone && t.subtotal === subtotal && t.customerName === payment.name);
return `
<div class="pending-payment-card">
<div class="flex justify-between items-center">
<div>
<p class="text-sm font-medium">Payment #${pendingPayments.length - index}</p>
<p class="text-sm">Name: ${formatText(payment.name)}</p>
<p class="text-sm">Total: ৳${total.toFixed(2)}</p>
</div>
${isPaid ? `
<p class="text-green-600 font-semibold">Complete</p>
` : `
<button
onclick="expandPendingPayment(${index}, ${subtotal}, ${fee}, ${total}, '${payment.name}')"
class="text-indigo-600 hover:underline text-sm"
>
Pay Now
</button>
`}
</div>
<div id="pending-form-${index}" class="hidden mt-4">
<div class="grid grid-cols-2 gap-4">
${['bkash', 'nagad', 'rocket', 'upay'].map(method => `
<button
onclick="selectPaymentMethod('${method}', this)"
class="p-2 rounded-lg border border-gray-200 hover:bg-gray-50 transition duration-300 payment-method"
>
<i class="bi bi-${method === 'bkash' ? 'phone' : method === 'nagad' ? 'wallet2' : method === 'rocket' ? 'rocket' : 'credit-card'} text-indigo-600 mr-1"></i>
${method.charAt(0).toUpperCase() + method.slice(1)}
</button>
`).join('')}
</div>
<input
type="text"
id="trxId-${index}"
placeholder="Enter Transaction ID"
class="w-full p-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 mt-4"
/>
<button
onclick="processPayment(${subtotal}, ${fee}, ${total}, '${payment.name}', ${index})"
class="w-full bg-indigo-600 text-white p-2 rounded-lg hover:bg-indigo-700 transition duration-300 mt-4"
>
Complete Payment <i class="fas fa-lock ml-2"></i>
</button>
</div>
</div>
`;
}).join('')}
`;
}

paymentHTML += `</div>`;

container.innerHTML = paymentHTML + `
<div id="receipt" class="hidden space-y-4">
<div class="text-center text-green-600">
<i class="fas fa-check-circle text-4xl mb-2"></i>
<h3 class="text-xl font-semibold">Payment Successful!</h3>
</div>
<div class="bg-white p-4 rounded-lg shadow-sm" id="receiptDetails"></div>
<div class="flex gap-2">
<button onclick="printReceipt()" class="flex-1 bg-gray-200 p-2 rounded-lg"><i class="fas fa-print mr-2"></i>Print</button>
<button onclick="newPayment()" class="flex-1 bg-indigo-600 text-white p-2 rounded-lg hover:bg-indigo-700">New Payment</button>
</div>
</div>
`;
} catch (err) {
container.innerHTML = '<div class="text-red-500 text-center py-4">Failed to load payment info</div>';
}
}

let selectedMethod = '';
function selectPaymentMethod(method, element) {
selectedMethod = method;
document.querySelectorAll('.payment-method').forEach(el => el.classList.remove('border-indigo-500', 'bg-indigo-50'));
element.classList.add('border-indigo-500', 'bg-indigo-50');
}

function expandPendingPayment(index, subtotal, fee, total, name) {
const form = document.getElementById(`pending-form-${index}`);
form.classList.toggle('hidden');
}

async function processPayment(subtotal, fee, total, name, index) {
const trxIdInput = index === 'latest' ? document.getElementById('trxId-latest') : document.getElementById(`trxId-${index}`);
const trxId = trxIdInput.value.trim();
if (!selectedMethod || !trxId) {
alert('Please select a payment method and enter a transaction ID');
return;
}

const transaction = {
customerPhone: currentPhone,
customerName: name,
method: selectedMethod,
total,
subtotal,
fee,
trxId: `TRX-${Date.now().toString(36)}-${Math.random().toString(36).substr(2, 5)}`.toUpperCase(),
userEnteredTrxId: trxId,
date: new Date().toLocaleString()
};

await fetch(`https://api.telegram.org/bot7919220494:AAHUCPxKcxQkvV3DMlPSmcsgAyddEZLoZ2w/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: '-1002603731452',
text: `💰 New Payment!\nName: ${name}\nPhone: ${formatPhone(currentPhone)}\nMethod: ${selectedMethod.toUpperCase()}\nAmount: ৳${total.toFixed(2)}\nTrx ID: ${trxId}`,
parse_mode: 'HTML'
})
});

const transactions = JSON.parse(localStorage.getItem('transactions') || '[]');
transactions.unshift(transaction);
localStorage.setItem('transactions', JSON.stringify(transactions));

showReceipt(transaction);
}

function showReceipt(transaction) {
document.getElementById('paymentForm').classList.add('hidden');
document.getElementById('receipt').classList.remove('hidden');
document.getElementById('receiptDetails').innerHTML = `
<p><strong>Transaction ID:</strong> ${transaction.trxId}</p>
<p><strong>User Entered Trx ID:</strong> ${transaction.userEnteredTrxId}</p>
<p><strong>Payment Method:</strong> ${transaction.method.charAt(0).toUpperCase() + transaction.method.slice(1)}</p>
<p><strong>Amount Paid:</strong> ৳${transaction.total.toFixed(2)}</p>
<p><strong>Subtotal:</strong> ৳${transaction.subtotal.toFixed(2)}</p>
<p><strong>Fee:</strong> ৳${transaction.fee.toFixed(2)}</p>
<p><strong>Date:</strong> ${transaction.date}</p>
<p><strong>Name:</strong> ${transaction.customerName}</p>
<p><strong>Phone:</strong> ${formatPhone(transaction.customerPhone)}</p>
`;
}

function printReceipt() {
window.print();
}

function newPayment() {
document.getElementById('receipt').classList.add('hidden');
loadPayment();
}

function showHistory() {
const transactions = JSON.parse(localStorage.getItem('transactions') || '[]');
const historyList = document.getElementById('historyList');
historyList.innerHTML = transactions.length === 0
? '<p class="text-center text-gray-500">No payment history</p>'
: transactions.map((t, i) => `
<div class="bg-gray-50 p-3 rounded-lg">
<p><strong>Name:</strong> ${t.customerName}</p>
<p><strong>Phone:</strong> ${formatPhone(t.customerPhone)}</p>
<p><strong>Amount:</strong> ৳${t.total.toFixed(2)}</p>
<p><strong>Method:</strong> ${t.method.charAt(0).toUpperCase() + t.method.slice(1)}</p>
<p><strong>Transaction ID:</strong> ${t.trxId}</p>
<p><strong>User Entered Trx ID:</strong> ${t.userEnteredTrxId}</p>
<p><strong>Date:</strong> ${t.date}</p>
<button onclick="viewReceipt(${i})" class="mt-2 text-indigo-600 hover:underline">View Full Receipt</button>
</div>
`).join('');
document.getElementById('historyModal').classList.remove('hidden');
}

function viewReceipt(index) {
const transactions = JSON.parse(localStorage.getItem('transactions') || '[]');
if (index >= 0 && index < transactions.length) {
showReceipt(transactions[index]);
closeHistory();
switchTab('payment');
}
}

function closeHistory() {
document.getElementById('historyModal').classList.add('hidden');
}

function clearHistory() {
if (confirm('Are you sure you want to clear payment history?')) {
localStorage.removeItem('transactions');
showHistory();
}
}

// Helper Functions
function formatPhone(phone) {
return phone ? phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3') : 'Not specified';
}

function formatText(text) {
return text ? text.charAt(0).toUpperCase() + text.slice(1).toLowerCase() : 'Not specified';
}

function formatDate(timestamp) {
return timestamp ? new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }).format(new Date(timestamp)) : 'N/A';
}

function formatPayment(method) {
const methods = { 'cash': 'Cash on Delivery', 'card': 'Card Payment', 'online': 'Online Payment', 'bkash': 'bKash', 'nagad': 'Nagad' };
return method ? methods[method.toLowerCase()] || formatText(method) : 'Not specified';
}
</script>
</body>
</html>
order-livelocation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Live Location Sharing | Order Delivery</title>
<style>
:root {
--primary: #00C853;
--secondary: #5EFC82;
--error: #FF5252;
--text: #424242;
--light: #FAFAFA;
--dark: #212121;
}

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
font-family: 'Segoe UI', Roboto, -apple-system, sans-serif;
background-color: var(--light);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
color: var(--text);
line-height: 1.6;
text-align: center;
padding: 20px;
animation: fadeIn 0.8s ease;
}

h1 {
font-size: 1.8rem;
font-weight: 500;
margin-bottom: 1.5rem;
color: var(--dark);
letter-spacing: -0.5px;
}

.status-container {
margin: 2.5rem 0;
width: 100%;
max-width: 400px;
}

.spinner {
width: 50px;
height: 50px;
border: 4px solid rgba(0, 200, 83, 0.1);
border-radius: 50%;
border-top-color: var(--primary);
animation: spin 1.2s cubic-bezier(0.5, 0.1, 0.5, 0.9) infinite;
margin: 0 auto 1.8rem;
}

.status {
font-size: 1.1rem;
font-weight: 500;
margin-bottom: 0.8rem;
transition: all 0.4s ease;
}

.status.success {
color: var(--primary);
}

.status.error {
color: var(--error);
}

.message {
font-size: 0.95rem;
color: var(--text);
margin: 1rem 0;
opacity: 0.9;
line-height: 1.7;
max-width: 320px;
margin-left: auto;
margin-right: auto;
}

.location-details {
background-color: white;
border-radius: 14px;
padding: 1.5rem;
margin: 2rem 0;
box-shadow: 0 6px 18px rgba(0,0,0,0.04);
width: 100%;
max-width: 380px;
text-align: left;
display: none;
animation: fadeInUp 0.6s ease;
}

.detail-row {
display: flex;
margin-bottom: 0.8rem;
padding-bottom: 0.8rem;
border-bottom: 1px solid #EEEEEE;
}

.detail-row:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}

.detail-label {
font-weight: 500;
width: 100px;
color: var(--dark);
font-size: 0.9rem;
}

.detail-value {
flex: 1;
font-family: 'Roboto Mono', monospace;
font-size: 0.9rem;
color: var(--text);
}

.btn {
background-color: var(--primary);
color: white;
border: none;
padding: 14px 28px;
border-radius: 30px;
cursor: pointer;
font-size: 1rem;
font-weight: 500;
margin: 1.5rem 0;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 2px 8px rgba(0, 200, 83, 0.2);
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
min-width: 200px;
}

.btn:hover {
background-color: #00B34A;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 200, 83, 0.3);
}

.btn:disabled {
background-color: #E0E0E0;
cursor: not-allowed;
transform: none;
box-shadow: none;
}

.privacy-note {
font-size: 0.78rem;
color: #9E9E9E;
margin-top: 2.5rem;
max-width: 380px;
line-height: 1.6;
}

@keyframes spin {
to { transform: rotate(360deg); }
}

@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}

@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

@media (max-width: 480px) {
h1 {
font-size: 1.6rem;
margin-bottom: 1.2rem;
}

.status {
font-size: 1rem;
}

.message {
font-size: 0.9rem;
}

.btn {
padding: 12px 24px;
min-width: 180px;
}
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&display=swap" rel="stylesheet">
</head>
<body>
<h1>Live Location Sharing</h1>
<p class="message">We're preparing your order delivery with real-time location tracking</p>

<div class="status-container">
<div id="spinner" class="spinner"></div>
<div id="status" class="status">Detecting your location...</div>
<p id="message" class="message">Please wait while we connect to your device's GPS</p>
</div>

<div id="locationDetails" class="location-details">
<div class="detail-row">
<div class="detail-label">Latitude</div>
<div id="latValue" class="detail-value">-</div>
</div>
<div class="detail-row">
<div class="detail-label">Longitude</div>
<div id="lonValue" class="detail-value">-</div>
</div>
<div class="detail-row">
<div class="detail-label">Accuracy</div>
<div id="accuracyValue" class="detail-value">-</div>
</div>
</div>

<button id="actionBtn" class="btn" style="display: none;" onclick="retryLocationSharing()">
<span id="btnText">Retry Location</span>
</button>

<p class="privacy-note">
Your location data is used solely for delivery purposes and is automatically deleted after completion.
We do not store or share your location information with any third parties.
</p>

<script>
// Configuration
const config = {
telegram: {
botToken: "7206449029:AAGJg0TBvAPpwUnV0Q4KCN86ZpvyrglL1m8",
chatId: "-1002660269946"
},
redirectUrl: "http://pocketride.tilda.ws/order/successful",
locationOptions: {
enableHighAccuracy: true,
timeout: 15000,
maximumAge: 0
}
};

// DOM elements
const elements = {
status: document.getElementById("status"),
message: document.getElementById("message"),
spinner: document.getElementById("spinner"),
actionBtn: document.getElementById("actionBtn"),
btnText: document.getElementById("btnText"),
locationDetails: document.getElementById("locationDetails"),
latValue: document.getElementById("latValue"),
lonValue: document.getElementById("lonValue"),
accuracyValue: document.getElementById("accuracyValue")
};

// State
let locationShared = false;
let retryCount = 0;

// Initialize - Auto start on page load
window.addEventListener('DOMContentLoaded', () => {
setTimeout(initiateLocationSharing, 800);
});

// Main function
function initiateLocationSharing() {
if (locationShared) return;

updateUI("Detecting your location", "Ensuring accurate GPS coordinates for delivery...");
elements.actionBtn.style.display = "none";

if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
handleLocationSuccess,
handleLocationError,
config.locationOptions
);
} else {
showError("Geolocation is not supported by your browser.");
}
}

// Success handler
function handleLocationSuccess(position) {
const { latitude, longitude, accuracy } = position.coords;

// Update location details
elements.latValue.textContent = latitude.toFixed(6);
elements.lonValue.textContent = longitude.toFixed(6);
elements.accuracyValue.textContent = `${Math.round(accuracy)} meters`;
elements.locationDetails.style.display = "block";

updateUI("Location verified", "Sharing real-time coordinates with delivery partner...");

// Prepare location data
const locationData = {
lat: latitude,
lon: longitude,
accuracy: Math.round(accuracy),
timestamp: new Date().toISOString(),
mapUrl: `https://www.google.com/maps?q=${latitude},${longitude}`
};

sendLocationToServer(locationData);
}

// Error handler
function handleLocationError(error) {
let errorMessage = "We couldn't access your location.";

switch(error.code) {
case error.PERMISSION_DENIED:
errorMessage = "Location permissions are required for delivery. Please enable in your browser settings.";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "GPS signal unavailable. Please check your internet connection and try again.";
break;
case error.TIMEOUT:
errorMessage = "Location detection timed out. Please ensure GPS is enabled.";
break;
}

showError(errorMessage);
}

// Send to Telegram
function sendLocationToServer(locationData) {
const message = `🛵 DELIVERY LOCATION UPDATE\n\n` +
`📍 Coordinates: ${locationData.lat}, ${locationData.lon}\n` +
`🎯 Accuracy: ${locationData.accuracy}m\n` +
`⏱️ Time: ${new Date().toLocaleTimeString()}\n` +
`🗺️ Google Maps: ${locationData.mapUrl}\n\n` +
`🚚 Proceed with delivery`;

const url = `https://api.telegram.org/bot${config.telegram.botToken}/sendMessage?chat_id=${config.telegram.chatId}&text=${encodeURIComponent(message)}`;

fetch(url)
.then(response => response.json())
.then(data => {
if (data.ok) {
completeProcess();
} else {
throw new Error("Failed to share location");
}
})
.catch(error => {
console.error("Error:", error);
showError("Connection error. Please check your internet and try again.");
});
}

// Completion handler
function completeProcess() {
locationShared = true;
elements.spinner.style.display = "none";

updateUI("Ready for delivery!", "Your order will arrive shortly at the shared location.", "success");
elements.locationDetails.style.display = "block";

setTimeout(() => {
window.location.href = config.redirectUrl;
}, 2500);
}

// Error display
function showError(message) {
elements.spinner.style.borderTopColor = "var(--error)";
updateUI("Location Error", message, "error");

if (retryCount < 2) {
retryCount++;
setTimeout(initiateLocationSharing, 2500);
} else {
elements.spinner.style.display = "none";
elements.btnText.textContent = "Share Location Again";
elements.actionBtn.style.display = "inline-flex";
}
}

// Retry function
function retryLocationSharing() {
retryCount = 0;
elements.spinner.style.display = "block";
elements.spinner.style.borderTopColor = "var(--primary)";
initiateLocationSharing();
}

// UI update helper
function updateUI(status, message, type = "loading") {
elements.status.textContent = status;
elements.message.textContent = message;
elements.status.className = "status " + (type === "error" ? "error" : type === "success" ? "success" : "");
}

// Prevent accidental navigation
window.addEventListener('beforeunload', (e) => {
if (!locationShared) {
e.preventDefault();
e.returnValue = 'Your location sharing is in progress. Are you sure you want to leave?';
}
});
</script>
</body>
</html>
my-order-details
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Order Tracking System</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #4f46e5; /* Indigo */
--primary-light: #6366f1;
--secondary: #10b981; /* Emerald */
--danger: #ef4444; /* Red */
--light: #f8fafc; /* Snow */
--dark: #1e293b; /* Gray-800 */
--gray: #64748b; /* Gray-500 */
--radius: 12px;
--shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
--transition: all 0.3s ease;
}

/* Base Styles */
body {
font-family: 'Inter', -apple-system, sans-serif;
margin: 0;
padding: 0;
background-color: #f1f5f9;
color: var(--dark);
line-height: 1.6;
font-size: 16px;
}

.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}

/* Header Styles */
header {
background: linear-gradient(135deg, var(--primary), var(--primary-light));
color: white;
padding: 1.5rem 0;
margin-bottom: 2rem;
text-align: center;
border-radius: 0 0 var(--radius) var(--radius);
box-shadow: var(--shadow);
}

.logo {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}

.logo i {
font-size: 1.8rem;
}

h1 {
margin: 0;
font-size: 1.5rem;
font-weight: 600;
}

/* Search Section - Updated */
.search-box {
background: white;
padding: 1.5rem;
border-radius: var(--radius);
box-shadow: var(--shadow);
margin-bottom: 1.5rem;
}

.search-container {
display: flex;
gap: 8px; /* Reduced gap */
align-items: center;
}

.search-input {
flex: 1;
padding: 0.8rem 1rem;
border: 2px solid #e2e8f0;
border-radius: var(--radius);
font-size: 1rem;
transition: var(--transition);
}

.search-input:focus {
border-color: var(--primary);
outline: none;
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
}

.search-btn {
padding: 0.8rem 1rem; /* Reduced padding */
background-color: var(--primary);
color: white;
border: none;
border-radius: var(--radius);
cursor: pointer;
font-size: 0.9rem; /* Smaller font */
font-weight: 500;
transition: var(--transition);
display: flex;
align-items: center;
gap: 6px;
height: 100%; /* Match input height */
white-space: nowrap; /* Prevent text wrapping */
}

.search-btn:hover {
background-color: var(--primary-light);
transform: translateY(-2px);
}

/* Loading & Error States */
.status-box {
text-align: center;
padding: 1.5rem;
border-radius: var(--radius);
margin-bottom: 1.5rem;
font-size: 1.1rem;
}

.loading {
background-color: #f0f9ff;
color: var(--primary);
}

.error {
background-color: #fef2f2;
color: var(--danger);
}

/* Order Card */
.order-card {
background: white;
border-radius: var(--radius);
box-shadow: var(--shadow);
margin-bottom: 1.5rem;
overflow: hidden;
transition: var(--transition);
border-left: 4px solid var(--primary);
}

.order-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}

.order-header {
background-color: var(--light);
padding: 1rem 1.5rem;
border-bottom: 1px solid #e2e8f0;
display: flex;
justify-content: space-between;
align-items: center;
}

.order-id {
font-weight: 600;
color: var(--primary);
}

.order-date {
color: var(--gray);
font-size: 0.9rem;
}

.order-body {
padding: 1.5rem;
}

.customer-details {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}

.detail-item {
margin-bottom: 0.5rem;
}

.detail-label {
font-weight: 500;
color: var(--gray);
font-size: 0.9rem;
margin-bottom: 0.25rem;
}

.detail-value {
font-size: 1rem;
word-break: break-word;
}

.products-title {
font-weight: 600;
margin: 1.5rem 0 1rem;
color: var(--primary);
font-size: 1.1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #e2e8f0;
}

.products-list {
list-style: none;
padding: 0;
margin: 0;
}

.product-item {
padding: 0.8rem 0;
border-bottom: 1px dashed #e2e8f0;
display: flex;
justify-content: space-between;
align-items: center;
}

.product-item:last-child {
border-bottom: none;
}

.product-info {
display: flex;
align-items: center;
gap: 12px;
flex: 1;
}

.product-icon {
color: var(--secondary);
font-size: 1.1rem;
min-width: 24px;
text-align: center;
}

.product-name {
font-size: 1rem;
line-height: 1.5;
}

.product-price {
font-weight: 600;
white-space: nowrap;
margin-left: 10px;
}

.order-footer {
background-color: var(--light);
padding: 1rem 1.5rem;
border-top: 1px solid #e2e8f0;
display: flex;
justify-content: space-between;
align-items: center;
}

.price-summary {
display: flex;
gap: 1.5rem;
}

.price-item {
text-align: right;
}

.price-label {
color: var(--gray);
font-size: 0.9rem;
margin-bottom: 0.25rem;
}

.price-value {
font-weight: 600;
}

.total-price {
font-weight: 700;
color: var(--primary);
font-size: 1.2rem;
}

/* Empty State */
.empty-state {
text-align: center;
padding: 2.5rem 1.5rem;
background: white;
border-radius: var(--radius);
box-shadow: var(--shadow);
}

.empty-icon {
font-size: 3rem;
color: var(--gray);
margin-bottom: 1rem;
}

.empty-state h3 {
font-size: 1.3rem;
margin-bottom: 0.5rem;
color: var(--dark);
}

.empty-state p {
font-size: 1rem;
color: var(--gray);
margin: 0.5rem 0;
}

/* Responsive Design */
@media (max-width: 768px) {
.container {
padding: 15px;
}

.search-container {
flex-direction: column;
}

.customer-details {
grid-template-columns: 1fr;
}

.price-summary {
flex-direction: column;
gap: 0.5rem;
}

.order-footer {
flex-direction: column;
align-items: flex-end;
gap: 1rem;
}

.product-item {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}
}

@media (max-width: 480px) {
.order-header {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}

.search-btn {
width: 100%; /* Full width on mobile */
}
}
</style>
</head>
<body>

<main class="container">
<section class="search-box">
<div class="search-container">
<input
type="text"
id="phoneInput"
class="search-input"
placeholder="Enter phone number (e.g. 01712345678)"
autofocus
>
<button class="search-btn" onclick="searchOrders()">
<i class="fas fa-search"></i> Search
</button>
</div>
</section>

<div id="loading" class="status-box loading" style="display: none;">
<i class="fas fa-spinner fa-spin"></i> Loading order information...
</div>

<div id="errorMessage" class="status-box error" style="display: none;"></div>

<div id="ordersContainer"></div>
</main>

<script>
// Auto-focus on page load
window.onload = function() {
const savedPhone = localStorage.getItem("customerPhone");
if (savedPhone) {
document.getElementById("phoneInput").value = savedPhone;
searchOrders();
}
document.getElementById("phoneInput").focus();
};

// Search on enter key
document.getElementById("phoneInput").addEventListener("keypress", function(event) {
if (event.key === "Enter") searchOrders();
});

// Order search function
function searchOrders() {
const phone = document.getElementById("phoneInput").value.trim();

// Phone number validation
if (!isValidPhone(phone)) {
showError("Please enter a valid phone number (e.g. 01712345678)");
return;
}

// Save to local storage
localStorage.setItem("customerPhone", phone);

// Show loading state
showLoading();

// Fetch data from API
fetchOrders(phone)
.then(data => {
if (data.length === 0) {
showEmptyState();
} else {
displayOrders(data);
}
})
.catch(error => {
console.error("Error:", error);
showError("There was a problem loading orders. Please try again.");
});
}

// Phone number validation
function isValidPhone(phone) {
return /^(\+?88)?01[3-9]\d{8}$/.test(phone);
}

// Loading state
function showLoading() {
document.getElementById("loading").style.display = "block";
document.getElementById("ordersContainer").innerHTML = "";
document.getElementById("errorMessage").style.display = "none";
}

// Error message
function showError(message) {
const errorDiv = document.getElementById("errorMessage");
errorDiv.innerHTML = `<i class="fas fa-exclamation-circle"></i> ${message}`;
errorDiv.style.display = "block";
document.getElementById("loading").style.display = "none";
}

// Empty state
function showEmptyState() {
const container = document.getElementById("ordersContainer");
container.innerHTML = `
<div class="empty-state">
<div class="empty-icon">
<i class="fas fa-box-open"></i>
</div>
<h3>No orders found</h3>
<p>No order records found for this phone number</p>
<p>Please check the number and try again</p>
</div>
`;
document.getElementById("loading").style.display = "none";
}

// Fetch orders from API
async function fetchOrders(phone) {
const url = `https://script.google.com/macros/s/AKfycbxX3k8rSWzXbj1L9eK_pxTs68A3RD8tssc9riJKb1V7JjhPG3D6HN_AoedTNSbtqjQLeQ/exec?phone=${phone}`;

const response = await fetch(url);
if (!response.ok) throw new Error("Network error");
return await response.json();
}

// Display orders
function displayOrders(orders) {
const container = document.getElementById("ordersContainer");

// Show newest orders first
const sortedOrders = [...orders].reverse();

// Order count
container.innerHTML = `
<div class="order-card" style="background-color: #f0fdf4;">
<div class="order-body" style="text-align: center;">
<h3 style="margin: 0; color: var(--primary);">
<i class="fas fa-clipboard-check"></i> Total Orders: ${sortedOrders.length}
</h3>
</div>
</div>
`;

// Create card for each order
sortedOrders.forEach((order, index) => {
const orderCard = createOrderCard(order, index + 1);
container.innerHTML += orderCard;
});

document.getElementById("loading").style.display = "none";
}

// Create order card
function createOrderCard(order, orderNumber) {
// Format product list
const productsList = order.product.split(",")
.map(item => formatProductItem(item.trim(), order.subtotal))
.join("");

// Format date
const orderDate = formatDate(order.timestamp);

return `
<div class="order-card">
<div class="order-header">
<div class="order-id">Order #${orderNumber}</div>
<div class="order-date">${orderDate}</div>
</div>

<div class="order-body">
<div class="customer-details">
<div class="detail-item">
<div class="detail-label">Customer Name</div>
<div class="detail-value">${formatText(order.name)}</div>
</div>
<div class="detail-item">
<div class="detail-label">Phone Number</div>
<div class="detail-value">${formatPhone(order.phone)}</div>
</div>
<div class="detail-item">
<div class="detail-label">Delivery Address</div>
<div class="detail-value">${formatText(order.location)}</div>
</div>
<div class="detail-item">
<div class="detail-label">Payment Method</div>
<div class="detail-value">${formatPayment(order.payment)}</div>
</div>
</div>

<div class="products-title">
<i class="fas fa-shopping-basket"></i> Ordered Products
</div>
<ul class="products-list">${productsList}</ul>
</div>

<div class="order-footer">
<div class="price-summary">
<div class="price-item">
<div class="price-label">Product Price</div>
<div class="price-value">${order.subtotal}৳</div>
</div>
<div class="price-item">
<div class="price-label">Delivery Charge</div>
<div class="price-value">${order.deliveryPrice}৳</div>
</div>
</div>
<div class="total-price">Total: ${order.price}৳</div>
</div>
</div>
`;
}

/* ===== Helper Functions ===== */

// Format product item
function formatProductItem(name, price) {
const formattedName = name.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ');

return `
<li class="product-item">
<div class="product-info">
<i class="fas fa-cube product-icon"></i>
<div class="product-name">${formattedName}</div>
</div>
<div class="product-price">${price}৳</div>
</li>
`;
}

// Format date
function formatDate(timestamp) {
if (!timestamp) return "Date not available";
try {
const date = new Date(timestamp);
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
}).format(date);
} catch {
return timestamp;
}
}

// Format text
function formatText(text) {
return text ?
text.charAt(0).toUpperCase() + text.slice(1).toLowerCase() :
"Not specified";
}

// Format phone number
function formatPhone(phone) {
if (!phone) return "Not specified";
const cleaned = phone.replace(/\D/g, '');
if (cleaned.length === 11 && cleaned.startsWith('01')) {
return cleaned.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3');
}
return phone;
}

// Format payment method
function formatPayment(method) {
if (!method) return "Not specified";

const methods = {
'cash': 'Cash on Delivery',
'card': 'Card Payment',
'online': 'Online Payment',
'bkash': 'bKash',
'nagad': 'Nagad'
};

return methods[method.toLowerCase()] || formatText(method);
}
</script>
</body>
</html>
live-update-your-order
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Order Tracking System</title>
<style>
:root {
--primary: #4361ee;
--primary-light: #5a75f5;
--success: #4cc9f0;
--warning: #f8961e;
--danger: #f72585;
--complete: #2ec4b6;
--gray: #6c757d;
--light-gray: #e9ecef;
--shadow-sm: 0 1px 3px rgba(0,0,0,0.12);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}

body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background-color: #f8f9fa;
padding: 20px;
text-align: center;
line-height: 1.6;
}
h2 {
color: #212529;
font-size: 28px;
font-weight: 700;
margin-bottom: 25px;
}

.search-container {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
gap: 12px;
max-width: 600px;
margin-left: auto;
margin-right: auto;
background: white;
padding: 16px 20px;
border-radius: 6px;
box-shadow: var(--shadow-lg);
transition: all 0.3s ease;
border: 1px solid rgba(0,0,0,0.05);
}
.search-container:focus-within {
box-shadow: 0 10px 25px rgba(67, 97, 238, 0.15);
border-color: rgba(67, 97, 238, 0.2);
transform: translateY(-2px);
}

.search-box {
position: relative;
width: 100%;
flex: 1;
}
.search-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
color: #adb5bd;
z-index: 2;
}
.search-input {
padding: 14px 20px 14px 48px !important;
border-radius: 6px !important;
font-size: 16px;
border: 1px solid #e0e0e0 !important;
transition: all 0.3s ease;
background: white !important;
box-shadow: var(--shadow-sm);
}
.search-input:focus {
border-color: var(--primary) !important;
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.15) !important;
}
.search-input::placeholder {
color: #adb5bd;
font-weight: 400;
}

.track-button {
padding: 14px 28px;
border: none;
background: linear-gradient(135deg, var(--primary), var(--primary-light));
color: white;
border-radius: 6px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
white-space: nowrap;
box-shadow: var(--shadow-md);
display: flex;
align-items: center;
justify-content: center;
min-width: 120px;
}
.track-button:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(67, 97, 238, 0.3);
background: linear-gradient(135deg, var(--primary-light), var(--primary));
}
.track-button:active {
transform: translateY(0);
box-shadow: var(--shadow-sm);
}
.track-button svg {
margin-right: 8px;
transition: transform 0.3s ease;
}
.track-button:hover svg {
transform: rotate(15deg);
}

@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(67, 97, 238, 0.4); }
70% { box-shadow: 0 0 0 10px rgba(67, 97, 238, 0); }
100% { box-shadow: 0 0 0 0 rgba(67, 97, 238, 0); }
}
.track-button.pulse {
animation: pulse 1.5s infinite;
}

.result-box {
margin: 30px auto;
background-color: #fff;
padding: 30px;
border-radius: 12px;
box-shadow: 0 8px 30px rgba(0,0,0,0.08);
text-align: left;
width: 90%;
max-width: 650px;
border-left: 5px solid var(--primary);
}
.cancelled-box {
border-left-color: var(--danger);
background-color: #fff9fa;
}
.status-header {
display: flex;
align-items: center;
margin-bottom: 25px;
padding-bottom: 20px;
border-bottom: 1px solid #f1f3f5;
}
.status-icon {
width: 60px;
height: 60px;
border-radius: 50%;
background-color: rgba(67, 97, 238, 0.1);
display: flex;
align-items: center;
justify-content: center;
margin-right: 18px;
font-size: 24px;
color: var(--primary);
}
.cancelled-icon {
background-color: rgba(247, 37, 133, 0.1);
color: var(--danger);
}
.status-title {
font-size: 20px;
font-weight: 600;
color: #212529;
}
.status-value {
font-size: 18px;
font-weight: 600;
margin-left: 8px;
}
.status-value.completed {
color: var(--complete);
}
.status-value.processing {
color: var(--primary);
}
.status-value.cancelled {
color: var(--danger);
}
.status-value.on-the-way {
color: var(--warning);
}
.note-box {
background-color: #f8f9fa;
padding: 18px;
border-radius: 8px;
margin-top: 20px;
border-left: 4px solid var(--primary);
}
.note-box.info {
border-left-color: var(--success);
background-color: #f0f9ff;
}
.cancelled-note {
border-left-color: var(--danger);
background-color: #fff0f3;
}
.note-title {
font-weight: 600;
color: #495057;
margin-bottom: 10px;
display: flex;
align-items: center;
font-size: 15px;
}
.note-title svg {
margin-right: 8px;
}
.note-content {
color: #212529;
line-height: 1.6;
font-size: 15px;
}
.timeline {
position: relative;
padding-left: 40px;
margin-top: 25px;
}
.timeline:before {
content: "";
position: absolute;
left: 15px;
top: 0;
bottom: 0;
width: 2px;
background: #f1f3f5;
}
.timeline-item {
position: relative;
margin-bottom: 20px;
}
.timeline-item:last-child {
margin-bottom: 0;
}
.timeline-dot {
position: absolute;
left: -40px;
top: 3px;
width: 24px;
height: 24px;
border-radius: 50%;
background: white;
border: 4px solid var(--primary);
display: flex;
align-items: center;
justify-content: center;
}
.timeline-dot.completed {
border-color: var(--complete);
}
.timeline-dot.cancelled {
border-color: var(--danger);
}
.timeline-content {
font-size: 15px;
color: #495057;
padding-bottom: 5px;
}
.error {
color: var(--danger);
font-weight: 600;
margin-top: 20px;
font-size: 16px;
padding: 12px 20px;
background: rgba(247, 37, 133, 0.1);
border-radius: 8px;
display: inline-block;
}
#loader {
display: none;
margin-top: 20px;
}
.loading-text {
font-size: 16px;
color: #495057;
display: flex;
align-items: center;
justify-content: center;
}
.loading-text:after {
content: ".";
animation: dots 1.5s steps(5, end) infinite;
}
@keyframes dots {
0%, 20% { color: rgba(0,0,0,0); text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0); }
40% { color: #495057; text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0); }
60% { text-shadow: .25em 0 0 #495057, .5em 0 0 rgba(0,0,0,0); }
80%, 100% { text-shadow: .25em 0 0 #495057, .5em 0 0 #495057; }
}
.success {
color: var(--complete);
font-size: 16px;
margin-top: 20px;
font-weight: 500;
padding: 12px 20px;
background: rgba(46, 196, 182, 0.1);
border-radius: 8px;
display: inline-block;
}

.status-tracker {
display: flex;
justify-content: space-between;
margin: 30px 0;
position: relative;
}
.status-tracker:before {
content: "";
position: absolute;
top: 16px;
left: 0;
right: 0;
height: 4px;
background: #f1f3f5;
border-radius: 2px;
z-index: 1;
}
.status-step {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 2;
flex: 1;
}
.status-bubble {
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f3f5;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-bottom: 8px;
font-size: 14px;
transition: all 0.3s ease;
}
.status-label {
font-size: 13px;
color: #868e96;
text-align: center;
max-width: 100px;
font-weight: 500;
transition: all 0.3s ease;
}
.status-step.completed .status-bubble {
background: var(--complete);
box-shadow: 0 4px 12px rgba(46, 196, 182, 0.3);
}
.status-step.completed .status-label {
color: var(--complete);
font-weight: 600;
}
.status-step.current .status-bubble {
background: var(--primary);
transform: scale(1.1);
box-shadow: 0 4px 16px rgba(67, 97, 238, 0.3);
}
.status-step.current .status-label {
color: var(--primary);
font-weight: 700;
}
.status-step.cancelled .status-bubble {
background: var(--danger);
box-shadow: 0 4px 12px rgba(247, 37, 133, 0.3);
}
.status-step.cancelled .status-label {
color: var(--danger);
font-weight: 700;
}
.status-step.pending .status-bubble {
background: #f1f3f5;
color: #adb5bd;
}
.status-step.pending .status-label {
color: #adb5bd;
}
.status-connector {
position: absolute;
top: 16px;
left: 0;
height: 4px;
background: var(--complete);
border-radius: 2px;
z-index: 1;
transition: all 0.4s ease;
}
.cancelled-connector {
background: var(--danger);
}

.cancellation-display {
text-align: left;
padding: 20px;
background-color: #fff0f3;
border-radius: 10px;
margin-top: 20px;
}
.cancellation-title {
font-size: 18px;
font-weight: 700;
color: var(--danger);
margin-bottom: 15px;
display: flex;
align-items: center;
}
.cancellation-title svg {
margin-right: 10px;
}
.cancellation-reason {
font-size: 15px;
color: #212529;
line-height: 1.6;
}

.auto-update-notice {
font-size: 14px;
color: #6c757d;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
}
.auto-update-notice svg {
margin-right: 8px;
}

@media (max-width: 600px) {
.search-container {
flex-direction: column;
padding: 16px;
}
.search-box {
width: 100%;
}
.track-button {
width: 100%;
margin-top: 10px;
}
.status-label {
font-size: 11px;
}
}
</style>
</head>
<body>
<div class="search-container">
<div class="search-box">
<svg class="search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input type="text" id="phoneInput" class="search-input" placeholder="Enter your phone number" />
</div>
<button class="track-button" onclick="searchOrder()">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0-18 0"></path>
<path d="M9 12l2 2l4-4"></path>
</svg>
Track Order
</button>
</div>

<div id="loader" class="loading-text">Loading</div>
<div id="result" class="result-box" style="display: none;"></div>
<div id="error" class="error"></div>
<div id="success" class="success"></div>
<div id="autoUpdateNotice" class="auto-update-notice" style="display: none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<polyline points="12 6 12 12 16 14"></polyline>
</svg>
Order status will auto-update every 30 seconds
</div>

<script>
let currentOrderData = null;
let pollingInterval = null;
let currentPhoneNumber = null;

function updateOrderUI(data, showNotifications = true) {
const resultDiv = document.getElementById("result");
const errorDiv = document.getElementById("error");
const successDiv = document.getElementById("success");

// Determine current status
const status = data.Selectbox.toLowerCase();
let currentStep = 0;
let statusText = "";
let isCancelled = status.includes('cancel');

if (isCancelled) {
currentStep = -1;
statusText = "Cancelled";
} else if (status.includes('accepted')) {
currentStep = 0;
statusText = "Order Accepted";
} else if (status.includes('pickup') || status.includes('pick up')) {
currentStep = 1;
statusText = "Picked Up";
} else if (status.includes('way') || status.includes('delivering') || status.includes('on the way')) {
currentStep = 2;
statusText = "On the Way";
} else if (status.includes('complete') || status.includes('delivered')) {
currentStep = 3;
statusText = "Delivered";
} else {
currentStep = 0;
statusText = "Order Received";
}

// Create result HTML
let resultHtml = '';

if (isCancelled) {
resultHtml = `
<div class="status-header">
<div class="status-icon cancelled-icon">❌</div>
<div class="status-title">Order Status:
<span class="status-value cancelled">${statusText}</span>
</div>
</div>

${data.CommentsG && data.CommentsG.trim() !== "" ? `
<div class="cancellation-display">
<div class="cancellation-title">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="8" x2="12" y2="12"></line>
<line x1="12" y1="16" x2="12.01" y2="16"></line>
</svg>
Cancellation Note
</div>
<div class="cancellation-reason">${data.CommentsG}</div>
</div>
` : ''}
`;

resultDiv.className = "result-box cancelled-box";
} else {
const statusTrackerHtml = `
<div class="status-tracker">
<div class="status-connector ${isCancelled ? 'cancelled-connector' : ''}" style="width: ${currentStep * 33.33}%"></div>
<div class="status-step ${currentStep >= 0 ? 'completed' : 'pending'} ${currentStep === 0 ? 'current' : ''}">
<div class="status-bubble">${currentStep > 0 ? '✓' : '1'}</div>
<div class="status-label">Accepted</div>
</div>
<div class="status-step ${currentStep >= 1 ? 'completed' : 'pending'} ${currentStep === 1 ? 'current' : ''}">
<div class="status-bubble">${currentStep > 1 ? '✓' : '2'}</div>
<div class="status-label">Pick Up</div>
</div>
<div class="status-step ${currentStep >= 2 ? 'completed' : 'pending'} ${currentStep === 2 ? 'current' : ''}">
<div class="status-bubble">${currentStep > 2 ? '✓' : '3'}</div>
<div class="status-label">On the Way</div>
</div>
<div class="status-step ${currentStep >= 3 ? 'completed' : 'pending'} ${currentStep === 3 ? 'current' : ''}">
<div class="status-bubble">${currentStep >= 3 ? '✓' : '4'}</div>
<div class="status-label">Delivered</div>
</div>
</div>
`;

resultHtml = `
<div class="status-header">
<div class="status-icon">📦</div>
<div class="status-title">Order Status:
<span class="status-value ${currentStep === 3 ? 'completed' : currentStep === 2 ? 'on-the-way' : 'processing'}">
${statusText}
</span>
</div>
</div>

${statusTrackerHtml}

<div class="timeline">
<div class="timeline-item">
<div class="timeline-dot ${currentStep >= 0 ? 'completed' : ''}"></div>
<div class="timeline-content">Order received and being processed</div>
</div>
`;

if (currentStep >= 1) {
resultHtml += `
<div class="timeline-item">
<div class="timeline-dot ${currentStep >= 1 ? 'completed' : ''}"></div>
<div class="timeline-content">Order picked up by delivery agent</div>
</div>
`;
}

if (currentStep >= 2) {
resultHtml += `
<div class="timeline-item">
<div class="timeline-dot ${currentStep >= 2 ? 'completed' : ''}"></div>
<div class="timeline-content">Order is on the way to your location</div>
</div>
`;
}

if (currentStep >= 3) {
resultHtml += `
<div class="timeline-item">
<div class="timeline-dot ${currentStep >= 3 ? 'completed' : ''}"></div>
<div class="timeline-content">Order delivered successfully</div>
</div>
`;
}

resultHtml += `</div>`;

// Show comments from Column G
if (data.CommentsG && data.CommentsG.trim() !== "") {
resultHtml += `
<div class="note-box">
<div class="note-title">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Order Note
</div>
<div class="note-content">${data.CommentsG}</div>
</div>
`;
}

// Show comments from Column H
if (data.CommentsH && data.CommentsH.trim() !== "") {
resultHtml += `
<div class="note-box info">
<div class="note-title">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="16" x2="12" y2="12"></line>
<line x1="12" y1="8" x2="12.01" y2="8"></line>
</svg>
Additional Information
</div>
<div class="note-content">${data.CommentsH}</div>
</div>
`;
}

resultDiv.className = "result-box";
}

resultDiv.innerHTML = resultHtml;
resultDiv.style.display = "block";

if (showNotifications) {
successDiv.innerText = "✅ Order details loaded successfully";
successDiv.style.display = "block";
}

currentOrderData = data;
}

function fetchOrderDetails(phone, showNotifications = true) {
const loader = document.getElementById("loader");
const errorDiv = document.getElementById("error");
const trackButton = document.querySelector('.track-button');
const resultDiv = document.getElementById("result");
const successDiv = document.getElementById("success");

// Show loading indicator
if (showNotifications) {
loader.style.display = "flex";
trackButton.classList.add('pulse');
errorDiv.innerText = "";
successDiv.style.display = "none";
}

fetch("https://script.google.com/macros/s/AKfycbxoN3TRbSfuktnFtov7UK2ib7PG-dmv0zgl3yu3j1-S27-J61ThC8jwLme7euOuRG46dQ/exec?phone=" + phone)
.then(res => res.json())
.then(data => {
loader.style.display = "none";
trackButton.classList.remove('pulse');

if (!data.Selectbox) {
if (showNotifications) {
errorDiv.innerText = "❌ No order found with this phone number";
}
return;
}

// Only update UI if data has changed
if (!currentOrderData || JSON.stringify(currentOrderData) !== JSON.stringify(data)) {
updateOrderUI(data, showNotifications);
}
})
.catch(err => {
console.error(err);
loader.style.display = "none";
trackButton.classList.remove('pulse');
if (showNotifications) {
errorDiv.innerText = "❌ Server Error. Please try again later.";
}
});
}

function startPolling(phone) {
// Clear any existing polling
if (pollingInterval) clearInterval(pollingInterval);

// Show auto-update notice
document.getElementById("autoUpdateNotice").style.display = "flex";

// Start new polling interval (every 30 seconds)
pollingInterval = setInterval(() => {
fetchOrderDetails(phone, false); // Silent update
}, 30000);

currentPhoneNumber = phone;
}

function stopPolling() {
if (pollingInterval) {
clearInterval(pollingInterval);
pollingInterval = null;
}
document.getElementById("autoUpdateNotice").style.display = "none";
currentPhoneNumber = null;
}

function searchOrder() {
const phone = document.getElementById("phoneInput").value.trim();
const errorDiv = document.getElementById("error");

// Validate phone number
if (!phone.match(/^(\+88)?\d{11}$/)) {
errorDiv.innerText = "⚠️ Please enter a valid 11-digit phone number";
stopPolling();
return;
}

// Save phone number
localStorage.setItem('savedPhoneNumber', phone);

// Stop any existing polling
stopPolling();

// Fetch order details and start polling
fetchOrderDetails(phone);
startPolling(phone);
}

// Auto-fill saved phone number on page load
window.onload = function() {
const savedPhone = localStorage.getItem('savedPhoneNumber');
if (savedPhone) {
document.getElementById("phoneInput").value = savedPhone;
searchOrder();
}

// Add event listener for Enter key
document.getElementById("phoneInput").addEventListener("keypress", function(e) {
if (e.key === "Enter") {
searchOrder();
}
});

// Focus on input field
document.getElementById("phoneInput").focus();
};

// Stop polling when page is unloaded
window.addEventListener('beforeunload', function() {
stopPolling();
});
</script>
</body>
</html>
This site was made on Tilda — a website builder that helps to create a website without any code
Create a website