document.addEventListener('DOMContentLoaded', function() {
loadStats();
checkAuthStatus();
setInterval(loadStats, 30000);
});
function checkAuthStatus() {
const token = localStorage.getItem('dashx_token');
if (token) {
const navMenu = document.querySelector('.nav-menu');
if (navMenu) {
navMenu.innerHTML = `
Dashboard
Profile
Logout
`;
}
}
}
async function loadStats() {
try {
const totalUsersEl = document.getElementById('totalUsers');
const totalRequestsEl = document.getElementById('totalRequests');
const todayRequestsEl = document.getElementById('todayRequests');
if (totalUsersEl) {
totalUsersEl.innerHTML = '';
}
if (totalRequestsEl) {
totalRequestsEl.innerHTML = '';
}
if (todayRequestsEl) {
todayRequestsEl.innerHTML = '';
}
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 = '';
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();
}
});
}
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
initializeEnhancements();
addLoadingStates();
addKeyboardShortcuts();
}, 1000);
});