'use client'; import type { CSSProperties } from 'react'; import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from 'recharts'; import type { TodayChartBucket } from '@/types/today'; import { TodayChartFrame } from '@/components/ui/today/TodayChartFrame'; import { chartRankColor, TODAY_CHART_TOOLTIP_STYLE, } from '@/components/today/chart-theme'; interface TodayDonutChartBaseProps { data: TodayChartBucket[]; labelForCode: (code: string) => string; colorForCode?: (code: string, index: number) => string; swatchStyleForCode?: (code: string, index: number) => CSSProperties; } interface TodayDonutChartProps extends TodayDonutChartBaseProps { variant?: 'donut' | 'pie'; /** Inline legend + chart row (legacy). Prefer TodayDonutChartLegend + sidePanelLayout. */ sideLegend?: boolean; } function useDonutChartModel({ data, labelForCode, colorForCode, swatchStyleForCode, }: TodayDonutChartBaseProps) { const chartData = data.map((item) => ({ ...item, displayLabel: labelForCode(item.code), })); const resolveColor = (code: string, index: number) => colorForCode?.(code, index) ?? chartRankColor(index); const resolveSwatchStyle = (code: string, index: number): CSSProperties => swatchStyleForCode?.(code, index) ?? { backgroundColor: resolveColor(code, index), borderColor: 'rgba(0, 0, 0, 0.18)', }; return { chartData, resolveColor, resolveSwatchStyle }; } export function TodayDonutChartLegend({ data, labelForCode, colorForCode, swatchStyleForCode, }: TodayDonutChartBaseProps) { const { chartData, resolveSwatchStyle } = useDonutChartModel({ data, labelForCode, colorForCode, swatchStyleForCode, }); const rowClass = 'flex h-4 items-center text-xs leading-none'; return (
{chartData.map((entry, index) => ( ))}
{chartData.map((entry) => ( {entry.displayLabel} ))}
{chartData.map((entry) => ( {entry.count} ))}
); } export function TodayDonutChart({ data, labelForCode, colorForCode, swatchStyleForCode, variant = 'donut', sideLegend = false, }: TodayDonutChartProps) { const { chartData, resolveColor } = useDonutChartModel({ data, labelForCode, colorForCode, swatchStyleForCode, }); const innerRadius = variant === 'pie' ? 0 : '62%'; const outerRadius = variant === 'pie' ? '88%' : 92; const pieChart = ( {chartData.map((entry, index) => ( ))} { const row = item?.payload as TodayChartBucket | undefined; return [value, row ? labelForCode(row.code) : '']; }} /> ); if (sideLegend) { return (
{pieChart}
); } return {pieChart}; }