diff --git a/frontend/css/style.css b/frontend/css/style.css
index efe8b61..4c1d500 100644
--- a/frontend/css/style.css
+++ b/frontend/css/style.css
@@ -108,11 +108,24 @@ header button {
transition: all 0.2s;
}
-header button:hover {
+header button:hover, .header-link-btn:hover {
background: #3a2e1f;
border-color: rgba(232, 121, 29, 0.3);
}
+.header-link-btn {
+ background: var(--bg-light);
+ color: var(--text);
+ border: 1px solid rgba(232, 121, 29, 0.15);
+ padding: 8px 16px;
+ border-radius: var(--radius-sm);
+ cursor: pointer;
+ transition: all 0.2s;
+ text-decoration: none;
+ font-size: inherit;
+ font-family: inherit;
+}
+
.theme-bar {
display: flex;
align-items: center;
diff --git a/frontend/index.html b/frontend/index.html
index 071f549..7fecafe 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -17,6 +17,7 @@
+
diff --git a/frontend/js/costs.js b/frontend/js/costs.js
index cef9e78..1b6f71b 100644
--- a/frontend/js/costs.js
+++ b/frontend/js/costs.js
@@ -50,19 +50,21 @@ function destroyChart(key) {
async function loadDashboard() {
const p = currentPeriod;
try {
- const [summary, timeline, models, categories, sessions, expensive] = await Promise.all([
+ const [summary, timeline, models, categories, sessions, expensive, tts] = await Promise.all([
fetch(`/api/costs/summary?period=${p}`).then(r => r.json()),
fetch(`/api/costs/timeline?period=${p}&group_by=session`).then(r => r.json()),
fetch(`/api/costs/models?period=${p}`).then(r => r.json()),
fetch(`/api/costs/categories?period=${p}`).then(r => r.json()),
fetch(`/api/costs/sessions?period=${p}`).then(r => r.json()),
fetch(`/api/costs/expensive?period=${p}&limit=10`).then(r => r.json()),
+ fetch(`/api/costs/tts?period=${p}`).then(r => r.json()),
]);
renderSummary(summary);
renderTimeline(timeline);
renderModels(models);
renderCategories(categories);
renderSessionBars(timeline);
+ renderTtsTable(tts);
renderExpensiveTable(expensive);
renderSessionsTable(sessions);
} catch (e) {
@@ -201,6 +203,18 @@ function renderSessionBars(data) {
});
}
+function renderTtsTable(data) {
+ const tbody = document.querySelector('#tts-table tbody');
+ tbody.innerHTML = data.map(d => `
+
+ | ${d.provider} |
+ ${d.calls.toLocaleString()} |
+ ${d.chars.toLocaleString()} |
+ ${formatCost(d.cost)} |
+
+ `).join('');
+}
+
function renderExpensiveTable(data) {
const tbody = document.querySelector('#expensive-table tbody');
tbody.innerHTML = data.map(d => `