"use client"; import * as React from "react"; import { ArrowDownRight, ArrowUpRight } from "lucide-react"; import { Skeleton } from "@/components/ui/misc"; import { Tooltip } from "@/components/ui/tooltip"; import { cn, formatUsd, formatTokens, formatNumber, formatMs } from "@/lib/utils"; import { formatPercent } from "@/lib/client/humanize"; import { Sparkline } from "./charts"; import type { UsageKpis, UsageProjection, UsageSeriesPoint } from "./types"; /** * Stat tile contract (dataviz): label (sentence case) · value (semibold, proportional figures, * auto-compact) · optional delta (signed, vs the previous period; colour = direction × whether up is good) * · optional sparkline (de-emphasised). */ export function KpiTile({ label, value, hint, delta, upIsGood = true, spark, sparkColor, className, tooltip }: { label: string; value: React.ReactNode; hint?: React.ReactNode; delta?: number | null; upIsGood?: boolean; spark?: number[]; sparkColor?: string; className?: string; tooltip?: string }) { const showDelta = typeof delta === "number" && Number.isFinite(delta) && Math.abs(delta) >= 0.5; const good = showDelta ? (delta! > 0) === upIsGood : true; const inner = (

{label}

{spark ? : null}

{value}

{showDelta ? ( {delta! > 0 ? : } {Math.abs(delta!).toFixed(delta! >= 100 ? 0 : 1)}% ) : null} {hint ? {hint} : null}
); return tooltip ? (
{inner}
) : ( inner ); } export function KpiSkeleton({ count = 8 }: { count?: number }) { return (
{Array.from({ length: count }).map((_, i) => ( ))}
); } export function KpiGrid({ kpis, projection, series }: { kpis: UsageKpis; projection: UsageProjection; series: UsageSeriesPoint[] }) { const cost = series.map((s) => s.costUsd); const req = series.map((s) => s.requests); const tok = series.map((s) => s.inputTokens + s.outputTokens); const cacheShare = kpis.inputTokens ? kpis.cachedTokens / kpis.inputTokens : 0; return (
0 && kpis.errorRate < 0.01 ? 2 : 1)} hint={kpis.errorRate > 0.05 ? "check provider status" : kpis.requests ? "healthy" : undefined} className={cn(kpis.errorRate > 0.05 && "ring-1 ring-warning/40")} />
); }