Files
GopherGate/static/js/api.js
hobokenchicken 686163780c feat: major dashboard overhaul and polish
- Switched from mock data to real backend APIs.
- Implemented unified ApiClient for consistent frontend data fetching.
- Refactored dashboard structure and styles for a modern SaaS aesthetic.
- Fixed Axum 0.8+ routing and parameter syntax issues.
- Implemented real client creation/deletion and provider health monitoring.
- Synchronized WebSocket event structures between backend and frontend.
2026-02-26 15:40:12 -05:00

91 lines
2.2 KiB
JavaScript

// Unified API client for the dashboard
class ApiClient {
constructor() {
this.baseUrl = '/api';
}
async request(path, options = {}) {
const url = `${this.baseUrl}${path}`;
const headers = {
'Content-Type': 'application/json',
...options.headers
};
// Add auth token if available
if (window.authManager && window.authManager.token) {
headers['Authorization'] = `Bearer ${window.authManager.token}`;
}
try {
const response = await fetch(url, {
...options,
headers
});
const result = await response.json();
if (!response.ok || !result.success) {
throw new Error(result.error || `HTTP error! status: ${response.status}`);
}
return result.data;
} catch (error) {
console.error(`API Request failed (${path}):`, error);
throw error;
}
}
async get(path) {
return this.request(path, { method: 'GET' });
}
async post(path, body) {
return this.request(path, {
method: 'POST',
body: JSON.stringify(body)
});
}
async put(path, body) {
return this.request(path, {
method: 'PUT',
body: JSON.stringify(body)
});
}
async delete(path) {
return this.request(path, { method: 'DELETE' });
}
// Helper for formatting large numbers
formatNumber(num) {
if (num >= 1000000) {
return (num / 1000000).toFixed(1) + 'M';
}
if (num >= 1000) {
return (num / 1000).toFixed(1) + 'K';
}
return num.toString();
}
// Helper for formatting currency
formatCurrency(amount) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
maximumFractionDigits: 4
}).format(amount);
}
// Helper for relative time
formatTimeAgo(dateStr) {
if (!dateStr) return 'Never';
const date = luxon.DateTime.fromISO(dateStr);
return date.toRelative();
}
}
window.api = new ApiClient();