"use client"; import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from "recharts"; import { useAnimationPreferences } from "~/components/providers/animation-preferences-provider"; import { getEffectiveInvoiceStatus } from "~/lib/invoice-status"; import type { StoredInvoiceStatus } from "~/types/invoice"; interface Invoice { id: string; totalAmount: number; status: string; dueDate: Date | string; } interface InvoiceStatusChartProps { invoices: Invoice[]; } export function InvoiceStatusChart({ invoices }: InvoiceStatusChartProps) { // Process invoice data to create status breakdown const statusData = invoices.reduce( (acc, invoice) => { const effectiveStatus = getEffectiveInvoiceStatus( invoice.status as StoredInvoiceStatus, invoice.dueDate, ); acc[effectiveStatus] ??= { status: effectiveStatus, count: 0, value: 0, }; acc[effectiveStatus].count += 1; acc[effectiveStatus].value += invoice.totalAmount; return acc; }, {} as Record, ); const chartData = Object.values(statusData).map((item) => ({ ...item, name: item.status.charAt(0).toUpperCase() + item.status.slice(1), })); // Use theme-aware colors const COLORS = { draft: "hsl(0, 0%, 60%)", // neutral grey - matches monthly metrics chart sent: "hsl(217, 91%, 60%)", // vibrant blue pending: "hsl(217, 91%, 60%)", // blue paid: "hsl(142, 71%, 45%)", // vibrant green overdue: "hsl(var(--destructive))", // red }; // Animation / motion preferences const { prefersReducedMotion, animationSpeedMultiplier } = useAnimationPreferences(); const pieAnimationDuration = Math.round( 600 / (animationSpeedMultiplier || 1), ); const formatCurrency = (value: number) => { return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(value); }; const CustomTooltip = ({ active, payload, }: { active?: boolean; payload?: Array<{ payload: { name: string; count: number; value: number }; }>; }) => { if (active && payload?.length) { const data = payload[0]!.payload; return (

{data.name}

{data.count} invoice{data.count !== 1 ? "s" : ""}

{formatCurrency(data.value)}

); } return null; }; if (chartData.length === 0) { return (

No invoice data available

Status breakdown will appear here once you create invoices

); } return (
{chartData.map((entry, index) => ( ))} } />
{/* Legend */}
{chartData.map((item) => (
{item.name}

{item.count}

{formatCurrency(item.value)}

))}
); }