dv/frontend/src/frameworks/components/charts/ChartRenderer.tsx

46 lines
1.6 KiB
TypeScript

'use client';
import React, { useMemo } from 'react';
import { type ChartInstance } from '@/domain/entities/ChartInstance';
import { chartRenderer } from '@/frameworks/di/container';
import { EChartsBase } from './EChartsBase';
import { KPICard } from './KPICard';
import { DataTable } from './DataTable';
export interface ChartRendererProps {
chart: ChartInstance;
data: Record<string, any>[];
}
export const ChartRenderer: React.FC<ChartRendererProps> = ({ chart, data }) => {
// Use JSON key to force recalculation when any chart property changes
const chartKey = JSON.stringify({ type: chart.type, bindings: chart.bindings, style: chart.style });
const echartsOption = useMemo(() => {
if (chart.type === 'kpi' || chart.type === 'data-table') return null;
if (!data.length) return null;
try {
return chartRenderer.build(chart, data);
} catch (e) {
console.warn('ECharts build error:', e);
return null;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [chartKey, data]);
switch (chart.type) {
case 'kpi':
return <KPICard chart={chart} data={data} />;
case 'data-table':
return <DataTable chart={chart} data={data} />;
default:
const borderRadius = chart.style?.background?.borderRadius ?? 0;
const overflow = borderRadius > 0 ? 'hidden' as const : undefined;
return echartsOption
? <EChartsBase option={echartsOption} style={{ width: '100%', height: '100%', minHeight: 250, borderRadius, overflow }} />
: <div style={{ padding: 16, color: '#999', textAlign: 'center' }}></div>;
}
};
export default ChartRenderer;