Spaces:
Sleeping
Sleeping
| const navToggle = document.getElementById('navToggle'); | |
| const navMenu = document.getElementById('navMenu'); | |
| const navOverlay = document.getElementById('navOverlay'); | |
| const body = document.body; | |
| const html = document.documentElement; | |
| let touchStartX = 0; | |
| let touchEndX = 0; | |
| let isAnimating = false; | |
| function preventHorizontalScroll() { | |
| html.style.overflowX = 'hidden'; | |
| html.style.width = '100%'; | |
| html.style.position = 'relative'; | |
| body.style.overflowX = 'hidden'; | |
| body.style.maxWidth = '100%'; | |
| body.style.width = '100%'; | |
| body.style.position = 'relative'; | |
| body.style.margin = '0'; | |
| body.style.padding = '0'; | |
| const existingStyle = document.getElementById('prevent-scroll-style'); | |
| if (existingStyle) { | |
| existingStyle.remove(); | |
| } | |
| const style = document.createElement('style'); | |
| style.id = 'prevent-scroll-style'; | |
| style.textContent = ` | |
| * { | |
| box-sizing: border-box !important; | |
| } | |
| html, body { | |
| overflow-x: hidden !important; | |
| max-width: 100% !important; | |
| width: 100% !important; | |
| margin: 0 !important; | |
| padding: 0 !important; | |
| } | |
| body.menu-open { | |
| overflow: hidden !important; | |
| position: fixed !important; | |
| width: 100% !important; | |
| height: 100% !important; | |
| top: 0 !important; | |
| left: 0 !important; | |
| } | |
| section, .container, .nav-container, .hero, .features, .stats, .footer { | |
| max-width: 100% !important; | |
| overflow-x: hidden !important; | |
| } | |
| .nav-menu { | |
| position: fixed !important; | |
| top: 0 !important; | |
| right: -100% !important; | |
| width: 280px !important; | |
| height: 100vh !important; | |
| background: rgba(44, 62, 80, 0.98) !important; | |
| backdrop-filter: blur(20px) !important; | |
| flex-direction: column !important; | |
| padding: 5rem 2rem 2rem !important; | |
| gap: 0.5rem !important; | |
| box-shadow: -5px 0 20px rgba(0, 0, 0, 0.5) !important; | |
| overflow-y: auto !important; | |
| overflow-x: hidden !important; | |
| border-left: 1px solid rgba(255, 255, 255, 0.1) !important; | |
| align-items: stretch !important; | |
| z-index: 10001 !important; | |
| transition: right 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; | |
| display: flex !important; | |
| } | |
| .nav-menu.active { | |
| right: 0 !important; | |
| } | |
| .nav-overlay { | |
| position: fixed !important; | |
| top: 0 !important; | |
| left: 0 !important; | |
| width: 100% !important; | |
| height: 100% !important; | |
| background: rgba(0, 0, 0, 0.7) !important; | |
| z-index: 10000 !important; | |
| opacity: 0 !important; | |
| visibility: hidden !important; | |
| transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1), visibility 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; | |
| pointer-events: none !important; | |
| } | |
| .nav-overlay.active { | |
| opacity: 1 !important; | |
| visibility: visible !important; | |
| pointer-events: auto !important; | |
| } | |
| .nav-toggle { | |
| z-index: 10002 !important; | |
| cursor: pointer !important; | |
| transition: transform 0.3s ease !important; | |
| position: relative !important; | |
| } | |
| .nav-toggle.active { | |
| transform: rotate(90deg) !important; | |
| } | |
| img, video, iframe { | |
| max-width: 100% !important; | |
| height: auto !important; | |
| } | |
| @media (max-width: 768px) { | |
| .hero-buttons, .cta-buttons, .hero-features { | |
| flex-wrap: wrap !important; | |
| justify-content: center !important; | |
| } | |
| .feature-card, .stat-card { | |
| width: 100% !important; | |
| max-width: 100% !important; | |
| } | |
| .nav-menu { | |
| width: 280px !important; | |
| } | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| } | |
| function toggleMenu(e) { | |
| if (e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| if (isAnimating) return; | |
| const isActive = navMenu.classList.contains('active'); | |
| if (isActive) { | |
| closeMenu(); | |
| } else { | |
| openMenu(); | |
| } | |
| } | |
| function openMenu() { | |
| if (isAnimating) return; | |
| isAnimating = true; | |
| const scrollY = window.scrollY; | |
| body.style.top = `-${scrollY}px`; | |
| navToggle.classList.add('active'); | |
| navOverlay.classList.add('active'); | |
| body.classList.add('menu-open'); | |
| setTimeout(() => { | |
| navMenu.classList.add('active'); | |
| setTimeout(() => { | |
| isAnimating = false; | |
| }, 400); | |
| }, 10); | |
| } | |
| function closeMenu() { | |
| if (isAnimating) return; | |
| isAnimating = true; | |
| navToggle.classList.remove('active'); | |
| navMenu.classList.remove('active'); | |
| navOverlay.classList.remove('active'); | |
| setTimeout(() => { | |
| body.classList.remove('menu-open'); | |
| const scrollY = body.style.top; | |
| body.style.top = ''; | |
| if (scrollY) { | |
| window.scrollTo(0, parseInt(scrollY || '0') * -1); | |
| } | |
| isAnimating = false; | |
| }, 400); | |
| } | |
| if (navToggle) { | |
| navToggle.addEventListener('click', toggleMenu); | |
| navToggle.addEventListener('touchstart', (e) => { | |
| e.stopPropagation(); | |
| }, { passive: true }); | |
| } | |
| if (navOverlay) { | |
| navOverlay.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| closeMenu(); | |
| }); | |
| } | |
| if (navMenu) { | |
| navMenu.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| }); | |
| navMenu.addEventListener('touchstart', (e) => { | |
| touchStartX = e.changedTouches[0].screenX; | |
| e.stopPropagation(); | |
| }, { passive: true }); | |
| navMenu.addEventListener('touchend', (e) => { | |
| touchEndX = e.changedTouches[0].screenX; | |
| if (touchStartX - touchEndX > 50) { | |
| closeMenu(); | |
| } | |
| e.stopPropagation(); | |
| }, { passive: true }); | |
| } | |
| document.querySelectorAll('.nav-link').forEach(link => { | |
| link.addEventListener('click', handleNavLinkClick); | |
| }); | |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
| if (!anchor.classList.contains('nav-link')) { | |
| anchor.addEventListener('click', function (e) { | |
| const href = this.getAttribute('href'); | |
| if (!href || href === '#') return; | |
| e.preventDefault(); | |
| const target = document.querySelector(href); | |
| if (target) { | |
| target.scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| } | |
| }); | |
| } | |
| }); | |
| window.addEventListener('load', () => { | |
| preventHorizontalScroll(); | |
| }); | |
| window.addEventListener('resize', () => { | |
| preventHorizontalScroll(); | |
| if (window.innerWidth > 768) { | |
| if (navMenu.classList.contains('active')) { | |
| closeMenu(); | |
| } | |
| } | |
| }); | |
| document.addEventListener('touchmove', (e) => { | |
| if (body.classList.contains('menu-open')) { | |
| if (!navMenu.contains(e.target)) { | |
| e.preventDefault(); | |
| } | |
| } | |
| }, { passive: false }); | |
| function checkAuthStatus() { | |
| const token = localStorage.getItem('dashx_token'); | |
| if (token) { | |
| const navMenuEl = document.querySelector('.nav-menu'); | |
| if (navMenuEl) { | |
| navMenuEl.innerHTML = ` | |
| <a href="/dashboard" class="nav-link"><i class="fas fa-chart-line"></i> Dashboard</a> | |
| <a href="/profile" class="nav-link"><i class="fas fa-user"></i> Profile</a> | |
| <a href="#" class="nav-link" id="logoutBtn"><i class="fas fa-sign-out-alt"></i> Logout</a> | |
| `; | |
| attachNavLinkListeners(); | |
| } | |
| } else { | |
| attachNavLinkListeners(); | |
| } | |
| } | |
| function attachNavLinkListeners() { | |
| document.querySelectorAll('.nav-link').forEach(link => { | |
| link.removeEventListener('click', handleNavLinkClick); | |
| link.addEventListener('click', handleNavLinkClick); | |
| }); | |
| const logoutBtn = document.getElementById('logoutBtn'); | |
| if (logoutBtn) { | |
| logoutBtn.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| closeMenu(); | |
| setTimeout(() => { | |
| logout(); | |
| }, 400); | |
| }); | |
| } | |
| } | |
| function handleNavLinkClick(e) { | |
| const href = this.getAttribute('href'); | |
| if (!href || href === '#' || this.id === 'logoutBtn') { | |
| return; | |
| } | |
| if (href.startsWith('#')) { | |
| e.preventDefault(); | |
| const target = document.querySelector(href); | |
| if (target) { | |
| closeMenu(); | |
| setTimeout(() => { | |
| target.scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| }, 400); | |
| } | |
| } else { | |
| e.preventDefault(); | |
| closeMenu(); | |
| setTimeout(() => { | |
| window.location.href = href; | |
| }, 400); | |
| } | |
| } | |
| async function loadStats() { | |
| try { | |
| const totalUsersEl = document.getElementById('totalUsers'); | |
| const totalRequestsEl = document.getElementById('totalRequests'); | |
| const todayRequestsEl = document.getElementById('todayRequests'); | |
| if (totalUsersEl) { | |
| totalUsersEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; | |
| } | |
| if (totalRequestsEl) { | |
| totalRequestsEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; | |
| } | |
| if (todayRequestsEl) { | |
| todayRequestsEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; | |
| } | |
| const response = await fetch('/api/stats', { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| } | |
| }); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| if (data.success && data.stats) { | |
| const stats = data.stats; | |
| if (totalUsersEl) { | |
| totalUsersEl.textContent = formatNumber(stats.totalUsers) || '0'; | |
| } | |
| if (totalRequestsEl) { | |
| totalRequestsEl.textContent = formatNumber(stats.totalRequests) || '0'; | |
| } | |
| if (todayRequestsEl) { | |
| todayRequestsEl.textContent = formatNumber(stats.todayRequests) || '0'; | |
| } | |
| animateNumbers(); | |
| } else { | |
| throw new Error(data.error || 'Failed to load stats'); | |
| } | |
| } else { | |
| throw new Error(`HTTP ${response.status}: ${response.statusText}`); | |
| } | |
| } catch (error) { | |
| console.error('Error loading stats:', error); | |
| const totalUsersEl = document.getElementById('totalUsers'); | |
| const totalRequestsEl = document.getElementById('totalRequests'); | |
| const todayRequestsEl = document.getElementById('todayRequests'); | |
| if (totalUsersEl) totalUsersEl.textContent = '0'; | |
| if (totalRequestsEl) totalRequestsEl.textContent = '0'; | |
| if (todayRequestsEl) todayRequestsEl.textContent = '0'; | |
| } | |
| } | |
| function formatNumber(num) { | |
| if (typeof num !== 'number') return '0'; | |
| if (num >= 1000000) { | |
| return (num / 1000000).toFixed(1) + 'M'; | |
| } else if (num >= 1000) { | |
| return (num / 1000).toFixed(1) + 'K'; | |
| } | |
| return num.toLocaleString(); | |
| } | |
| function animateNumbers() { | |
| const numbers = document.querySelectorAll('.stat-number'); | |
| numbers.forEach(number => { | |
| if (number.textContent.includes('Error') || number.textContent.includes('fa-spin')) { | |
| return; | |
| } | |
| const finalText = number.textContent; | |
| let targetValue = 0; | |
| if (finalText.includes('K')) { | |
| targetValue = parseFloat(finalText) * 1000; | |
| } else if (finalText.includes('M')) { | |
| targetValue = parseFloat(finalText) * 1000000; | |
| } else { | |
| targetValue = parseInt(finalText.replace(/,/g, '')) || 0; | |
| } | |
| if (targetValue === 0) return; | |
| let current = 0; | |
| const increment = Math.max(1, Math.ceil(targetValue / 50)); | |
| number.textContent = '0'; | |
| const timer = setInterval(() => { | |
| current += increment; | |
| if (current >= targetValue) { | |
| current = targetValue; | |
| clearInterval(timer); | |
| number.textContent = finalText; | |
| } else { | |
| if (targetValue >= 1000000) { | |
| number.textContent = (current / 1000000).toFixed(1) + 'M'; | |
| } else if (targetValue >= 1000) { | |
| number.textContent = (current / 1000).toFixed(1) + 'K'; | |
| } else { | |
| number.textContent = current.toLocaleString(); | |
| } | |
| } | |
| }, 30); | |
| }); | |
| } | |
| function logout() { | |
| localStorage.removeItem('dashx_token'); | |
| localStorage.removeItem('dashx_user'); | |
| window.location.href = '/'; | |
| } | |
| function addLiveUpdates() { | |
| const statsCards = document.querySelectorAll('.stat-card'); | |
| statsCards.forEach(card => { | |
| card.addEventListener('mouseenter', () => { | |
| card.style.transform = 'translateY(-5px)'; | |
| card.style.boxShadow = '0 8px 25px rgba(0,0,0,0.15)'; | |
| }); | |
| card.addEventListener('mouseleave', () => { | |
| card.style.transform = 'translateY(0)'; | |
| card.style.boxShadow = '0 4px 12px rgba(0,0,0,0.1)'; | |
| }); | |
| }); | |
| } | |
| function addRefreshButton() { | |
| const refreshBtn = document.createElement('button'); | |
| refreshBtn.innerHTML = '<i class="fas fa-sync-alt"></i>'; | |
| refreshBtn.title = 'Refresh Statistics'; | |
| refreshBtn.style.cssText = ` | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| width: 50px; | |
| height: 50px; | |
| border-radius: 50%; | |
| border: none; | |
| background: linear-gradient(45deg, #853030, #a64545); | |
| color: white; | |
| font-size: 1.2rem; | |
| cursor: pointer; | |
| box-shadow: 0 4px 12px rgba(133, 48, 48, 0.3); | |
| transition: all 0.3s ease; | |
| z-index: 1000; | |
| `; | |
| refreshBtn.addEventListener('click', () => { | |
| refreshBtn.style.transform = 'rotate(360deg)'; | |
| loadStats(); | |
| setTimeout(() => { | |
| refreshBtn.style.transform = 'rotate(0deg)'; | |
| }, 500); | |
| }); | |
| refreshBtn.addEventListener('mouseenter', () => { | |
| refreshBtn.style.transform = 'scale(1.1)'; | |
| refreshBtn.style.boxShadow = '0 6px 20px rgba(133, 48, 48, 0.4)'; | |
| }); | |
| refreshBtn.addEventListener('mouseleave', () => { | |
| refreshBtn.style.transform = 'scale(1)'; | |
| refreshBtn.style.boxShadow = '0 4px 12px rgba(133, 48, 48, 0.3)'; | |
| }); | |
| document.body.appendChild(refreshBtn); | |
| } | |
| function initializeEnhancements() { | |
| addLiveUpdates(); | |
| addRefreshButton(); | |
| } | |
| function addLoadingStates() { | |
| const style = document.createElement('style'); | |
| style.textContent = ` | |
| .loading-pulse { | |
| animation: pulse 1.5s ease-in-out infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 1; } | |
| } | |
| .stat-card:hover .stat-number { | |
| transform: scale(1.05); | |
| transition: transform 0.2s ease; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| } | |
| function addKeyboardShortcuts() { | |
| document.addEventListener('keydown', (event) => { | |
| if (event.ctrlKey || event.metaKey) { | |
| switch (event.key) { | |
| case 'r': | |
| event.preventDefault(); | |
| loadStats(); | |
| break; | |
| case 'd': | |
| event.preventDefault(); | |
| if (localStorage.getItem('dashx_token')) { | |
| window.location.href = '/dashboard'; | |
| } | |
| break; | |
| } | |
| } | |
| if (event.key === 'F5') { | |
| event.preventDefault(); | |
| loadStats(); | |
| } | |
| if (event.key === 'Escape') { | |
| closeMenu(); | |
| } | |
| }); | |
| } | |
| document.addEventListener('DOMContentLoaded', function() { | |
| preventHorizontalScroll(); | |
| loadStats(); | |
| checkAuthStatus(); | |
| attachNavLinkListeners(); | |
| setInterval(loadStats, 30000); | |
| setTimeout(() => { | |
| initializeEnhancements(); | |
| addLoadingStates(); | |
| addKeyboardShortcuts(); | |
| }, 1000); | |
| }); |