"use client"; import { LineChart, Line, BarChart, Bar, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer, CartesianGrid, Cell, } from "recharts"; import { SERIES_COLORS } from "@/lib/report-colors"; // Re-exported for back-compat; new server-component code should import the // palette from "@/lib/report-colors" directly (see that file for why). export { SERIES_COLORS }; /** Compact Indian-currency formatter for axis ticks / tooltips (₹..K / ₹..L / ₹..Cr). */ export function formatINRShort(n: number): string { const a = Math.abs(n); if (a >= 1_00_00_000) return `₹${(n / 1_00_00_000).toFixed(1)}Cr`; if (a >= 1_00_000) return `₹${(n / 1_00_000).toFixed(1)}L`; if (a >= 1_000) return `₹${(n / 1_000).toFixed(0)}K`; return `₹${n.toFixed(0)}`; } function fullINR(n: number): string { return n.toLocaleString("en-IN", { style: "currency", currency: "INR", maximumFractionDigits: 0 }); } export interface Series { key: string; color: string; } interface ComparisonProps { kind: "lines" | "bars"; data: Record[]; xKey: string; series: Series[]; height?: number; } /** Multi-series comparison: monthly trend lines, or year-over-year grouped bars. */ export function ComparisonChart({ kind, data, xKey, series, height = 340 }: ComparisonProps) { const axis = { tick: { fontSize: 11, fill: "#737373" }, tickLine: false, axisLine: false } as const; return ( {kind === "lines" ? ( [fullINR(Number(v)), name]} /> {series.map((s) => ( ))} ) : ( [fullINR(Number(v)), name]} cursor={{ fill: "#f5f5f5" }} /> {series.map((s) => ( ))} )} ); } interface TrendProps { kind: "line" | "bar"; data: { label: string; value: number }[]; height?: number; } /** Single-series spend trend (monthly line or yearly bar). */ export function TrendChart({ kind, data, height = 300 }: TrendProps) { const axis = { tick: { fontSize: 11, fill: "#737373" }, tickLine: false, axisLine: false } as const; return ( {kind === "line" ? ( [fullINR(Number(v)), "Spend"]} /> ) : ( [fullINR(Number(v)), "Spend"]} cursor={{ fill: "#f5f5f5" }} /> )} ); } /** Horizontal top-N breakdown bars (each bar its own colour). */ export function BreakdownChart({ data, height = 300 }: { data: { label: string; value: number }[]; height?: number }) { const trimmed = data.map((d) => ({ ...d, short: d.label.length > 22 ? d.label.slice(0, 21) + "…" : d.label })); return ( [fullINR(Number(v)), "Spend"]} cursor={{ fill: "#f5f5f5" }} /> {trimmed.map((_, i) => ( ))} ); } /** Tiny inline trend sparkline (plain SVG — no chart library needed per row). */ export function Sparkline({ values, width = 90, height = 28 }: { values: number[]; width?: number; height?: number }) { if (values.length < 2) return ; const max = Math.max(...values); const min = Math.min(...values); const pad = 3; const span = max - min || 1; const pts = values.map((v, i) => { const x = pad + (i / (values.length - 1)) * (width - 2 * pad); const y = height - pad - ((v - min) / span) * (height - 2 * pad); return `${x.toFixed(1)},${y.toFixed(1)}`; }); const last = pts[pts.length - 1].split(","); return ( ); }