"use client"; import { useMemo } from "react"; import { useTranslations } from "next-intl"; import Card from "../Card"; import { getModelColor } from "@/shared/constants/colors"; import { fmtCompact as fmt, fmtCost } from "@/shared/utils/formatting"; import { ChartLoadingCard, DarkTooltip, useRecharts } from "./rechartsCore"; // ── DailyTrendChart (Recharts) ───────────────────────────────────────────── export function DailyTrendChart({ dailyTrend }) { const t = useTranslations("analytics"); const chartData = useMemo(() => { return (dailyTrend || []).map((d) => ({ date: d.date.slice(5), [t("chartInput")]: d.promptTokens, [t("chartOutput")]: d.completionTokens, [t("chartCost")]: d.cost || 0, })); }, [dailyTrend, t]); const hasCost = useMemo(() => chartData.some((d) => d[t("chartCost")] > 0), [chartData, t]); if (!chartData.length) { return (

{t("chartModelUsageOverTime")}

{t("chartNoData")}
); } return ; } function DailyTrendChartBody({ chartData, hasCost }) { const t = useTranslations("analytics"); const recharts = useRecharts(); if (!recharts) { return ; } const { ComposedChart, Bar, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } = recharts; return (

{t("chartModelUsageOverTime")}

{hasCost && ( `$${v.toFixed(2)}`} width={36} /> )} } cursor={{ fill: "rgba(255,255,255,0.04)" }} /> {hasCost && ( )}
{t("chartInput")} {t("chartOutput")} {hasCost && ( {t("chartCost")} ($) )}
); } // ── Cost-aware Tooltip ───────────────────────────────────────────────────── function CostTooltip({ active, payload, label, }: { active?: boolean; payload?: any[]; label?: any; }) { const t = useTranslations("analytics"); if (!active || !payload?.length) return null; return (
{label &&
{label}
} {payload.map((entry, i) => (
{entry.name}: {entry.name === t("chartCost") ? fmtCost(entry.value) : fmt(entry.value)}
))}
); } // ── WeeklyPattern (Recharts) ─────────────────────────────────────────────── function WeeklyPattern({ weeklyPattern }) { const t = useTranslations("analytics"); const chartData = useMemo(() => { return (weeklyPattern || []).map((w) => ({ day: w.day.slice(0, 3), Tokens: w.totalTokens, })); }, [weeklyPattern]); return ; } function WeeklyPatternBody({ chartData, title }) { const recharts = useRecharts(); if (!recharts) { return (

{title}

); } const { ResponsiveContainer, BarChart, XAxis, Tooltip, Bar } = recharts; return (

{title}

} cursor={{ fill: "rgba(255,255,255,0.04)" }} />
); } // ── MostActiveDay7d ──────────────────────────────────────────────────────── export function ModelOverTimeChart({ dailyByModel, modelNames }) { const t = useTranslations("analytics"); const data = useMemo(() => dailyByModel || [], [dailyByModel]); const models = useMemo(() => modelNames || [], [modelNames]); // Prepare chart data — format dates (must be before early return for rules-of-hooks) const chartData = useMemo(() => { return data.map((d) => { const row = { ...d }; // Short date label if (d.date) { const parts = d.date.split("-"); row.dateLabel = `${parts[1]}/${parts[2]}`; } return row; }); }, [data]); if (!data.length || !models.length) { return (

{t("chartModelUsageOverTime")}

{t("chartNoData")}
); } return ; } function ModelOverTimeChartBody({ chartData, models }) { const t = useTranslations("analytics"); const recharts = useRecharts(); if (!recharts) { return ; } const { AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer } = recharts; return (

{t("chartModelUsageOverTime")}

fmt(v)} axisLine={false} tickLine={false} width={50} /> } /> {models.map((m, i) => ( ))}
{models.map((m, i) => ( {m} ))}
); } // ── ProviderTable ──────────────────────────────────────────────────────────