Spaces:
Build error
Build error
| import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip, Legend } from 'recharts'; | |
| const COLORS = { | |
| income: { | |
| Sales: '#4caf50', | |
| Services: '#66bb6a', | |
| Consulting: '#81c784', | |
| Subscriptions: '#a5d6a7', | |
| Refunds: '#c8e6c9', | |
| 'Other Income': '#e8f5e9', | |
| }, | |
| expense: { | |
| Supplies: '#ef5350', | |
| Equipment: '#e57373', | |
| Marketing: '#ef9a9a', | |
| Utilities: '#ffcdd2', | |
| Software: '#ffebee', | |
| Travel: '#ffcdd2', | |
| 'Professional Services': '#ef5350', | |
| Taxes: '#e57373', | |
| Other: '#ffebee', | |
| }, | |
| }; | |
| export default function CategoryChart({ transactions, type }) { | |
| const filtered = transactions.filter((t) => t.type === type); | |
| const data = filtered.reduce((acc, t) => { | |
| const existing = acc.find((item) => item.name === t.category); | |
| if (existing) { | |
| existing.value += t.amount; | |
| } else { | |
| acc.push({ name: t.category, value: t.amount }); | |
| } | |
| return acc; | |
| }, []); | |
| const total = data.reduce((sum, item) => sum + item.value, 0); | |
| if (data.length === 0) { | |
| return ( | |
| <div className="text-center py-12"> | |
| <p className="text-neutral-400">No {type} data to display</p> | |
| </div> | |
| ); | |
| } | |
| const colors = type === 'income' ? COLORS.income : COLORS.expense; | |
| return ( | |
| <div className="h-64"> | |
| <ResponsiveContainer width="100%" height="100%"> | |
| <PieChart> | |
| <Pie | |
| data={data} | |
| cx="50%" | |
| cy="50%" | |
| innerRadius={60} | |
| outerRadius={80} | |
| paddingAngle={2} | |
| dataKey="value" | |
| > | |
| {data.map((entry, index) => ( | |
| <Cell | |
| key={`cell-${index}`} | |
| fill={colors[entry.name] || '#9e9e9e'} | |
| /> | |
| ))} | |
| </Pie> | |
| <Tooltip | |
| formatter={(value) => `$${value.toLocaleString()}`} | |
| contentStyle={{ | |
| backgroundColor: '#fff', | |
| border: '1px solid #e0e0e0', | |
| borderRadius: '8px', | |
| boxShadow: '0 2px 8px rgba(0,0,0,0.1)', | |
| /> | |
| <Legend | |
| formatter={(value) => ( | |
| <span className="text-sm text-neutral-600">{value}</span> | |
| )} | |
| /> | |
| </PieChart> | |
| </ResponsiveContainer> | |
| <div className="text-center mt-2"> | |
| <span className="text-lg font-semibold text-neutral-800"> | |
| ${total.toLocaleString()} | |
| </span> | |
| <span className="text-sm text-neutral-500 ml-2">total</span> | |
| </div> | |
| </div> | |
| ); | |
| } |