import type { ReactElement } from "react"; import { Card, SectionHeader, ProgressBar, type ProgressBarVariant } from "@mosaic/ui"; import type { TokenBudgetEntry } from "@/lib/api/dashboard"; export interface TokenBudgetProps { budgets?: TokenBudgetEntry[] | undefined; } /* ------------------------------------------------------------------ */ /* Helpers */ /* ------------------------------------------------------------------ */ const VARIANT_CYCLE: ProgressBarVariant[] = ["blue", "teal", "purple", "amber"]; function formatTokenCount(n: number): string { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`; if (n >= 1_000) return `${(n / 1_000).toFixed(0)}K`; return String(n); } interface ModelBudgetDisplay { id: string; label: string; usage: string; value: number; variant: ProgressBarVariant; } function mapBudgetToDisplay(entry: TokenBudgetEntry, index: number): ModelBudgetDisplay { const percent = entry.limit > 0 ? Math.round((entry.used / entry.limit) * 100) : 0; const usage = entry.limit > 0 ? `${formatTokenCount(entry.used)} / ${formatTokenCount(entry.limit)}` : "unlimited"; return { id: entry.model, label: entry.model, usage, value: percent, variant: VARIANT_CYCLE[index % VARIANT_CYCLE.length] ?? "blue", }; } /* ------------------------------------------------------------------ */ /* Components */ /* ------------------------------------------------------------------ */ interface ModelRowProps { model: ModelBudgetDisplay; } function ModelRow({ model }: ModelRowProps): ReactElement { return (
{model.label} {model.usage}
); } export function TokenBudget({ budgets }: TokenBudgetProps): ReactElement { const displayModels = budgets ? budgets.map(mapBudgetToDisplay) : []; return (
{displayModels.length > 0 ? ( displayModels.map((model) => ) ) : (
No budget data
)}
); }