import apiClient from './apiClient.js';
class AdminDashboard {
constructor() {
this.providersContainer = document.querySelector('[data-admin-providers]');
this.tableBody = document.querySelector('[data-admin-table]');
this.refreshBtn = document.querySelector('[data-admin-refresh]');
this.healthBadge = document.querySelector('[data-admin-health]');
this.latencyChartCanvas = document.querySelector('#provider-latency-chart');
this.statusChartCanvas = document.querySelector('#provider-status-chart');
this.latencyChart = null;
this.statusChart = null;
}
init() {
this.loadProviders();
if (this.refreshBtn) {
this.refreshBtn.addEventListener('click', () => this.loadProviders());
}
}
async loadProviders() {
if (this.tableBody) {
this.tableBody.innerHTML = '
| Loading providers... |
';
}
const result = await apiClient.getProviders();
if (!result.ok) {
this.providersContainer.innerHTML = `${result.error}
`;
this.tableBody.innerHTML = '';
return;
}
const providers = result.data || [];
this.renderCards(providers);
this.renderTable(providers);
this.renderCharts(providers);
}
renderCards(providers) {
if (!this.providersContainer) return;
const healthy = providers.filter((p) => p.status === 'healthy').length;
const failing = providers.length - healthy;
const avgLatency = (
providers.reduce((sum, provider) => sum + Number(provider.latency || 0), 0) / (providers.length || 1)
).toFixed(0);
this.providersContainer.innerHTML = `
Total Providers
${providers.length}
Avg Latency
${avgLatency} ms
`;
if (this.healthBadge) {
this.healthBadge.dataset.state = failing ? 'warn' : 'ok';
this.healthBadge.querySelector('span').textContent = failing ? 'degraded' : 'optimal';
}
}
renderTable(providers) {
if (!this.tableBody) return;
this.tableBody.innerHTML = providers
.map(
(provider) => `
| ${provider.name} |
${provider.category || '—'} |
${provider.latency || '—'} ms |
${provider.status}
|
${provider.endpoint || provider.url || ''} |
`,
)
.join('');
}
renderCharts(providers) {
if (this.latencyChartCanvas) {
const labels = providers.map((p) => p.name);
const data = providers.map((p) => p.latency || 0);
if (this.latencyChart) this.latencyChart.destroy();
this.latencyChart = new Chart(this.latencyChartCanvas, {
type: 'bar',
data: {
labels,
datasets: [
{
label: 'Latency (ms)',
data,
backgroundColor: '#38bdf8',
},
],
},
options: {
plugins: { legend: { display: false } },
scales: {
x: { ticks: { color: 'var(--text-muted)' } },
y: { ticks: { color: 'var(--text-muted)' } },
},
},
});
}
if (this.statusChartCanvas) {
const healthy = providers.filter((p) => p.status === 'healthy').length;
const degraded = providers.length - healthy;
if (this.statusChart) this.statusChart.destroy();
this.statusChart = new Chart(this.statusChartCanvas, {
type: 'doughnut',
data: {
labels: ['Healthy', 'Degraded'],
datasets: [
{
data: [healthy, degraded],
backgroundColor: ['#22c55e', '#f59e0b'],
},
],
},
options: {
plugins: { legend: { labels: { color: 'var(--text-primary)' } } },
},
});
}
}
}
window.addEventListener('DOMContentLoaded', () => {
const dashboard = new AdminDashboard();
dashboard.init();
});