"use client"; import { ArrowDownIcon, ArrowUpIcon } from "lucide-react"; import { useTranslations } from "next-intl"; import { Card, CardContent } from "../../../shadcnui"; import { cn } from "../../../utils"; import type { TokenUsageAdminSummaryInterface } from "../data/tokenusage-admin-summary.interface"; import type { Metric } from "../data/tokenusage-admin.types"; import { useUsageFormatters } from "../lib/formatters"; import { cacheHitPercentage, metricValue, percentageDelta, type TokenUsageMetrics } from "../lib/metrics"; type Props = { /** The six summary rows: {customer, platform, total} × {current, previous}. */ summary: TokenUsageAdminSummaryInterface[]; metric: Metric; /** True when a company filter is applied — platform spend is then meaningless. */ singleCustomerMode: boolean; }; const ZERO: TokenUsageMetrics = { cost: 0, credits: 0, tokensIn: 0, tokensOut: 0, cached: 0, calls: 0 }; /** * The KPI header of the administrative token-usage page. * * Two lead tiles carry the cost centres — customer spend and platform spend — * each with its delta against the equal-length preceding window. Three * supporting tiles below carry the totals that give those two numbers context. * * The backend always returns both windows, which is why no tile has to branch on * a missing row: an absent scope is simply zero-filled here. */ export function TokenUsageAdminTiles({ summary, metric, singleCustomerMode }: Props) { const t = useTranslations(); const { decimal, metricValue: formatValue, currency, percent } = useUsageFormatters(); const rowFor = (scope: string, window: string): TokenUsageMetrics => summary.find((r) => r.scope === scope && r.window === window) ?? ZERO; const customerCurrent = rowFor("customer", "current"); const customerPrevious = rowFor("customer", "previous"); const platformCurrent = rowFor("platform", "current"); const platformPrevious = rowFor("platform", "previous"); const totalCurrent = rowFor("total", "current"); const totalPrevious = rowFor("total", "previous"); const averagePerCall = totalCurrent.calls ? totalCurrent.cost / totalCurrent.calls : 0; const cacheHit = cacheHitPercentage(totalCurrent.cached, totalCurrent.tokensIn); return (