69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
'use client'
|
|
|
|
import {
|
|
PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer,
|
|
} from 'recharts'
|
|
import { formatCents } from '@/lib/utils/currency'
|
|
|
|
interface DataPoint {
|
|
category: string
|
|
totalCents: number
|
|
}
|
|
|
|
const COLORS = [
|
|
'#6366f1', '#22c55e', '#f59e0b', '#ef4444', '#8b5cf6',
|
|
'#14b8a6', '#f97316', '#ec4899', '#0ea5e9', '#84cc16',
|
|
]
|
|
|
|
function ChartTooltip({ active, payload }: {
|
|
active?: boolean
|
|
payload?: Array<{ name: string; value: number; payload: DataPoint }>
|
|
}) {
|
|
if (!active || !payload?.length) return null
|
|
const item = payload[0]
|
|
return (
|
|
<div className="rounded-md border bg-card p-3 shadow-md text-sm">
|
|
<p className="font-medium">{item.payload.category}</p>
|
|
<p className="text-muted-foreground">{formatCents(item.value)}</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function CategoryBreakdownChart({ data }: { data: DataPoint[] }) {
|
|
if (data.length === 0) {
|
|
return (
|
|
<div className="flex h-[320px] items-center justify-center text-sm text-muted-foreground">
|
|
No spending this month.
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<ResponsiveContainer width="100%" height={320}>
|
|
<PieChart>
|
|
<Pie
|
|
data={data}
|
|
dataKey="totalCents"
|
|
nameKey="category"
|
|
cx="50%"
|
|
cy="45%"
|
|
innerRadius={70}
|
|
outerRadius={110}
|
|
paddingAngle={2}
|
|
>
|
|
{data.map((_, i) => (
|
|
<Cell key={i} fill={COLORS[i % COLORS.length]} />
|
|
))}
|
|
</Pie>
|
|
<Tooltip content={<ChartTooltip />} />
|
|
<Legend
|
|
iconType="circle"
|
|
iconSize={8}
|
|
wrapperStyle={{ fontSize: 12 }}
|
|
formatter={(value) => <span className="text-foreground">{value}</span>}
|
|
/>
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
)
|
|
}
|