feat: componentes data_table y pie_chart — tabla con sorting/pagination y gráfico circular Recharts
Nuevos componentes React/TS en frontend/functions/ui/: - data_table: tabla de datos con columnas tipadas, sorting, paginación y formato personalizable - pie_chart: gráfico circular Recharts con tooltips, leyenda y paleta configurable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
PieChart as RechartsPieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer,
|
||||
} from 'recharts'
|
||||
import { cn } from '../core/cn'
|
||||
|
||||
const DEFAULT_COLORS = [
|
||||
'#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6',
|
||||
'#ec4899', '#06b6d4', '#f97316',
|
||||
]
|
||||
|
||||
interface PieChartProps {
|
||||
data: Record<string, unknown>[]
|
||||
nameKey: string
|
||||
valueKey: string
|
||||
colors?: string[]
|
||||
donut?: boolean
|
||||
innerRadius?: number
|
||||
outerRadius?: number
|
||||
showLegend?: boolean
|
||||
showLabels?: boolean
|
||||
height?: number | string
|
||||
className?: string
|
||||
valueFormatter?: (value: number) => string
|
||||
}
|
||||
|
||||
function PieChartComponent({
|
||||
data,
|
||||
nameKey,
|
||||
valueKey,
|
||||
colors = DEFAULT_COLORS,
|
||||
donut = false,
|
||||
innerRadius,
|
||||
outerRadius = 100,
|
||||
showLegend = true,
|
||||
showLabels = true,
|
||||
height = 300,
|
||||
className,
|
||||
valueFormatter = (v) => v.toLocaleString(),
|
||||
}: PieChartProps) {
|
||||
// Ensure numeric values for Recharts Pie
|
||||
const pieData = data.map(row => ({
|
||||
...row,
|
||||
[valueKey]: Number(row[valueKey]) || 0,
|
||||
}))
|
||||
|
||||
const resolvedInnerRadius = donut ? (innerRadius ?? 50) : (innerRadius ?? 0)
|
||||
|
||||
const labelRenderer = showLabels
|
||||
? ({ name, percent }: Record<string, unknown>) =>
|
||||
`${name ?? ''} ${(((percent as number) ?? 0) * 100).toFixed(0)}%`
|
||||
: undefined
|
||||
|
||||
return (
|
||||
<ResponsiveContainer width="100%" height={height} className={cn(className)}>
|
||||
<RechartsPieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
dataKey={valueKey}
|
||||
nameKey={nameKey}
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
outerRadius={outerRadius}
|
||||
innerRadius={resolvedInnerRadius}
|
||||
strokeWidth={0}
|
||||
fontSize={11}
|
||||
label={labelRenderer}
|
||||
labelLine={showLabels}
|
||||
>
|
||||
{pieData.map((_, i) => (
|
||||
<Cell key={i} fill={colors[i % colors.length]} />
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
backgroundColor: 'var(--card)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 8,
|
||||
fontSize: 12,
|
||||
}}
|
||||
formatter={(value: unknown) => [valueFormatter(value as number)]}
|
||||
/>
|
||||
{showLegend && <Legend wrapperStyle={{ fontSize: 11 }} />}
|
||||
</RechartsPieChart>
|
||||
</ResponsiveContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export const PieChart = PieChartComponent
|
||||
export type { PieChartProps }
|
||||
Reference in New Issue
Block a user