import { useMemo } from 'react'; import type { DashboardOverview } from './api'; import { EmptyState } from './EmptyState'; import type { Messages } from './i18n'; export type UsageRow = DashboardOverview['usage']['rows'][number]; type RiskLevel = 'ok' | 'warn' | 'critical'; type UsageGroup = 'primary' | 'codex'; type UsageLimitWindow = 'h5' | 'd7'; export interface UsagePanelProps { overview: DashboardOverview; t: Messages; } function formatPct(value: number): string { if (value < 0) return '-'; return `${Math.round(value)}%`; } function usagePeak(row: UsageRow): number { return Math.max(row.h5pct, row.d7pct); } 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'; if (peak >= 65) return 'warn'; return 'ok'; } function usageActive(row: UsageRow): boolean { return row.name.includes('*'); } function usageLimited(row: UsageRow): boolean { return row.name.includes('!'); } function usageNameParts(row: UsageRow): { account: string; plan: string | null; } { const cleaned = row.name.replace(/[*!]/g, '').replace(/\s+/g, ' ').trim(); const parts = cleaned.split(' '); const plan = parts.at(-1) ?? null; if (plan && ['max', 'mid', 'pro', 'team'].includes(plan.toLowerCase())) { return { account: parts.slice(0, -1).join(' ') || cleaned, plan }; } return { account: cleaned, plan: null }; } function usageWindowReset(row: UsageRow, window: UsageLimitWindow): string { return (window === 'd7' ? row.d7reset : row.h5reset).trim(); } function usageBurnRate(row: UsageRow): number | null { if (row.h5pct < 0) return null; return row.h5pct / 5; } function usageSpeedLevel(rate: number | null): RiskLevel { if (rate === null) return 'ok'; if (rate >= 12) return 'critical'; if (rate >= 7) return 'warn'; return 'ok'; } function formatUsageRate(rate: number | null): string { if (rate === null) return '-'; if (rate > 0 && rate < 1) return '<1%/h'; return `${Math.round(rate)}%/h`; } function usageGroup(row: UsageRow): UsageGroup { return row.name.toLowerCase().startsWith('codex') ? 'codex' : 'primary'; } function UsageQuotaMeter({ row, rowName, window, t, }: { row: UsageRow; rowName: string; window: UsageLimitWindow; t: Messages; }) { const remaining = usageWindowRemaining(row, window); const reset = usageWindowReset(row, window); const tightest = usageLimitWindow(row) === window; const label = t.usage.quota[window]; return (