69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
'use client'
|
|
|
|
import {
|
|
AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer,
|
|
} from 'recharts'
|
|
import { formatCents, formatCentsAbbrev } from '@/lib/utils/currency'
|
|
|
|
interface DataPoint {
|
|
label: string
|
|
totalCents: number
|
|
}
|
|
|
|
function ChartTooltip({ active, payload, label }: {
|
|
active?: boolean
|
|
payload?: Array<{ value: number }>
|
|
label?: string
|
|
}) {
|
|
if (!active || !payload?.length) return null
|
|
return (
|
|
<div className="rounded-md border bg-card p-3 shadow-md text-sm">
|
|
<p className="font-medium mb-1">{label}</p>
|
|
<p className="text-primary">{formatCents(payload[0].value)}</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function NetWorthTrendChart({ data }: { data: DataPoint[] }) {
|
|
if (data.length === 0) {
|
|
return (
|
|
<div className="flex h-[300px] items-center justify-center text-sm text-muted-foreground">
|
|
No snapshot data yet — upload transactions to populate this chart.
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<ResponsiveContainer width="100%" height={300}>
|
|
<AreaChart data={data} margin={{ top: 4, right: 16, left: 16, bottom: 0 }}>
|
|
<defs>
|
|
<linearGradient id="netWorthGradient" x1="0" y1="0" x2="0" y2="1">
|
|
<stop offset="5%" stopColor="#6366f1" stopOpacity={0.3} />
|
|
<stop offset="95%" stopColor="#6366f1" stopOpacity={0} />
|
|
</linearGradient>
|
|
</defs>
|
|
<CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
|
|
<XAxis dataKey="label" tick={{ fontSize: 12 }} tickLine={false} axisLine={false} />
|
|
<YAxis
|
|
tickFormatter={formatCentsAbbrev}
|
|
tick={{ fontSize: 12 }}
|
|
tickLine={false}
|
|
axisLine={false}
|
|
width={64}
|
|
/>
|
|
<Tooltip content={<ChartTooltip />} />
|
|
<Area
|
|
type="monotone"
|
|
dataKey="totalCents"
|
|
name="Net Worth"
|
|
stroke="#6366f1"
|
|
strokeWidth={2}
|
|
fill="url(#netWorthGradient)"
|
|
dot={false}
|
|
activeDot={{ r: 4 }}
|
|
/>
|
|
</AreaChart>
|
|
</ResponsiveContainer>
|
|
)
|
|
}
|