diff --git a/apps/dashboard/src/App.tsx b/apps/dashboard/src/App.tsx index 9f26f4e..2151ac8 100644 --- a/apps/dashboard/src/App.tsx +++ b/apps/dashboard/src/App.tsx @@ -150,6 +150,15 @@ function usageLimitWindow(row: UsageRow): UsageLimitWindow { return row.d7pct >= row.h5pct ? 'd7' : 'h5'; } +function usageWindowRemaining( + row: UsageRow, + window: UsageLimitWindow, +): number | null { + const pct = window === 'h5' ? row.h5pct : row.d7pct; + if (pct < 0) return null; + return Math.max(0, 100 - pct); +} + function usageRiskLevel(row: UsageRow): RiskLevel { const peak = usagePeak(row); if (peak >= 85) return 'critical'; @@ -931,6 +940,8 @@ function UsageRemainingMeter({ }) { const remaining = usageRemaining(row); const window = usageLimitWindow(row); + const h5Remaining = usageWindowRemaining(row, 'h5'); + const d7Remaining = usageWindowRemaining(row, 'd7'); const reset = usageLimitReset(row); return ( @@ -946,6 +957,18 @@ function UsageRemainingMeter({ max={100} value={remaining ?? 0} /> +
+ + {t.usage.quota.h5} + {h5Remaining === null ? '-' : formatPct(h5Remaining)} + + + + {t.usage.quota.d7} + {d7Remaining === null ? '-' : formatPct(d7Remaining)} + + +
{remaining === null ? '-' : t.usage.limitBasis[window]} {reset ? ` · ${t.usage.reset} ${reset}` : ` · ${t.usage.noReset}`} diff --git a/apps/dashboard/src/i18n.ts b/apps/dashboard/src/i18n.ts index 237e368..64ccd0c 100644 --- a/apps/dashboard/src/i18n.ts +++ b/apps/dashboard/src/i18n.ts @@ -130,6 +130,10 @@ export interface Messages { h5: string; d7: string; }; + quota: { + h5: string; + d7: string; + }; usage: string; groupPrimary: string; groupCodex: string; @@ -335,6 +339,10 @@ export const messages = { h5: '5시간 기준', d7: '7일 기준', }, + quota: { + h5: '5시간', + d7: '7일', + }, usage: '사용량', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex', @@ -524,6 +532,10 @@ export const messages = { h5: '5h basis', d7: '7d basis', }, + quota: { + h5: '5h', + d7: '7d', + }, usage: 'usage', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex', @@ -713,6 +725,10 @@ export const messages = { h5: '按5小时', d7: '按7天', }, + quota: { + h5: '5小时', + d7: '7天', + }, usage: '用量', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex', @@ -902,6 +918,10 @@ export const messages = { h5: '5時間基準', d7: '7日基準', }, + quota: { + h5: '5時間', + d7: '7日', + }, usage: '使用量', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex', diff --git a/apps/dashboard/src/styles.css b/apps/dashboard/src/styles.css index dc939c8..0d408f4 100644 --- a/apps/dashboard/src/styles.css +++ b/apps/dashboard/src/styles.css @@ -739,6 +739,46 @@ td small { gap: 5px; } +.quota-pair { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 5px; +} + +.quota-pair span { + display: grid; + min-width: 0; + gap: 3px; + padding: 5px; + border-radius: 11px; + background: rgba(43, 55, 38, 0.045); +} + +.quota-pair span.is-tight { + background: rgba(191, 95, 44, 0.11); + box-shadow: inset 0 0 0 1px rgba(191, 95, 44, 0.16); +} + +.quota-pair b, +.quota-pair em { + min-width: 0; + overflow: hidden; + font-size: 10px; + font-style: normal; + font-weight: 900; + line-height: 1; + text-overflow: ellipsis; + white-space: nowrap; +} + +.quota-pair b { + color: var(--muted); +} + +.quota-pair progress { + height: 5px; +} + .usage-speed { min-height: 54px; align-content: center; @@ -1589,6 +1629,14 @@ progress::-moz-progress-bar { white-space: nowrap; } + .quota-pair { + gap: 4px; + } + + .quota-pair span { + padding: 4px; + } + .record-card-grid { grid-template-columns: 1fr 1fr; }