All files / react-base/src/components/ui pie-chart.tsx

0% Statements 0/48
0% Branches 0/1
0% Functions 0/1
0% Lines 0/48

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88                                                                                                                                                                               
import { Cell, Label, Pie, PieChart as RechartsPieChart } from "recharts";
import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@/components/ui/chart";
import { chartColor, type ChartColorIndex } from "@/config/theme";
import { cn } from "@/lib/utils";
 
export type PieChartDataPoint = Record<string, string | number> & {
  fill?: string;
};
 
type PieChartProps = {
  data: PieChartDataPoint[];
  config: ChartConfig;
  dataKey: string;
  nameKey: string;
  className?: string;
  showLegend?: boolean;
  innerRadius?: number;
  showCenterLabel?: boolean;
  centerLabel?: string;
};
 
export function PieChart({
  data,
  config,
  dataKey,
  nameKey,
  className,
  showLegend = true,
  innerRadius = 0,
  showCenterLabel = false,
  centerLabel,
}: PieChartProps) {
  const total = data.reduce((sum, item) => sum + Number(item[dataKey] ?? 0), 0);
 
  return (
    <ChartContainer config={config} className={cn("mx-auto aspect-square h-[300px] w-full max-w-[300px]", className)}>
      <RechartsPieChart>
        <ChartTooltip cursor={false} content={<ChartTooltipContent hideLabel nameKey={nameKey} />} />
        {showLegend && <ChartLegend content={<ChartLegendContent nameKey={nameKey} />} />}
        <Pie
          data={data}
          dataKey={dataKey}
          nameKey={nameKey}
          innerRadius={innerRadius}
          strokeWidth={2}
        >
          {data.map((entry, index) => (
            <Cell
              key={`cell-${index}`}
              fill={entry.fill ?? chartColor(((index % 5) + 1) as ChartColorIndex)}
            />
          ))}
          {showCenterLabel && (
            <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-2xl font-bold">
                        {total.toLocaleString()}
                      </tspan>
                      <tspan x={viewBox.cx} y={(viewBox.cy || 0) + 20} className="fill-muted-foreground text-xs">
                        {centerLabel ?? "Total"}
                      </tspan>
                    </text>
                  );
                }
              }}
            />
          )}
        </Pie>
      </RechartsPieChart>
    </ChartContainer>
  );
}