import { useTranslation } from "react-i18next"; import { BarChart, Bar, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer, CartesianGrid, } from "recharts"; import type { CategoryDelta } from "../../shared/types"; export interface ComparePeriodChartProps { rows: CategoryDelta[]; previousLabel: string; currentLabel: string; } function formatCurrency(amount: number, language: string): string { return new Intl.NumberFormat(language === "fr" ? "fr-CA" : "en-CA", { style: "currency", currency: "CAD", maximumFractionDigits: 0, }).format(amount); } export default function ComparePeriodChart({ rows, previousLabel, currentLabel, }: ComparePeriodChartProps) { const { t, i18n } = useTranslation(); // The chart stays a spending view: the income-statement result (revenues + // result lines, Issue #253) lives in the table, so keep only expense leaves // here — mixing revenue bars into the same axis would misread. Drop subtotal // (is_parent) rows too so a group is not double-counted against its own // leaves. Sorted by current amount (largest spending first) for a top-down // read of the biggest movers. const chartData = rows .filter((r) => !r.is_parent && (r.category_type ?? "expense") === "expense") .sort((a, b) => b.currentAmount - a.currentAmount) .map((r) => ({ name: r.categoryName, previousAmount: r.previousAmount, currentAmount: r.currentAmount, color: r.categoryColor, })); // Empty when there is no data at all, or when the period is pure // income/transfers (no expense bars to draw) — avoid rendering bare axes. if (chartData.length === 0) { return (