// Main Dashboard Controller class Dashboard { constructor() { this.currentPage = 'overview'; this.pages = {}; this.init(); } init() { // Initialize only if authenticated if (!window.authManager || !window.authManager.isAuthenticated) { return; } this.setupNavigation(); this.setupSidebar(); this.setupRefresh(); this.updateTime(); this.loadPage(this.currentPage); // Start time updates setInterval(() => this.updateTime(), 1000); } setupNavigation() { // Handle menu item clicks const menuItems = document.querySelectorAll('.menu-item'); menuItems.forEach(item => { item.addEventListener('click', (e) => { e.preventDefault(); // Get page from data attribute or href const page = item.getAttribute('data-page') || item.getAttribute('href').substring(1); // Update active state menuItems.forEach(i => i.classList.remove('active')); item.classList.add('active'); // Load page this.loadPage(page); }); }); // Handle hash changes (browser back/forward) window.addEventListener('hashchange', () => { const page = window.location.hash.substring(1) || 'overview'; this.loadPage(page); }); } setupSidebar() { const toggleBtn = document.getElementById('sidebar-toggle'); const sidebar = document.querySelector('.sidebar'); if (toggleBtn && sidebar) { toggleBtn.addEventListener('click', () => { sidebar.classList.toggle('collapsed'); // Save preference const isCollapsed = sidebar.classList.contains('collapsed'); localStorage.setItem('sidebar_collapsed', isCollapsed); }); // Load saved preference const savedState = localStorage.getItem('sidebar_collapsed'); if (savedState === 'true') { sidebar.classList.add('collapsed'); } } } setupRefresh() { const refreshBtn = document.getElementById('refresh-btn'); if (refreshBtn) { refreshBtn.addEventListener('click', () => { this.refreshCurrentPage(); }); } } updateTime() { const timeElement = document.getElementById('current-time'); if (!timeElement) return; const now = luxon.DateTime.now(); timeElement.textContent = now.toFormat('HH:mm:ss'); } async loadPage(page) { // Update current page this.currentPage = page; // Update URL hash window.location.hash = page; // Update page title this.updatePageTitle(page); // Show loading state this.showLoading(); try { // Load page content await this.loadPageContent(page); // Initialize page-specific functionality await this.initializePage(page); } catch (error) { console.error(`Error loading page ${page}:`, error); this.showError(`Failed to load ${page} page`); } finally { // Hide loading state this.hideLoading(); } } updatePageTitle(page) { const titleElement = document.getElementById('page-title'); if (!titleElement) return; const titles = { 'overview': 'Dashboard Overview', 'analytics': 'Usage Analytics', 'costs': 'Cost Management', 'clients': 'Client Management', 'providers': 'Provider Configuration', 'monitoring': 'Real-time Monitoring', 'settings': 'System Settings', 'logs': 'System Logs' }; titleElement.textContent = titles[page] || 'Dashboard'; } showLoading() { const content = document.getElementById('page-content'); if (!content) return; content.classList.add('loading'); } hideLoading() { const content = document.getElementById('page-content'); if (!content) return; content.classList.remove('loading'); } async loadPageContent(page) { const content = document.getElementById('page-content'); if (!content) return; // For now, we'll generate content dynamically // In a real app, you might fetch HTML templates or use a framework let html = ''; switch (page) { case 'overview': html = await this.getOverviewContent(); break; case 'analytics': html = await this.getAnalyticsContent(); break; case 'costs': html = await this.getCostsContent(); break; case 'clients': html = await this.getClientsContent(); break; case 'providers': html = await this.getProvidersContent(); break; case 'monitoring': html = await this.getMonitoringContent(); break; case 'settings': html = await this.getSettingsContent(); break; case 'logs': html = await this.getLogsContent(); break; default: html = '
${message}
Last 50 requests
| Time | Client | Provider | Model | Tokens | Status |
|---|
Filter and analyze usage data
| Date | Client | Provider | Model | Requests | Tokens | Cost |
|---|
Current provider pricing
| Provider | Model | Input Price | Output Price | Last Updated |
|---|
Manage API clients and tokens
| Client ID | Name | Token | Created | Last Used | Requests | Status | Actions |
|---|
Live request stream and system metrics
View and filter system logs
| Timestamp | Level | Source | Message |
|---|