Files
openrouter-watcher/templates/dashboard/index.html
Luca Sacchi Ricciardi c1f47c897f feat(frontend): T44 setup FastAPI static files and templates
- Mount static files on /static endpoint
- Configure Jinja2Templates with directory structure
- Create base template with Pico.css, HTMX, Chart.js
- Create all template subdirectories (auth, dashboard, keys, tokens, profile, components)
- Create initial CSS and JS files
- Add tests for static files and templates configuration

Tests: 12 passing
Coverage: 100% on new configuration code
2026-04-07 17:58:03 +02:00

134 lines
3.2 KiB
HTML

{% extends "base.html" %}
{% block title %}Dashboard - OpenRouter Monitor{% endblock %}
{% block content %}
<h1>Dashboard</h1>
<!-- Summary Cards -->
<div class="grid">
<article>
<header>
<h3>Total Requests</h3>
</header>
<p style="font-size: 2rem; font-weight: bold;">{{ stats.total_requests | default(0) }}</p>
</article>
<article>
<header>
<h3>Total Cost</h3>
</header>
<p style="font-size: 2rem; font-weight: bold;">${{ stats.total_cost | default(0) | round(2) }}</p>
</article>
<article>
<header>
<h3>API Keys</h3>
</header>
<p style="font-size: 2rem; font-weight: bold;">{{ stats.api_keys_count | default(0) }}</p>
</article>
</div>
<!-- Charts -->
<div class="grid">
<article>
<header>
<h3>Usage Over Time</h3>
</header>
<canvas id="usageChart" height="200"></canvas>
</article>
<article>
<header>
<h3>Top Models</h3>
</header>
<canvas id="modelsChart" height="200"></canvas>
</article>
</div>
<!-- Recent Activity -->
<article>
<header>
<h3>Recent Usage</h3>
</header>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Model</th>
<th>Requests</th>
<th>Cost</th>
</tr>
</thead>
<tbody>
{% for usage in recent_usage %}
<tr>
<td>{{ usage.date }}</td>
<td>{{ usage.model }}</td>
<td>{{ usage.requests }}</td>
<td>${{ usage.cost | round(4) }}</td>
</tr>
{% else %}
<tr>
<td colspan="4" style="text-align: center;">No usage data available</td>
</tr>
{% endfor %}
</tbody>
</table>
</article>
{% endblock %}
{% block extra_scripts %}
<script>
// Usage Chart
const usageCtx = document.getElementById('usageChart').getContext('2d');
const usageData = {{ chart_data | default({"labels": [], "data": []}) | tojson }};
new Chart(usageCtx, {
type: 'line',
data: {
labels: usageData.labels || [],
datasets: [{
label: 'Requests',
data: usageData.data || [],
borderColor: '#2563eb',
backgroundColor: 'rgba(37, 99, 235, 0.1)',
fill: true
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true
}
}
}
});
// Models Chart
const modelsCtx = document.getElementById('modelsChart').getContext('2d');
const modelsData = {{ models_data | default({"labels": [], "data": []}) | tojson }};
new Chart(modelsCtx, {
type: 'doughnut',
data: {
labels: modelsData.labels || [],
datasets: [{
data: modelsData.data || [],
backgroundColor: [
'#2563eb',
'#10b981',
'#f59e0b',
'#ef4444',
'#8b5cf6'
]
}]
},
options: {
responsive: true
}
});
</script>
{% endblock %}