import type { QuotaWindow } from "@paperclipai/shared"; import { cn, quotaSourceDisplayName } from "@/lib/utils"; interface CodexSubscriptionPanelProps { windows: QuotaWindow[]; source?: string | null; error?: string | null; } const WINDOW_PRIORITY = [ "5hlimit", "weeklylimit", "credits", ] as const; function normalizeLabel(text: string): string { return text.toLowerCase().replace(/[^a-z0-9]+/g, ""); } function orderedWindows(windows: QuotaWindow[]): QuotaWindow[] { return [...windows].sort((a, b) => { const aBase = normalizeLabel(a.label).replace(/^gpt53codexspark/, ""); const bBase = normalizeLabel(b.label).replace(/^gpt53codexspark/, ""); const aIndex = WINDOW_PRIORITY.indexOf(aBase as (typeof WINDOW_PRIORITY)[number]); const bIndex = WINDOW_PRIORITY.indexOf(bBase as (typeof WINDOW_PRIORITY)[number]); return (aIndex === -1 ? WINDOW_PRIORITY.length : aIndex) - (bIndex === -1 ? WINDOW_PRIORITY.length : bIndex); }); } function detailText(window: QuotaWindow): string | null { if (typeof window.detail === "string" && window.detail.trim().length > 0) return window.detail.trim(); if (!window.resetsAt) return null; const formatted = new Date(window.resetsAt).toLocaleString(undefined, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit", timeZoneName: "short", }); return `Resets ${formatted}`; } function fillClass(usedPercent: number | null): string { if (usedPercent == null) return "bg-zinc-700"; if (usedPercent >= 90) return "bg-red-400"; if (usedPercent >= 70) return "bg-amber-400"; return "bg-primary/70"; } function isModelSpecific(label: string): boolean { const normalized = normalizeLabel(label); return normalized.includes("gpt53codexspark") || normalized.includes("gpt5"); } export function CodexSubscriptionPanel({ windows, source = null, error = null, }: CodexSubscriptionPanelProps) { const ordered = orderedWindows(windows); const accountWindows = ordered.filter((window) => !isModelSpecific(window.label)); const modelWindows = ordered.filter((window) => isModelSpecific(window.label)); return (
Codex subscription
Live Codex quota windows.
{source ? ( {quotaSourceDisplayName(source)} ) : null}
{error ? (
{error}
) : null}
Account windows
{accountWindows.map((window) => ( ))}
{modelWindows.length > 0 ? (
Model windows
{modelWindows.map((window) => ( ))}
) : null}
); } function QuotaWindowRow({ window }: { window: QuotaWindow }) { const detail = detailText(window); if (window.usedPercent == null) { return (
{window.label}
{window.valueLabel ? (
{window.valueLabel}
) : null}
{detail ? (
{detail}
) : null}
); } return (
{window.label}
{detail ? (
{detail}
) : null}
{window.usedPercent}% used
); }