diff --git a/apps/dashboard/src/App.tsx b/apps/dashboard/src/App.tsx index 864702d..9f26f4e 100644 --- a/apps/dashboard/src/App.tsx +++ b/apps/dashboard/src/App.tsx @@ -28,6 +28,7 @@ type UsageRow = DashboardOverview['usage']['rows'][number]; type InboxItem = DashboardOverview['inbox'][number]; type RiskLevel = 'ok' | 'warn' | 'critical'; type UsageGroup = 'primary' | 'codex'; +type UsageLimitWindow = 'h5' | 'd7'; type DashboardView = 'usage' | 'inbox' | 'health' | 'rooms' | 'scheduled'; type TaskGroupKey = 'watchers' | 'scheduled' | 'paused' | 'completed'; type TaskResultTone = 'ok' | 'fail' | 'none'; @@ -145,6 +146,10 @@ function usageRemaining(row: UsageRow): number | null { return Math.max(0, 100 - peak); } +function usageLimitWindow(row: UsageRow): UsageLimitWindow { + return row.d7pct >= row.h5pct ? 'd7' : 'h5'; +} + function usageRiskLevel(row: UsageRow): RiskLevel { const peak = usagePeak(row); if (peak >= 85) return 'critical'; @@ -174,7 +179,7 @@ function usageNameParts(row: UsageRow): { } function usageLimitReset(row: UsageRow): string { - return (row.d7pct >= row.h5pct ? row.d7reset : row.h5reset).trim(); + return (usageLimitWindow(row) === 'd7' ? row.d7reset : row.h5reset).trim(); } function usageBurnRate(row: UsageRow): number | null { @@ -925,6 +930,7 @@ function UsageRemainingMeter({ t: Messages; }) { const remaining = usageRemaining(row); + const window = usageLimitWindow(row); const reset = usageLimitReset(row); return ( @@ -940,7 +946,10 @@ function UsageRemainingMeter({ max={100} value={remaining ?? 0} /> - {reset ? `${t.usage.reset} ${reset}` : t.usage.noReset} + + {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 0f96e07..237e368 100644 --- a/apps/dashboard/src/i18n.ts +++ b/apps/dashboard/src/i18n.ts @@ -126,6 +126,10 @@ export interface Messages { inUse: string; reset: string; noReset: string; + limitBasis: { + h5: string; + d7: string; + }; usage: string; groupPrimary: string; groupCodex: string; @@ -327,6 +331,10 @@ export const messages = { inUse: '사용중', reset: '리셋', noReset: '리셋 없음', + limitBasis: { + h5: '5시간 기준', + d7: '7일 기준', + }, usage: '사용량', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex', @@ -512,6 +520,10 @@ export const messages = { inUse: 'in use', reset: 'reset', noReset: 'no reset', + limitBasis: { + h5: '5h basis', + d7: '7d basis', + }, usage: 'usage', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex', @@ -697,6 +709,10 @@ export const messages = { inUse: '使用中', reset: '重置', noReset: '无重置', + limitBasis: { + h5: '按5小时', + d7: '按7天', + }, usage: '用量', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex', @@ -882,6 +898,10 @@ export const messages = { inUse: '使用中', reset: 'リセット', noReset: 'リセットなし', + limitBasis: { + h5: '5時間基準', + d7: '7日基準', + }, usage: '使用量', groupPrimary: 'Claude / Kimi', groupCodex: 'Codex',