From 25f19b6ada4bf4dc8a2f64d4d0eb5a5b69d6cab7 Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Wed, 29 Apr 2026 09:55:25 +0200 Subject: [PATCH] Show reset date below quota progress bars in admin UI --- backend/admin.py | 2 ++ backend/schemas.py | 2 ++ frontend/src/main.jsx | 25 ++++++++++++++++++------- frontend/src/styles.css | 7 +++++++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/backend/admin.py b/backend/admin.py index ec9c314..ae72736 100644 --- a/backend/admin.py +++ b/backend/admin.py @@ -47,6 +47,8 @@ async def read_api_keys( item.tokens_used_month = usage.tokens_used_month or 0 item.requests_today = usage.requests_today or 0 item.requests_month = usage.requests_month or 0 + item.daily_reset_at = usage.daily_reset_at + item.monthly_reset_at = usage.monthly_reset_at result.append(item) return result diff --git a/backend/schemas.py b/backend/schemas.py index 15cf563..7fe788a 100644 --- a/backend/schemas.py +++ b/backend/schemas.py @@ -58,6 +58,8 @@ class APIKeyWithUsage(APIKey): tokens_used_month: int = 0 requests_today: int = 0 requests_month: int = 0 + daily_reset_at: Optional[datetime] = None + monthly_reset_at: Optional[datetime] = None class Config: from_attributes = True \ No newline at end of file diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index cc5a985..0b66f63 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -11,17 +11,28 @@ function authHeaders(token) { const fmtK = (n) => { const k = n / 1000; return k % 1 === 0 ? `${k}k` : `${k.toFixed(1)}k`; }; -function QuotaBar({ used, limit, isToken = false }) { - if (limit == null) return ; +function QuotaBar({ used, limit, isToken = false, since = null }) { + const fmt = isToken ? fmtK : (n) => n.toLocaleString('de-DE'); + const sinceLabel = since + ? new Date(since).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }) + : null; + + if (limit == null) return ( +
+ + {sinceLabel && seit {sinceLabel}} +
+ ); + const pct = Math.min(100, (used / limit) * 100); const color = pct >= 90 ? '#e74c3c' : pct >= 70 ? '#e67e22' : '#27ae60'; - const fmt = isToken ? fmtK : (n) => n.toLocaleString('de-DE'); return (
{fmt(used)} / {fmt(limit)}
+ {sinceLabel && seit {sinceLabel}}
); } @@ -400,10 +411,10 @@ function App() { {key.name} {displayKey(key.key_prefix)} {key.expires_at ? new Date(key.expires_at).toLocaleDateString('de-DE', { timeZone: 'Europe/Berlin' }) : '∞'} - - - - + + + + {key.is_active ? ( diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 333d37c..0c76504 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -246,6 +246,13 @@ tr:hover { font-size: 14px; } +.quota-since { + display: block; + font-size: 10px; + color: #aaa; + margin-top: 2px; +} + .progress-bar { height: 4px; background: #e2e8f0;