diff --git "a/public/dashboard.js" "b/public/dashboard.js" new file mode 100644--- /dev/null +++ "b/public/dashboard.js" @@ -0,0 +1,2496 @@ +let currentUser = null; +let pluginsData = []; +let usageStats = null; +let adminUsers = []; +let currentPage = 0; +const usersPerPage = 3; +let selectedUserForRole = null; +let countdownInterval = null; +let apiStatsCharts = { + topEndpoints: null, + successFail: null, + dailyRequests: null, + hourlyTrends: null +}; + +async function loadApiStats() { + try { + const token = localStorage.getItem('dashx_token'); + const response = await fetch('/api/stats/all', { + headers: { 'Authorization': `Bearer ${token}` } + }); + + if (response.ok) { + const result = await response.json(); + if (result.success) { + updateApiStatsUI(result.stats); + renderApiStatsCharts(result.stats); + } + } + } catch (error) { + console.error('Error loading API stats:', error); + } +} + +function updateApiStatsUI(stats) { + document.getElementById('globalTotalRequests').textContent = formatNumber(stats.totalRequests); + document.getElementById('globalTodayRequests').textContent = formatNumber(stats.todayRequests); + document.getElementById('successRate').textContent = stats.successRate + '%'; + document.getElementById('failRate').textContent = stats.failRate + '%'; + + const listContainer = document.getElementById('topEndpointsList'); + if (stats.topEndpoints.length > 0) { + listContainer.innerHTML = stats.topEndpoints.map((ep, index) => ` +
Role: ${roleName.toUpperCase()}
+New Limit: ${result.newLimit}
+Expires: ${new Date(result.expiresAt).toLocaleString()}
+ ${customApiKey ? `API Key: ${result.apiKey}
` : ''} + ` + }); + + document.getElementById('selectedUserId').value = ''; + document.getElementById('selectedUserDisplay').value = ''; + document.getElementById('customApiKey').value = ''; + selectedUserForRole = null; + + loadAdminUsers(); + } else { + Swal.fire({ + icon: 'error', + title: 'Assignment Failed', + text: result.error + }); + } + } catch (error) { + Swal.fire({ + icon: 'error', + title: 'Network Error', + text: 'Failed to assign role' + }); + } +} + +async function loadServerStats() { + try { + const token = localStorage.getItem('dashx_token'); + const response = await fetch('/api/server-stats', { + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + } + }); + + const result = await response.json(); + + if (!response.ok) { + console.error('Server stats error:', result.error); + return; + } + + if (result.success) { + document.getElementById('totalUsersCount').textContent = result.stats.totalUsers || 0; + document.getElementById('regularUsersCount').textContent = result.stats.regularUsers || 0; + document.getElementById('premiumUsersCount').textContent = result.stats.premiumUsers || 0; + + document.getElementById('cheapCount').textContent = result.stats.roleDistribution.cheap || 0; + document.getElementById('premiumCount').textContent = result.stats.roleDistribution.premium || 0; + document.getElementById('vipCount').textContent = result.stats.roleDistribution.vip || 0; + document.getElementById('supremeCount').textContent = result.stats.roleDistribution.supreme || 0; + + document.getElementById('dbSize').textContent = result.stats.database.size || '0 MB'; + document.getElementById('ramUsage').textContent = result.stats.system.ramUsage || '0 MB'; + document.getElementById('cpuUsage').textContent = result.stats.system.cpuUsage + '%' || '0%'; + document.getElementById('storageUsed').textContent = result.stats.system.storageUsed || '0 GB'; + + renderRoleChart(result.stats.roleDistribution); + } + } catch (error) { + console.error('Server stats error:', error); + } +} + +function renderRoleChart(roleData) { + const ctx = document.getElementById('roleChart'); + if (!ctx) return; + + if (window.roleChartInstance) { + window.roleChartInstance.destroy(); + } + + window.roleChartInstance = new Chart(ctx, { + type: 'pie', + data: { + labels: ['Regular', 'Cheap', 'Premium', 'VIP', 'Supreme'], + datasets: [{ + data: [ + roleData.regular || 0, + roleData.cheap || 0, + roleData.premium || 0, + roleData.vip || 0, + roleData.supreme || 0 + ], + backgroundColor: [ + 'rgba(108, 117, 125, 0.8)', + 'rgba(255, 193, 7, 0.8)', + 'rgba(133, 48, 48, 0.8)', + 'rgba(255, 215, 0, 0.8)', + 'rgba(138, 43, 226, 0.8)' + ], + borderWidth: 2, + borderColor: 'rgba(255, 255, 255, 0.2)' + }] + }, + options: { + responsive: true, + maintainAspectRatio: true, + plugins: { + legend: { + position: 'bottom', + labels: { + color: 'rgba(255, 255, 255, 0.8)', + padding: 15, + font: { + size: 12 + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.8)', + padding: 12, + titleColor: '#fff', + bodyColor: '#fff', + borderColor: 'rgba(255, 255, 255, 0.2)', + borderWidth: 1 + } + } + } + }); +} + +document.addEventListener('DOMContentLoaded', function() { + if (!checkAuth()) return; + loadUserProfile(); + loadPlugins(); + showSection('overview'); + + const redeemTypeEl = document.getElementById('redeemType'); + if (redeemTypeEl) { + redeemTypeEl.addEventListener('change', updateRedeemFormVisibility); + updateRedeemFormVisibility(); + } + + setInterval(() => { + if (currentUser) { + loadUserProfile(); + if (currentUser.role === 'admin') { + loadAdminStats(); + } + } + }, 5000); + + setTimeout(setupAutoSave, 1000); +}); + +function checkAuth() { + const token = localStorage.getItem('dashx_token'); + const user = JSON.parse(localStorage.getItem('dashx_user') || '{}'); + + if (!token || !user.username) { + window.location.href = '/auth'; + return false; + } + + currentUser = user; + + if (user.role === 'admin') { + const adminMenu = document.getElementById('adminMenu'); + if (adminMenu) { + adminMenu.style.display = 'block'; + } + loadAdminStats(); + } + + loadServerStats(); + + return true; +} + +async function loadUserProfile() { + try { + const token = localStorage.getItem('dashx_token'); + if (!token) { + window.location.href = '/auth'; + return; + } + + const response = await fetch('/api/user/profile', { + headers: { 'Authorization': `Bearer ${token}` } + }); + + if (response.status === 401) { + localStorage.removeItem('dashx_token'); + localStorage.removeItem('dashx_user'); + window.location.href = '/auth'; + return; + } + + if (response.ok) { + const result = await response.json(); + if (result.success) { + const user = result.user; + localStorage.setItem('dashx_user', JSON.stringify(user)); + currentUser = user; + + await loadUsageStats(); + updateProfileElements(user); + + if (user.tempBanned) { + const banUntil = new Date(user.tempBanUntil); + Swal.fire({ + icon: 'warning', + title: 'Account Temporarily Banned', + html: `Your account is temporarily banned until ${banUntil.toLocaleString()}Unable to load usage statistics
+ +No API usage data yet
+ Start making API requests to see analytics here +No plugins available at the moment
+Failed to load users
+ +No users found
+Type: ${type}
`; + + if (limitValue > 0) { + benefitsHtml += `Limit Value: +${limitValue}
`; + } + + benefitsHtml += `Code Valid Until: ${new Date(codeExpired).toLocaleString()}
`; + + if (premiumExpired) { + benefitsHtml += `Premium Valid Until: ${new Date(premiumExpired).toLocaleString()}
`; + } + + await Swal.fire({ + title: "Redeem Code Created!", + html: ` +