"use client"; import { useTranslations } from "next-intl"; import { RoundPageContainer } from "../../../components"; import { Card, CardContent, CardHeader, CardTitle } from "../../../shadcnui"; import { cn } from "../../../utils"; import { useTokenUsageReport } from "../contexts/TokenUsageReportContext"; import { TokenUsageRankedBar } from "./TokenUsageRankedBar"; import { TokenUsageReportTiles, type TokenUsageBalances } from "./TokenUsageReportTiles"; import { TokenUsageTimelineChart } from "./TokenUsageTimelineChart"; type Props = { /** * The caller's own credit balances. Supplied by the host app, which reads them * from its CurrentUserContext — the package has no access to that context. */ balances?: TokenUsageBalances | null; }; /** * Page body for the self-service token-usage dashboard. * * Stateless by design — every value comes from useTokenUsageReport(). The filter * bar is deliberately NOT here: it belongs to the page title bar, which * RoundPageContainer fills from SharedContext, so the provider publishes it. * * The timeline and the ranked bars are the PACKAGE'S EXISTING components, used * verbatim. They take the same six metric getters the report interfaces were * given, which is what makes that reuse possible. */ export function TokenUsageReportContainer({ balances = null }: Props) { const t = useTranslations(); const { summary, timeline, byOperation, byTarget, isLoading, error, targetPanelTitleKey } = useTokenUsageReport(); if (error) { return (

{error}

); } // Loading renders nothing in the body: the title bar (with the filter bar) is // already mounted, so a spinner would only make the controls jump on arrival. if (isLoading) return ; const emptyLabel = t("token_usage.report.no_data"); // The panel needs both a title the host app owns and rows to put under it. const targetTitle = targetPanelTitleKey && byTarget.length > 0 ? t(targetPanelTitleKey) : undefined; return (
{t("token_usage.report.usage_over_time")}
{t("token_usage.report.by_operation")} {/* Operation types are vocabulary the host app translates, unlike the target panel's rows, which carry entity NAMES. */} {targetTitle && ( {targetTitle} )}
); }