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;
}