// src/CategoryPieCharts.tsx (renamed from CategoryPieChart.tsx) import { useMemo } from 'react'; import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from 'recharts'; import { type Transaction, type Category } from '../api'; const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#AF19FF', '#FF4242', '#8884d8', '#82ca9d']; // Helper component for a single pie chart function SinglePieChart({ data, title }: { data: { name: string; value: number }[]; title: string }) { if (data.length === 0) { return (

{title}

No data to display.
); } return (

{title}

`${props.name} ${(props.percent * 100).toFixed(0)}%`} > {data.map((_entry, index) => ( ))} new Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD' }).format(value as number)} />
); } export default function CategoryPieCharts({ transactions, categories }: { transactions: Transaction[], categories: Category[] }) { // Calculate expenses data const expensesData = useMemo(() => { const spendingMap = new Map(); transactions.forEach(tx => { // Expenses are typically negative amounts in your system if (tx.amount < 0 && tx.category_ids.length > 0) { tx.category_ids.forEach(catId => { // Use absolute value for display on chart spendingMap.set(catId, (spendingMap.get(catId) || 0) + Math.abs(tx.amount)); }); } }); return Array.from(spendingMap.entries()) .map(([categoryId, total]) => ({ name: categories.find(c => c.id === categoryId)?.name || `Category #${categoryId}`, value: total, })) .sort((a, b) => b.value - a.value); // Sort descending }, [transactions, categories]); // Calculate earnings data const earningsData = useMemo(() => { const incomeMap = new Map(); transactions.forEach(tx => { // Earnings are typically positive amounts in your system if (tx.amount > 0 && tx.category_ids.length > 0) { tx.category_ids.forEach(catId => { incomeMap.set(catId, (incomeMap.get(catId) || 0) + tx.amount); }); } }); return Array.from(incomeMap.entries()) .map(([categoryId, total]) => ({ name: categories.find(c => c.id === categoryId)?.name || `Category #${categoryId}`, value: total, })) .sort((a, b) => b.value - a.value); // Sort descending }, [transactions, categories]); return (
); }