CUMING SOON

Audience & Analytics
🌐 View Landing Page
Total Visits šŸ‘ļø
0
Total landing page impressions
Unique Visitors šŸ‘„
0
Distinct audience devices
Live Fans Waiting ⚔
2,846
4 Digits (Controlled from Admin)
World Premiere Date šŸ—“ļø
Oct 5, 2026
Countdown Active
Trailers Uploaded šŸŽ¬
0
Cloudinary CDN Connected
Top Indian Region 🚩
Uttar Pradesh
Highest Hindi dub demand
šŸŒ Country Distribution
7 Countries
šŸ‡®šŸ‡³ India State & Region Breakdown
UP • Bihar • Tamil Nadu
ā— Recent Live Visitors Stream
Auto-refreshing live activity
šŸŽ¬ Trailer Preview
āœ“ Message
// Ensure admin is on the primary production domain (avoids 308 redirect header drops) if (window.location.hostname === 'trustme.buzz') { window.location.replace('https://www.trustme.buzz' + window.location.pathname + window.location.search + window.location.hash); } // State management let authToken = localStorage.getItem('cuming_soon_admin_token') || null; let leadsData = []; let analyticsData = null; let currentSettings = { fansWaitingCount: 2846, autoIncrement: true }; let refreshInterval = null; let currentTab = 'geo'; const viewLogin = document.getElementById('view-login'); const viewDashboard = document.getElementById('view-dashboard'); const authControls = document.getElementById('auth-controls'); const adminUserEmail = document.getElementById('admin-user-email'); const loginError = document.getElementById('login-error'); const kpiVisits = document.getElementById('kpi-visits'); const kpiUnique = document.getElementById('kpi-unique'); const kpiFansWaiting = document.getElementById('kpi-fans-waiting'); const kpiFansDigitsSub = document.getElementById('kpi-fans-digits-sub'); const kpiLaunchDate = document.getElementById('kpi-launch-date'); const kpiLaunchCountdownSub = document.getElementById('kpi-launch-countdown-sub'); const kpiTrailersCount = document.getElementById('kpi-trailers-count'); const kpiTopState = document.getElementById('kpi-top-state'); const leadsCountTab = document.getElementById('leads-count-tab'); const videosCountTab = document.getElementById('videos-count-tab'); const countryDistList = document.getElementById('country-distribution-list'); const stateDistList = document.getElementById('state-distribution-list'); const recentStreamGrid = document.getElementById('recent-stream-grid'); const tagCountriesCount = document.getElementById('tag-countries-count'); // Fans Counter Elements const inputFansCount = document.getElementById('input-fans-count'); const inputDigitCount = document.getElementById('input-digit-count'); const tagCurrentDigits = document.getElementById('tag-current-digits'); const checkAutoIncrement = document.getElementById('check-auto-increment'); const previewFansNumber = document.getElementById('preview-fans-number'); const counterLastUpdated = document.getElementById('counter-last-updated'); // Launch Date & Subtitle Elements const tagCurrentLaunch = document.getElementById('tag-current-launch'); const inputLaunchDate = document.getElementById('input-launch-date'); const inputLaunchDisplay = document.getElementById('input-launch-display'); const inputLaunchBadge = document.getElementById('input-launch-badge'); const inputHeroSubtitle = document.getElementById('input-hero-subtitle'); const previewHeroSubtitle = document.getElementById('preview-hero-subtitle'); const previewLaunchDateText = document.getElementById('preview-launch-date-text'); const previewLaunchBadge = document.getElementById('preview-launch-badge'); const previewVipTitle = document.getElementById('preview-vip-title'); const previewCdDays = document.getElementById('preview-cd-days'); const previewCdHours = document.getElementById('preview-cd-hours'); const previewCdMinutes = document.getElementById('preview-cd-minutes'); const previewCdSeconds = document.getElementById('preview-cd-seconds'); const launchLastUpdated = document.getElementById('launch-last-updated'); // Video & Trailer Elements let videosData = []; const videosGridCount = document.getElementById('videos-grid-count'); const adminVideosGrid = document.getElementById('admin-videos-grid'); const videosEmpty = document.getElementById('videos-empty'); const labelActiveVideosCount = document.getElementById('label-active-videos-count'); const miniPreviewVideo = document.getElementById('mini-preview-video'); const miniPreviewEmpty = document.getElementById('mini-preview-empty'); const formUploadVideo = document.getElementById('form-upload-video'); const inputVideoFile = document.getElementById('input-video-file'); const inputThumbFile = document.getElementById('input-thumb-file'); const inputVideoTitle = document.getElementById('input-video-title'); const inputVideoBadge = document.getElementById('input-video-badge'); const inputVideoDuration = document.getElementById('input-video-duration'); const uploadProgressBox = document.getElementById('upload-progress-box'); const uploadProgressStatus = document.getElementById('upload-progress-status'); const uploadProgressPct = document.getElementById('upload-progress-pct'); const uploadProgressBar = document.getElementById('upload-progress-bar'); const btnSubmitUpload = document.getElementById('btn-submit-upload'); const formDirectVideoUrl = document.getElementById('form-direct-video-url'); const inputDirectVideoUrl = document.getElementById('input-direct-video-url'); const inputDirectThumbUrl = document.getElementById('input-direct-thumb-url'); const leadsTbody = document.getElementById('leads-tbody'); const leadsEmpty = document.getElementById('leads-empty'); const filterSearch = document.getElementById('filter-search'); // Country Flags Dictionary const COUNTRY_FLAGS = { 'India': 'šŸ‡®šŸ‡³', 'Pakistan': 'šŸ‡µšŸ‡°', 'United Arab Emirates': 'šŸ‡¦šŸ‡Ŗ', 'UAE': 'šŸ‡¦šŸ‡Ŗ', 'Nepal': 'šŸ‡³šŸ‡µ', 'Bangladesh': 'šŸ‡§šŸ‡©', 'United States': 'šŸ‡ŗšŸ‡ø', 'United Kingdom': 'šŸ‡¬šŸ‡§', 'Canada': 'šŸ‡ØšŸ‡¦', 'Saudi Arabia': 'šŸ‡øšŸ‡¦' }; // Indian State Top Cities Hints const STATE_CITIES = { 'Uttar Pradesh': 'Lucknow, Kanpur, Varanasi, Agra', 'Bihar': 'Patna, Gaya, Muzaffarpur, Bhagalpur', 'Delhi NCR': 'New Delhi, Noida, Gurgaon', 'Maharashtra': 'Mumbai, Pune, Nagpur', 'Madhya Pradesh': 'Bhopal, Indore, Gwalior', 'Rajasthan': 'Jaipur, Jodhpur, Kota', 'Tamil Nadu': 'Chennai, Coimbatore, Madurai', 'West Bengal': 'Kolkata, Asansol, Howrah', 'Punjab': 'Ludhiana, Amritsar, Jalandhar', 'Gujarat': 'Ahmedabad, Surat, Vadodara' }; // Tab switcher window.switchTab = function(tab) { currentTab = tab; const tabGeo = document.getElementById('tab-geo'); const tabCounter = document.getElementById('tab-counter'); const tabLaunch = document.getElementById('tab-launch'); const tabVideos = document.getElementById('tab-videos'); const tabLeads = document.getElementById('tab-leads'); const secGeo = document.getElementById('section-geo'); const secCounter = document.getElementById('section-counter'); const secLaunch = document.getElementById('section-launch'); const secVideos = document.getElementById('section-videos'); const secLeads = document.getElementById('section-leads'); [tabGeo, tabCounter, tabLaunch, tabVideos, tabLeads].forEach(b => b && b.classList.remove('active')); [secGeo, secCounter, secLaunch, secVideos, secLeads].forEach(s => s && (s.style.display = 'none')); if (tab === 'geo') { tabGeo.classList.add('active'); secGeo.style.display = 'block'; } else if (tab === 'counter') { tabCounter.classList.add('active'); secCounter.style.display = 'block'; } else if (tab === 'launch') { tabLaunch.classList.add('active'); secLaunch.style.display = 'block'; } else if (tab === 'videos') { tabVideos.classList.add('active'); secVideos.style.display = 'block'; } else { tabLeads.classList.add('active'); secLeads.style.display = 'block'; } }; // Toast helper function showToast(msg, icon = 'āœ“') { const toast = document.getElementById('toast'); document.getElementById('toast-text').textContent = msg; document.getElementById('toast-icon').textContent = icon; toast.classList.add('show'); setTimeout(() => toast.classList.remove('show'), 2500); } // Auth verification function checkAuth() { if (authToken) { viewLogin.style.display = 'none'; viewDashboard.style.display = 'block'; authControls.style.display = 'flex'; adminUserEmail.textContent = localStorage.getItem('cuming_soon_admin_email') || 'admin@reallity.com'; fetchAllData(); if (!refreshInterval) { refreshInterval = setInterval(fetchAllData, 4000); } } else { viewLogin.style.display = 'block'; viewDashboard.style.display = 'none'; authControls.style.display = 'none'; if (refreshInterval) { clearInterval(refreshInterval); refreshInterval = null; } } } // Login Form Submit document.getElementById('form-login').addEventListener('submit', async (e) => { e.preventDefault(); loginError.style.display = 'none'; const email = document.getElementById('input-email').value.trim(); const password = document.getElementById('input-password').value; const btn = document.getElementById('btn-submit-login'); btn.disabled = true; btn.textContent = 'Verifying...'; try { const res = await fetch('/api/admin/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const data = await res.json(); if (data.success && data.token) { authToken = data.token; localStorage.setItem('cuming_soon_admin_token', authToken); localStorage.setItem('cuming_soon_admin_email', email); checkAuth(); showToast('Welcome back, Admin!'); } else { loginError.textContent = data.error || 'Invalid email or password'; loginError.style.display = 'block'; } } catch (err) { loginError.textContent = 'Network error connecting to auth server.'; loginError.style.display = 'block'; } finally { btn.disabled = false; btn.textContent = 'Enter Dashboard'; } }); // Logout document.getElementById('btn-logout').addEventListener('click', () => { authToken = null; localStorage.removeItem('cuming_soon_admin_token'); localStorage.removeItem('cuming_soon_admin_email'); checkAuth(); showToast('Logged out successfully', 'ā„¹ļø'); }); // Fetch all analytics, settings, and leads async function fetchAllData() { if (!authToken) return; await Promise.all([fetchAnalytics(), fetchLeads()]); } // Fetch Analytics API async function fetchAnalytics() { try { const res = await fetch('/api/admin/analytics', { headers: { 'Authorization': `Bearer ${authToken}` } }); if (res.status === 401) { authToken = null; checkAuth(); return; } const data = await res.json(); if (data.success) { analyticsData = data.analytics; if (data.settings) { currentSettings = data.settings; updateCounterUI(); updateLaunchUI(); } if (data.videos) { videosData = data.videos; renderVideosList(); } renderAnalytics(); } } catch (e) { console.error('Failed to fetch analytics:', e); } } // Counter UI Update function updateCounterUI() { const count = currentSettings.fansWaitingCount || 2846; const digits = String(count).length; kpiFansWaiting.textContent = Number(count).toLocaleString('en-US'); kpiFansDigitsSub.textContent = `${digits} Digits (${currentSettings.autoIncrement ? 'Auto-incrementing' : 'Fixed'})`; previewFansNumber.textContent = Number(count).toLocaleString('en-US'); tagCurrentDigits.textContent = `${digits} Digits Active`; if (document.activeElement !== inputFansCount) { inputFansCount.value = count; inputDigitCount.textContent = `${digits} Digits`; } checkAutoIncrement.checked = currentSettings.autoIncrement !== false; if (currentSettings.updatedAt) { counterLastUpdated.textContent = new Date(currentSettings.updatedAt).toLocaleTimeString('en-IN', { hour: '2-digit', minute: '2-digit' }); } } // Launch Date & Subtitle UI Update function formatAdminSubtitle(text) { if (!text) return ''; if (text.includes('<') && text.includes('>')) return text; return text.replace(/\b(Hindi|English|Dubbed)\b/gi, (match) => { if (match.toLowerCase() === 'hindi') return `${match}`; return `${match}`; }); } function updateLaunchUI() { const launchDate = currentSettings.launchDate || '2026-10-05T00:00:00+05:30'; const launchDisplay = currentSettings.launchDateDisplay || 'October 5, 2026'; const launchBadge = currentSettings.launchBadge || 'EXCLUSIVE DUB'; const subTitle = currentSettings.subTitle || 'Ab English Wali Hindi mein'; if (kpiLaunchDate) kpiLaunchDate.textContent = launchDisplay; if (tagCurrentLaunch) tagCurrentLaunch.textContent = launchDisplay; if (previewLaunchDateText) previewLaunchDateText.textContent = `World Premiere: ${launchDisplay}`; if (previewLaunchBadge) previewLaunchBadge.textContent = launchBadge; if (previewVipTitle) previewVipTitle.innerHTML = `šŸ”” Get First Access on ${launchDisplay}`; if (previewHeroSubtitle) previewHeroSubtitle.innerHTML = formatAdminSubtitle(subTitle); if (inputLaunchDisplay && document.activeElement !== inputLaunchDisplay) { inputLaunchDisplay.value = launchDisplay; } if (inputLaunchBadge && document.activeElement !== inputLaunchBadge) { inputLaunchBadge.value = launchBadge; } if (inputHeroSubtitle && document.activeElement !== inputHeroSubtitle) { inputHeroSubtitle.value = subTitle; } if (inputLaunchDate && document.activeElement !== inputLaunchDate) { try { const d = new Date(launchDate); if (!isNaN(d.getTime())) { const pad = (n) => String(n).padStart(2, '0'); const localIso = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; inputLaunchDate.value = localIso; } } catch (_) {} } updateAdminCountdown(); } function updateAdminCountdown() { const targetStr = (inputLaunchDate && inputLaunchDate.value) || currentSettings.launchDate || '2026-10-05T00:00:00'; const target = new Date(targetStr).getTime(); const now = Date.now(); const distance = target - now; if (distance <= 0) { if (previewCdDays) previewCdDays.textContent = '00'; if (previewCdHours) previewCdHours.textContent = '00'; if (previewCdMinutes) previewCdMinutes.textContent = '00'; if (previewCdSeconds) previewCdSeconds.textContent = '00'; if (kpiLaunchCountdownSub) kpiLaunchCountdownSub.textContent = 'Premiere Dropped!'; return; } const days = Math.floor(distance / (1000 * 60 * 60 * 24)); const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((distance % (1000 * 60)) / 1000); if (previewCdDays) previewCdDays.textContent = String(days).padStart(2, '0'); if (previewCdHours) previewCdHours.textContent = String(hours).padStart(2, '0'); if (previewCdMinutes) previewCdMinutes.textContent = String(minutes).padStart(2, '0'); if (previewCdSeconds) previewCdSeconds.textContent = String(seconds).padStart(2, '0'); if (kpiLaunchCountdownSub) kpiLaunchCountdownSub.textContent = `${days}d ${hours}h ${minutes}m left`; } setInterval(updateAdminCountdown, 1000); // Dynamic digit count indicator as user types inputFansCount.addEventListener('input', () => { const val = inputFansCount.value.trim(); const len = val ? val.length : 0; inputDigitCount.textContent = `${len} Digits`; if (val && !isNaN(val)) { previewFansNumber.textContent = Number(val).toLocaleString('en-US'); } }); // Preset button click handler window.applyPreset = function(num, label) { inputFansCount.value = num; inputDigitCount.textContent = `${String(num).length} Digits`; previewFansNumber.textContent = Number(num).toLocaleString('en-US'); document.querySelectorAll('#section-counter .btn-preset').forEach(b => b.classList.remove('active')); event.currentTarget.classList.add('active'); }; // Launch Preset button handler window.applyLaunchPreset = function(isoStr, displayStr, badgeStr) { if (inputLaunchDate) inputLaunchDate.value = isoStr; if (inputLaunchDisplay) inputLaunchDisplay.value = displayStr; if (inputLaunchBadge) inputLaunchBadge.value = badgeStr; if (previewLaunchDateText) previewLaunchDateText.textContent = `World Premiere: ${displayStr}`; if (previewLaunchBadge) previewLaunchBadge.textContent = badgeStr; if (previewVipTitle) previewVipTitle.innerHTML = `šŸ”” Get First Access on ${displayStr}`; if (tagCurrentLaunch) tagCurrentLaunch.textContent = displayStr; document.querySelectorAll('#section-launch .btn-preset').forEach(b => b.classList.remove('active')); if (window.event && window.event.currentTarget) { window.event.currentTarget.classList.add('active'); } updateAdminCountdown(); }; // Live typing listeners in launch date form ['input-launch-display', 'input-launch-badge', 'input-launch-date', 'input-hero-subtitle'].forEach(id => { const el = document.getElementById(id); if (el) { el.addEventListener('input', () => { const dText = inputLaunchDisplay ? inputLaunchDisplay.value : ''; const bText = inputLaunchBadge ? inputLaunchBadge.value : ''; const sText = inputHeroSubtitle ? inputHeroSubtitle.value : ''; if (previewLaunchDateText) previewLaunchDateText.textContent = `World Premiere: ${dText}`; if (previewLaunchBadge) previewLaunchBadge.textContent = bText; if (previewHeroSubtitle) previewHeroSubtitle.innerHTML = formatAdminSubtitle(sText); if (previewVipTitle) previewVipTitle.innerHTML = `šŸ”” Get First Access on ${dText}`; updateAdminCountdown(); }); } }); // Save Counter Form Submission document.getElementById('form-counter-settings').addEventListener('submit', async (e) => { e.preventDefault(); const num = parseInt(inputFansCount.value, 10); const autoInc = checkAutoIncrement.checked; const btn = document.getElementById('btn-save-counter'); if (isNaN(num) || num < 1) { showToast('Please enter a valid positive number', 'āš ļø'); return; } btn.disabled = true; btn.textContent = 'Updating Live Website...'; try { const res = await fetch('/api/admin/counter', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${authToken}` }, body: JSON.stringify({ fansWaitingCount: num, autoIncrement: autoInc }) }); const data = await res.json(); if (data.success && data.settings) { currentSettings = data.settings; updateCounterUI(); showToast(`Live counter updated to ${Number(num).toLocaleString('en-US')} (${String(num).length} digits)!`, '⚔'); } else { showToast(data.error || 'Failed to update counter', 'āŒ'); } } catch (err) { showToast('Network error updating counter', 'āŒ'); } finally { btn.disabled = false; btn.textContent = 'Save & Update Live Counter'; } }); // Save Launch Date Form Submission document.getElementById('form-launch-settings').addEventListener('submit', async (e) => { e.preventDefault(); const dateVal = inputLaunchDate.value; const displayVal = inputLaunchDisplay.value.trim(); const badgeVal = inputLaunchBadge.value.trim(); const subTitleVal = inputHeroSubtitle ? inputHeroSubtitle.value.trim() : 'Ab English Wali Hindi mein'; const btn = document.getElementById('btn-save-launch'); if (!dateVal) { showToast('Please select a target date & time', 'āš ļø'); return; } btn.disabled = true; btn.textContent = 'Publishing Premiere Date...'; try { const res = await fetch('/api/admin/launch', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${authToken}` }, body: JSON.stringify({ launchDate: new Date(dateVal).toISOString(), launchDateDisplay: displayVal, launchBadge: badgeVal, subTitle: subTitleVal }) }); const data = await res.json(); if (data.success && data.settings) { currentSettings = data.settings; updateLaunchUI(); if (launchLastUpdated) launchLastUpdated.textContent = 'Published Just Now'; showToast(`World Premiere settings updated! Subtitle & launch synced.`, 'šŸš€'); } else { showToast(data.error || 'Failed to update premiere date', 'āŒ'); } } catch (err) { showToast('Network error updating launch date', 'āŒ'); } finally { btn.disabled = false; btn.textContent = 'šŸš€ Save & Publish Premiere Settings'; } }); // ========================================================================= // VIDEO & TRAILER MANAGEMENT (CLOUDINARY DIRECT UPLOADS) // ========================================================================= // Auto-detect duration and set default title on video file select if (inputVideoFile) { inputVideoFile.addEventListener('change', () => { const file = inputVideoFile.files[0]; if (file) { if (!inputVideoTitle.value) { const cleanName = file.name.replace(/\.[^/.]+$/, "").replace(/[-_]/g, " "); inputVideoTitle.value = cleanName.charAt(0).toUpperCase() + cleanName.slice(1); } try { const vid = document.createElement('video'); vid.preload = 'metadata'; vid.onloadedmetadata = () => { window.URL.revokeObjectURL(vid.src); const totalSecs = Math.round(vid.duration); const mins = Math.floor(totalSecs / 60); const secs = String(totalSecs % 60).padStart(2, '0'); if (inputVideoDuration) inputVideoDuration.value = `${mins}:${secs}`; }; vid.src = URL.createObjectURL(file); } catch (_) {} } }); } // Direct Cloudinary Upload via XHR with real-time percentage progress function uploadFileToCloudinary(file, resourceType = 'video', onProgress) { return new Promise((resolve, reject) => { const cloudName = (currentSettings.cloudinary && currentSettings.cloudinary.cloudName) || 'jokxw4xl'; const uploadPreset = (currentSettings.cloudinary && currentSettings.cloudinary.uploadPreset) || 'dubbed_videos'; const folder = (currentSettings.cloudinary && currentSettings.cloudinary.folder) || 'dubbed_trailers'; const url = `https://api.cloudinary.com/v1_1/${cloudName}/${resourceType}/upload`; const xhr = new XMLHttpRequest(); const fd = new FormData(); fd.append('file', file); fd.append('upload_preset', uploadPreset); if (folder) fd.append('folder', folder); xhr.open('POST', url, true); xhr.upload.onprogress = (e) => { if (e.lengthComputable && onProgress) { const pct = Math.round((e.loaded / e.total) * 100); const loadedMB = (e.loaded / (1024 * 1024)).toFixed(1); const totalMB = (e.total / (1024 * 1024)).toFixed(1); onProgress(pct, loadedMB, totalMB); } }; xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { try { const res = JSON.parse(xhr.responseText); resolve(res); } catch (err) { reject(new Error('Invalid response from Cloudinary')); } } else { let errMsg = xhr.statusText || 'Upload failed'; try { const errObj = JSON.parse(xhr.responseText); if (errObj.error && errObj.error.message) errMsg = errObj.error.message; } catch (_) {} reject(new Error(errMsg)); } }; xhr.onerror = () => reject(new Error('Network connection error to Cloudinary')); xhr.send(fd); }); } // Video Upload Form Submit if (formUploadVideo) { formUploadVideo.addEventListener('submit', async (e) => { e.preventDefault(); const videoFile = inputVideoFile.files[0]; const thumbFile = inputThumbFile.files[0]; const title = inputVideoTitle.value.trim(); const badge = inputVideoBadge.value.trim() || 'EXCLUSIVE DUB'; const duration = inputVideoDuration.value.trim() || '3:45'; if (!videoFile) { showToast('Please select a video file', 'āš ļø'); return; } btnSubmitUpload.disabled = true; uploadProgressBox.style.display = 'block'; uploadProgressPct.textContent = '0%'; uploadProgressBar.style.width = '0%'; uploadProgressStatus.textContent = 'Starting direct Cloudinary upload...'; try { // 1. Upload Video const vidResult = await uploadFileToCloudinary(videoFile, 'video', (pct, loaded, total) => { uploadProgressPct.textContent = `${pct}%`; uploadProgressBar.style.width = `${pct}%`; uploadProgressStatus.textContent = `Uploading Video: ${pct}% (${loaded} MB / ${total} MB)...`; }); const videoUrl = vidResult.secure_url; let thumbnailUrl = videoUrl.replace(/\.[^/.]+$/, ".jpg"); const publicId = vidResult.public_id; // 2. Upload Custom Thumbnail if provided if (thumbFile) { uploadProgressStatus.textContent = 'Uploading Custom Thumbnail image...'; uploadProgressPct.textContent = '96%'; uploadProgressBar.style.width = '96%'; try { const thumbResult = await uploadFileToCloudinary(thumbFile, 'image', () => {}); if (thumbResult && thumbResult.secure_url) { thumbnailUrl = thumbResult.secure_url; } } catch (tErr) { console.warn('Custom thumb upload fallback:', tErr); } } uploadProgressStatus.textContent = 'Publishing trailer to landing page...'; uploadProgressPct.textContent = '100%'; uploadProgressBar.style.width = '100%'; // 3. Save to backend /api/admin/videos const res = await fetch('/api/admin/videos', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${authToken}` }, body: JSON.stringify({ title, videoUrl, thumbnailUrl, badge, duration, publicId }) }); const data = await res.json(); if (data.success) { videosData = data.videos || []; renderVideosList(); inputVideoFile.value = ''; inputThumbFile.value = ''; inputVideoTitle.value = ''; showToast(`Trailer "${title}" published successfully!`, 'šŸŽ¬'); } else { showToast(data.error || 'Failed to register video on server', 'āŒ'); } } catch (err) { console.error('Upload error:', err); showToast(`Upload failed: ${err.message}`, 'āŒ'); } finally { btnSubmitUpload.disabled = false; setTimeout(() => { uploadProgressBox.style.display = 'none'; }, 2500); } }); } // Direct Video URL Save Form if (formDirectVideoUrl) { formDirectVideoUrl.addEventListener('submit', async (e) => { e.preventDefault(); const videoUrl = inputDirectVideoUrl.value.trim(); const thumbUrl = inputDirectThumbUrl.value.trim(); const title = (inputVideoTitle && inputVideoTitle.value.trim()) || 'Hindi Dub Premiere Trailer'; const badge = (inputVideoBadge && inputVideoBadge.value.trim()) || 'EXCLUSIVE DUB'; const duration = (inputVideoDuration && inputVideoDuration.value.trim()) || '3:45'; if (!videoUrl) { showToast('Please enter a video URL', 'āš ļø'); return; } try { const res = await fetch('/api/admin/videos', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${authToken}` }, body: JSON.stringify({ title, videoUrl, thumbnailUrl: thumbUrl || videoUrl.replace(/\.[^/.]+$/, ".jpg"), badge, duration }) }); const data = await res.json(); if (data.success) { videosData = data.videos || []; renderVideosList(); inputDirectVideoUrl.value = ''; inputDirectThumbUrl.value = ''; showToast('Direct video link published!', 'šŸ”—'); } else { showToast(data.error || 'Failed to save link', 'āŒ'); } } catch (err) { showToast('Network error saving link', 'āŒ'); } }); } // Render Videos in Admin Dashboard function renderVideosList() { const count = videosData.length; if (kpiTrailersCount) kpiTrailersCount.textContent = count; if (videosCountTab) videosCountTab.textContent = count; if (videosGridCount) videosGridCount.textContent = count; if (labelActiveVideosCount) labelActiveVideosCount.textContent = `${count} Videos Live`; if (count === 0) { if (videosEmpty) videosEmpty.style.display = 'block'; if (adminVideosGrid) adminVideosGrid.innerHTML = ''; if (miniPreviewVideo) { miniPreviewVideo.style.display = 'none'; miniPreviewVideo.src = ''; } if (miniPreviewEmpty) miniPreviewEmpty.style.display = 'block'; return; } if (videosEmpty) videosEmpty.style.display = 'none'; // Update mini preview with first video const firstVid = videosData[0]; if (miniPreviewVideo) { miniPreviewVideo.style.display = 'block'; miniPreviewVideo.src = firstVid.videoUrl; if (firstVid.thumbnailUrl) miniPreviewVideo.poster = firstVid.thumbnailUrl; } if (miniPreviewEmpty) miniPreviewEmpty.style.display = 'none'; // Render video cards if (adminVideosGrid) { adminVideosGrid.innerHTML = videosData.map((v) => { const thumb = v.thumbnailUrl || v.videoUrl.replace(/\.[^/.]+$/, ".jpg"); return `
${v.title}
ā–¶
${v.badge || 'EXCLUSIVE DUB'} ${v.duration || '3:30'}
${v.title}
${v.videoUrl}
`; }).join(''); } } // Modal Player handlers window.openVideoModal = function(url, title) { const modal = document.getElementById('video-modal'); const titleEl = document.getElementById('modal-video-title'); const videoEl = document.getElementById('modal-video-element'); if (titleEl) titleEl.textContent = title || 'Trailer Preview'; if (videoEl) { videoEl.src = url; videoEl.play().catch(() => {}); } if (modal) modal.style.display = 'flex'; }; window.closeVideoModal = function() { const modal = document.getElementById('video-modal'); const videoEl = document.getElementById('modal-video-element'); if (videoEl) { videoEl.pause(); videoEl.src = ''; } if (modal) modal.style.display = 'none'; }; window.copyToClipboard = function(text, successMsg) { if (navigator.clipboard) { navigator.clipboard.writeText(text); showToast(successMsg || 'Copied to clipboard!', 'šŸ“‹'); } }; window.deleteVideo = async function(id) { if (!confirm('Are you sure you want to delete this trailer from the landing page?')) return; // Optimistic instant UI removal videosData = videosData.filter(v => v.id !== id); renderVideosList(); showToast('Removing trailer...', 'ā³'); try { const res = await fetch(`/api/admin/videos/${encodeURIComponent(id)}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${authToken}` } }); let data = {}; try { data = await res.json(); } catch (_) {} if (res.ok || (data && data.success)) { if (data && Array.isArray(data.videos)) { videosData = data.videos; renderVideosList(); } showToast('Trailer removed successfully', 'šŸ—‘ļø'); } else if (res.status === 404) { showToast('Trailer removed', 'šŸ—‘ļø'); } else { showToast(data.error || 'Notice: Updated locally (' + res.status + ')', 'āš ļø'); } } catch (err) { showToast('Trailer removed from view', 'šŸ—‘ļø'); } }; // Render Analytics Panels function renderAnalytics() { if (!analyticsData) return; const totalVisits = analyticsData.totalVisits || 0; kpiVisits.textContent = Number(analyticsData.totalVisits || 0).toLocaleString('en-US'); kpiUnique.textContent = Number(analyticsData.uniqueVisitors || 0).toLocaleString('en-US'); // 1. Countries const countryEntries = Object.entries(analyticsData.countries || {}).sort((a, b) => b[1] - a[1]); tagCountriesCount.textContent = `${countryEntries.length} Countries`; if (countryEntries.length === 0) { countryDistList.innerHTML = `
No country traffic recorded yet. Live visits will appear here.
`; } else { const divVisits = totalVisits || 1; countryDistList.innerHTML = countryEntries.map(([country, count], idx) => { const pct = Math.min(100, Math.round((count / divVisits) * 100)); const flag = COUNTRY_FLAGS[country] || '🌐'; const fillClass = idx === 0 ? '' : idx === 1 ? 'cyan' : 'violet'; return `
${flag} ${country} ${idx === 0 ? 'TOP MARKET' : ''} ${Number(count).toLocaleString('en-US')} ${pct}%
`; }).join(''); } // 2. Indian States const stateEntries = Object.entries(analyticsData.indianStates || {}).sort((a, b) => b[1] - a[1]); const totalIndia = (analyticsData.countries && analyticsData.countries['India']) || totalVisits || 1; if (stateEntries.length > 0) { kpiTopState.textContent = stateEntries[0][0]; const statePct = ((stateEntries[0][1] / totalIndia) * 100).toFixed(1); document.getElementById('kpi-top-state-sub').textContent = `${statePct}% of India traffic (${Number(stateEntries[0][1]).toLocaleString('en-US')} fans)`; } else { kpiTopState.textContent = 'Awaiting Traffic'; document.getElementById('kpi-top-state-sub').textContent = 'Live visitors will appear here'; } if (stateEntries.length === 0) { stateDistList.innerHTML = `
No regional traffic recorded yet. Indian state breakdown will appear as fans visit.
`; } else { stateDistList.innerHTML = stateEntries.map(([state, count], idx) => { const pct = Math.min(100, Math.round((count / totalIndia) * 100)); const cities = STATE_CITIES[state] || 'Key regional centers'; const fillClass = state.includes('Uttar Pradesh') ? '' : state.includes('Bihar') ? 'cyan' : state.includes('Tamil') ? 'violet' : 'cyan'; return `
🚩 ${state} ${state === 'Uttar Pradesh' || state === 'Bihar' || state === 'Tamil Nadu' ? `${state === 'Tamil Nadu' ? 'SOUTH HUB' : 'HEAVY DUB DEMAND'}` : ''} ${Number(count).toLocaleString('en-US')} ${pct}%
Top Cities: ${cities}
`; }).join(''); } // 3. Recent Live Visitors Stream const recents = analyticsData.recentVisits || []; if (recents.length === 0) { recentStreamGrid.innerHTML = `
No visitor sessions yet. New sessions stream in real-time.
`; } else { recentStreamGrid.innerHTML = recents.slice(0, 8).map(v => { const flag = COUNTRY_FLAGS[v.country] || '🌐'; const dateObj = new Date(v.timestamp); const timeAgo = formatTimeAgo(dateObj); return `
${flag} ${escapeHtml(v.city || 'Visitor')}
${escapeHtml(v.region || '')}, ${escapeHtml(v.country)}
${v.device === 'Mobile' ? 'šŸ“± Mobile' : 'šŸ’» Desktop'} ${timeAgo}
`; }).join(''); } } function formatTimeAgo(date) { const sec = Math.floor((Date.now() - date.getTime()) / 1000); if (sec < 60) return `${sec}s ago`; const min = Math.floor(sec / 60); if (min < 60) return `${min}m ago`; const hrs = Math.floor(min / 60); return `${hrs}h ago`; } async function resetAnalyticsToZero() { if (!confirm('Are you sure you want to reset all visitor statistics (Total Visits, Unique, Countries, Sessions) to 0?')) { return; } try { const res = await fetch('/api/admin/reset-analytics', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + authToken } }); const data = await res.json(); if (data.success) { analyticsData = data.analytics; renderAnalytics(); showToast('Analytics reset to 0! Pure real-time tracking active.', 'šŸ”„'); } else { showToast('Failed to reset: ' + (data.error || 'Server error'), 'āš ļø'); } } catch (err) { showToast('Error resetting analytics: ' + err.message, 'āš ļø'); } } // Fetch Leads API async function fetchLeads() { try { const res = await fetch('/api/admin/leads', { headers: { 'Authorization': `Bearer ${authToken}` } }); if (res.status === 401) { authToken = null; checkAuth(); return; } const data = await res.json(); if (data.success && Array.isArray(data.leads)) { leadsData = data.leads; leadsCountTab.textContent = leadsData.length; renderLeadsTable(); } } catch (e) { console.error('Failed to fetch leads:', e); } } // Leads Management: Telegram & WhatsApp let currentChannelFilter = 'all'; // 'all', 'telegram', 'whatsapp' window.filterByChannel = function(ch) { currentChannelFilter = ch; ['all', 'tg', 'wa'].forEach(k => { const el = document.getElementById('filter-ch-' + k); if (el) el.classList.remove('gold'); }); const activeEl = document.getElementById('filter-ch-' + (ch === 'telegram' ? 'tg' : ch === 'whatsapp' ? 'wa' : 'all')); if (activeEl) activeEl.classList.add('gold'); renderLeadsTable(); }; // Render Leads Table function renderLeadsTable() { const query = filterSearch.value.trim().toLowerCase(); const filtered = leadsData.filter(item => { const isWa = item.type === 'whatsapp' || !!item.whatsappNo; const itemType = isWa ? 'whatsapp' : 'telegram'; if (currentChannelFilter !== 'all' && itemType !== currentChannelFilter) { return false; } const contactStr = (item.contact || item.telegramId || item.whatsappNo || '').toLowerCase(); return contactStr.includes(query) || (item.city && item.city.toLowerCase().includes(query)) || (item.region && item.region.toLowerCase().includes(query)) || (item.country && item.country.toLowerCase().includes(query)) || (item.submittedAt && item.submittedAt.toLowerCase().includes(query)); }); if (filtered.length === 0) { leadsTbody.innerHTML = ''; leadsEmpty.style.display = 'block'; return; } leadsEmpty.style.display = 'none'; leadsTbody.innerHTML = filtered.map((item, idx) => { const isWa = item.type === 'whatsapp' || !!item.whatsappNo; const contactVal = item.contact || (isWa ? item.whatsappNo : item.telegramId) || ''; const dateObj = new Date(item.submittedAt); const formattedDate = dateObj.toLocaleString('en-IN', { dateStyle: 'medium', timeStyle: 'short', timeZone: 'Asia/Kolkata' }); const flag = COUNTRY_FLAGS[item.country] || '🌐'; const locParts = []; if (item.city) locParts.push(item.city); if (item.region) locParts.push(item.region); if (item.country) locParts.push(item.country); const locationText = locParts.length > 0 ? locParts.join(', ') : 'India'; let badgeHtml = ''; let directChatBtn = ''; if (isWa) { const cleanPhone = contactVal.replace(/[^\d]/g, ''); badgeHtml = ` šŸ’¬ ${escapeHtml(contactVal)} `; directChatBtn = `šŸ’¬`; } else { const cleanHandle = contactVal.replace('@', ''); badgeHtml = ` āœˆļø ${escapeHtml(contactVal.startsWith('@') ? contactVal : '@' + contactVal)} `; directChatBtn = `āœˆļø`; } return ` #${filtered.length - idx} ${badgeHtml}
${flag} ${escapeHtml(locationText)}
${formattedDate} ${escapeHtml(item.ip || '127.0.0.1')} ${directChatBtn} `; }).join(''); } filterSearch.addEventListener('input', renderLeadsTable); function escapeHtml(str) { if (!str) return ''; return String(str).replace(/[&<>"']/g, (m) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[m]); } window.copyId = function(id) { navigator.clipboard.writeText(id).then(() => { showToast(`Copied ${id} to clipboard!`); }); }; document.getElementById('btn-copy-all').addEventListener('click', () => { if (leadsData.length === 0) { showToast('No contacts to copy', 'āš ļø'); return; } const allContacts = leadsData.map(l => l.contact || l.whatsappNo || l.telegramId).join('\n'); navigator.clipboard.writeText(allContacts).then(() => { showToast(`Copied ${leadsData.length} contacts!`); }); }); window.deleteLead = async function(id) { if (!confirm('Are you sure you want to remove this submission?')) return; try { const res = await fetch(`/api/admin/leads/${id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${authToken}` } }); const data = await res.json(); if (data.success) { leadsData = leadsData.filter(l => l.id !== id); renderLeadsTable(); leadsCountTab.textContent = leadsData.length; showToast('Lead deleted successfully'); } } catch (e) { showToast('Failed to delete lead', 'āŒ'); } }; document.getElementById('btn-export-csv').addEventListener('click', () => { if (leadsData.length === 0) { showToast('No leads available to export', 'āš ļø'); return; } let csv = 'ID,Channel,Contact,City,State / Region,Country,Submitted Date,IP\n'; leadsData.forEach(l => { const isWa = l.type === 'whatsapp' || !!l.whatsappNo; const ch = isWa ? 'WhatsApp' : 'Telegram'; const contact = l.contact || (isWa ? l.whatsappNo : l.telegramId) || ''; csv += `"${l.id}","${ch}","${contact}","${l.city || ''}","${l.region || ''}","${l.country || ''}","${l.submittedAt}","${l.ip || ''}"\n`; }); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `cuming_soon_audience_leads_${Date.now()}.csv`; a.click(); URL.revokeObjectURL(url); showToast('CSV downloaded!'); }); document.getElementById('btn-refresh').addEventListener('click', () => { fetchAllData(); showToast('Dashboard refreshed'); }); checkAuth();