|
|
"use client"; |
|
|
|
|
|
import { |
|
|
PieChart as RechartsPieChart, |
|
|
Pie, |
|
|
Cell, |
|
|
Tooltip, |
|
|
Legend, |
|
|
ResponsiveContainer |
|
|
} from 'recharts'; |
|
|
|
|
|
interface PieChartProps { |
|
|
data: Array<{ [key: string]: any }>; |
|
|
title?: string; |
|
|
height?: number; |
|
|
donut?: boolean; |
|
|
nameKey?: string; |
|
|
valueKey?: string; |
|
|
} |
|
|
|
|
|
|
|
|
const COLORS = ['#6366f1', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4', '#ec4899', '#84cc16']; |
|
|
|
|
|
export default function PieChart({ |
|
|
data, |
|
|
title, |
|
|
height = 300, |
|
|
donut = false |
|
|
}: PieChartProps) { |
|
|
|
|
|
const total = data.reduce((sum, item) => sum + item.value, 0); |
|
|
|
|
|
return ( |
|
|
<div className="w-full bg-white rounded-xl border border-slate-100 p-4 shadow-sm"> |
|
|
{title && ( |
|
|
<h3 className="text-sm font-semibold text-slate-700 mb-4">{title}</h3> |
|
|
)} |
|
|
<ResponsiveContainer width="100%" height={height}> |
|
|
<RechartsPieChart> |
|
|
<Pie |
|
|
data={data} |
|
|
cx="50%" |
|
|
cy="50%" |
|
|
labelLine={false} |
|
|
label={(props: any) => |
|
|
`${props.name} (${((props.percent ?? 0) * 100).toFixed(0)}%)` |
|
|
} |
|
|
outerRadius={100} |
|
|
innerRadius={donut ? 60 : 0} |
|
|
fill="#8884d8" |
|
|
dataKey="value" |
|
|
paddingAngle={donut ? 2 : 0} |
|
|
> |
|
|
{data.map((entry, index) => ( |
|
|
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} /> |
|
|
))} |
|
|
</Pie> |
|
|
<Tooltip |
|
|
formatter={(value: number | undefined) => [ |
|
|
`${(value ?? 0).toLocaleString()} (${(((value ?? 0) / total) * 100).toFixed(1)}%)`, |
|
|
'Value' |
|
|
]} |
|
|
contentStyle={{ |
|
|
background: 'white', |
|
|
border: '1px solid #e2e8f0', |
|
|
borderRadius: '8px', |
|
|
boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)' |
|
|
}} |
|
|
/> |
|
|
<Legend |
|
|
verticalAlign="bottom" |
|
|
wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }} |
|
|
/> |
|
|
</RechartsPieChart> |
|
|
</ResponsiveContainer> |
|
|
{donut && ( |
|
|
<div className="text-center -mt-4"> |
|
|
<span className="text-2xl font-bold text-slate-700">{total.toLocaleString()}</span> |
|
|
<span className="text-sm text-slate-500 block">Total</span> |
|
|
</div> |
|
|
)} |
|
|
</div> |
|
|
); |
|
|
} |
|
|
|