// Clients Page Module class ClientsPage { constructor() { this.clients = []; this.init(); } async init() { // Load data await Promise.all([ this.loadClients(), this.loadClientUsageChart() ]); // Setup event listeners this.setupEventListeners(); } async loadClients() { try { const data = await window.api.get('/clients'); this.clients = data; this.renderClientsTable(); } catch (error) { console.error('Error loading clients:', error); window.authManager.showToast('Failed to load clients', 'error'); } } renderClientsTable() { const tableBody = document.querySelector('#clients-table tbody'); if (!tableBody) return; if (this.clients.length === 0) { tableBody.innerHTML = 'No clients configured'; return; } tableBody.innerHTML = this.clients.map(client => { const statusClass = client.status === 'active' ? 'success' : 'secondary'; const statusIcon = client.status === 'active' ? 'check-circle' : 'clock'; const created = luxon.DateTime.fromISO(client.created_at).toFormat('MMM dd, yyyy'); return ` ${client.id} ${client.name} sk-••••${client.id.substring(client.id.length - 4)} ${created} ${client.last_used ? window.api.formatTimeAgo(client.last_used) : 'Never'} ${client.requests_count.toLocaleString()} ${client.status}
`; }).join(''); } async loadClientUsageChart() { try { const data = await window.api.get('/usage/clients'); if (!data || data.length === 0) { const canvas = document.getElementById('client-usage-chart'); if (canvas) canvas.closest('.chart-container').style.display = 'none'; return; } const chartData = { labels: data.map(item => item.client_id), datasets: [{ label: 'Requests', data: data.map(item => item.requests), color: '#6366f1' }] }; window.chartManager.createHorizontalBarChart('client-usage-chart', chartData); } catch (error) { console.error('Error loading client usage chart:', error); } } setupEventListeners() { const addBtn = document.getElementById('add-client'); if (addBtn) { addBtn.onclick = () => this.showAddClientModal(); } } showAddClientModal() { const modal = document.createElement('div'); modal.className = 'modal active'; modal.innerHTML = ` `; document.body.appendChild(modal); modal.querySelector('#confirm-create-client').onclick = async () => { const name = modal.querySelector('#new-client-name').value; const id = modal.querySelector('#new-client-id').value; if (!name) { window.authManager.showToast('Name is required', 'error'); return; } try { await window.api.post('/clients', { name, client_id: id || null }); window.authManager.showToast(`Client "${name}" created`, 'success'); modal.remove(); this.loadClients(); } catch (error) { window.authManager.showToast(error.message, 'error'); } }; } async deleteClient(id) { if (!confirm(`Are you sure you want to delete client ${id}? This cannot be undone.`)) return; try { await window.api.delete(`/clients/${id}`); window.authManager.showToast('Client deleted', 'success'); this.loadClients(); } catch (error) { window.authManager.showToast(error.message, 'error'); } } editClient(id) { window.authManager.showToast('Edit client not implemented yet', 'info'); } } window.initClients = async () => { window.clientsPage = new ClientsPage(); };