in financial-data-analyst/components/ChartRenderer.tsx [218:308]
function PieChartComponent({ data }: { data: ChartData }) {
const totalValue = React.useMemo(() => {
return data.data.reduce((acc, curr) => acc + curr.value, 0);
}, [data.data]);
const chartData = data.data.map((item, index) => {
return {
...item,
// Use the same color variable pattern as other charts
fill: `hsl(var(--chart-${index + 1}))`,
};
});
return (
<Card className="flex flex-col">
<CardHeader className="items-center pb-0">
<CardTitle className="text-xl">{data.config.title}</CardTitle>
<CardDescription>{data.config.description}</CardDescription>
</CardHeader>
<CardContent className="flex-1 pb-0">
<ChartContainer
config={data.chartConfig}
className="mx-auto aspect-square max-h-[250px]"
>
<PieChart>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent hideLabel />}
/>
<Pie
data={chartData}
dataKey="value"
nameKey="segment"
innerRadius={60}
strokeWidth={5}
>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text
x={viewBox.cx}
y={viewBox.cy}
textAnchor="middle"
dominantBaseline="middle"
>
<tspan
x={viewBox.cx}
y={viewBox.cy}
className="fill-foreground text-3xl font-bold"
>
{totalValue.toLocaleString()}
</tspan>
<tspan
x={viewBox.cx}
y={(viewBox.cy || 0) + 24}
className="fill-muted-foreground"
>
{data.config.totalLabel}
</tspan>
</text>
);
}
return null;
}}
/>
</Pie>
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter className="flex-col gap-2 text-sm">
{data.config.trend && (
<div className="flex items-center gap-2 font-medium leading-none">
Trending {data.config.trend.direction} by{" "}
{data.config.trend.percentage}% this period{" "}
{data.config.trend.direction === "up" ? (
<TrendingUp className="h-4 w-4" />
) : (
<TrendingDown className="h-4 w-4" />
)}
</div>
)}
{data.config.footer && (
<div className="leading-none text-muted-foreground">
{data.config.footer}
</div>
)}
</CardFooter>
</Card>
);
}