// Analytics Page Module class AnalyticsPage { constructor() { this.filters = { dateRange: '7d', client: 'all', provider: 'all' }; this.init(); } async init() { // Load data await Promise.all([ this.loadClients(), this.loadCharts(), this.loadUsageData() ]); // Setup event listeners this.setupEventListeners(); } async loadClients() { try { const clients = await window.api.get('/clients'); this.renderClientFilter(clients); } catch (error) { console.error('Error loading clients for filter:', error); } } renderClientFilter(clients) { const select = document.getElementById('client-filter'); if (!select) return; // Clear existing options except "All Clients" while (select.options.length > 1) { select.remove(1); } // Add client options clients.forEach(client => { const option = document.createElement('option'); option.value = client.id; option.textContent = client.name || client.id; select.appendChild(option); }); } async loadCharts() { try { const breakdown = await window.api.get('/analytics/breakdown'); const timeSeries = await window.api.get('/usage/time-series'); this.renderAnalyticsChart(timeSeries.series); this.renderClientsChart(breakdown.clients); this.renderModelsChart(breakdown.models); } catch (error) { console.error('Error loading analytics charts:', error); } } renderAnalyticsChart(series) { const data = { labels: series.map(s => s.time), datasets: [ { label: 'Requests', data: series.map(s => s.requests), color: '#fe8019', // orange fill: true }, { label: 'Tokens', data: series.map(s => s.tokens), color: '#b8bb26', // green fill: true, hidden: true } ] }; window.chartManager.createLineChart('analytics-chart', data); } renderClientsChart(clients) { const data = { labels: clients.map(c => c.label), datasets: [{ label: 'Requests', data: clients.map(c => c.value), color: '#83a598' // blue }] }; window.chartManager.createHorizontalBarChart('clients-chart', data); } renderModelsChart(models) { const data = { labels: models.map(m => m.label), data: models.map(m => m.value), colors: window.chartManager.defaultColors }; window.chartManager.createDoughnutChart('models-chart', data); } async loadUsageData() { try { const usageData = await window.api.get('/usage/detailed'); this.renderUsageTable(usageData); } catch (error) { console.error('Error loading usage data:', error); } } renderUsageTable(data) { const tableBody = document.querySelector('#usage-table tbody'); if (!tableBody) return; if (data.length === 0) { tableBody.innerHTML = '
${row.model}