import type { AllowanceExhaustedRefusal } from "@opengeni/sdk"; import { GaugeIcon } from "lucide-react"; import { createContext, useContext, useMemo, type ReactNode } from "react"; import { cn } from "../lib/cn"; import { allowanceLabels, allowanceResetSentence, formatAllowanceInstant, type AllowanceLabels, } from "../usage/allowance-copy"; import { useEntranceAnimation } from "./entrance"; import { useOpenGeniText } from "../messages/runtime"; /** * Replace the built-in "usage limit reached" row. Return `undefined` to keep * the default for this refusal (for example, only customize member limits). */ export type RenderAllowanceExhausted = ( refusal: AllowanceExhaustedRefusal, context: { labels: AllowanceLabels; defaultRow: ReactNode }, ) => ReactNode | undefined; type AllowancePresentation = { render: RenderAllowanceExhausted | undefined; /** Host overrides; the defaults come from the active message catalog. */ labels: Partial | undefined; }; const AllowancePresentationContext = createContext({ render: undefined, labels: undefined, }); export function AllowancePresentationProvider({ render, labels, children, }: { render: RenderAllowanceExhausted | undefined; labels: Partial | undefined; children: ReactNode; }) { const value = useMemo(() => ({ render, labels }), [render, labels]); return ( {children} ); } /** * A usage ceiling stopped further work. Calm by design: nothing failed, the * conversation is kept, and the row says who can raise the limit and when it * resets. Never the server's prose or a member identifier. */ export function AllowanceExhaustedRow({ refusal }: { refusal: AllowanceExhaustedRefusal }) { const { render, labels: overrides } = useContext(AllowancePresentationContext); const t = useOpenGeniText(); const labels = useMemo(() => allowanceLabels(t, overrides), [t, overrides]); const enter = useEntranceAnimation(); const workspace = refusal.scope === "workspace"; const defaultRow = (

{workspace ? labels.workspaceLimitReachedTitle : labels.memberLimitReachedTitle}

{workspace ? labels.workspaceRemedy : labels.memberRemedy}{" "} {allowanceResetSentence(labels, refusal.resetsAt)}

); return <>{render?.(refusal, { labels, defaultRow }) ?? defaultRow}; }