Spaces:
Running
Running
File size: 5,465 Bytes
ee7d7b9 | 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import {
ExecutiveKPICard,
DonutWidget,
RegionalMatrix,
RankingOverviewPro,
MasterPortfolioTable,
TreemapWidget,
PerformerWidget
} from './VisualWidgets';
import {
BarChart, Bar, AreaChart, Area,
XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell
} from 'recharts';
interface WidgetFactoryProps {
analysis: any;
theme: any;
}
const CHART_COLORS = ['#3B82F6', '#10B981', '#F59E0B', '#8B5CF6', '#EF4444', '#06B6D4'];
export const WidgetFactory: React.FC<WidgetFactoryProps> = ({ analysis, theme }) => {
const { chart_type, widget_size, title, data } = analysis;
// CSS class for widget size
const getSizeClass = () => {
switch (widget_size) {
case 'small': return 'col-span-12 sm:col-span-6 lg:col-span-3 h-32';
case 'medium': return 'col-span-12 sm:col-span-6 lg:col-span-4 h-80';
case 'large': return 'col-span-12 lg:col-span-8 h-80';
case 'full': return 'col-span-12 h-[32rem]';
default: return 'col-span-12 sm:col-span-6 lg:col-span-4 h-64';
}
};
const renderWidget = () => {
if (!data || data.length === 0) {
return (
<div className="flex items-center justify-center p-4 border rounded-2xl h-full opacity-50" style={{ borderColor: theme.borderColor }}>
<span className="text-[10px]" style={{ color: theme.textMuted }}>No data for {title}</span>
</div>
);
}
switch (chart_type) {
case 'executive_kpi':
case 'kpi':
return <ExecutiveKPICard data={analysis} theme={theme} />;
case 'donut':
case 'donut_group':
return <DonutWidget data={analysis} theme={theme} />;
case 'ranking':
case 'ranking_pro':
return <RankingOverviewPro data={analysis} theme={theme} />;
case 'matrix':
return <RegionalMatrix data={analysis} theme={theme} />;
case 'master_table':
return <MasterPortfolioTable data={analysis} theme={theme} />;
case 'performer':
return <PerformerWidget data={analysis} theme={theme} />;
case 'treemap':
return <TreemapWidget data={analysis} theme={theme} />;
case 'bar':
return (
<div className="p-4 rounded-2xl border h-full" style={{ borderColor: theme.borderColor }}>
<h4 className="text-[11px] font-bold uppercase mb-4" style={{ color: theme.textMuted }}>{title}</h4>
<ResponsiveContainer width="100%" height="90%">
<BarChart data={data}>
<CartesianGrid strokeDasharray="3 3" stroke={theme.borderColor} vertical={false} opacity={0.5} />
<XAxis dataKey="category" hide />
<YAxis hide />
<Tooltip contentStyle={{ backgroundColor: theme.cardBg, border: `1px solid ${theme.borderColor}`, fontSize: '10px' }} />
<Bar dataKey="value" radius={[4, 4, 0, 0]}>
{data.map((_: any, i: number) => (
<Cell key={`cell-${i}`} fill={CHART_COLORS[i % CHART_COLORS.length]} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
</div>
);
case 'line':
case 'area':
return (
<div className="p-4 rounded-2xl border h-full" style={{ borderColor: theme.borderColor }}>
<h4 className="text-[11px] font-bold uppercase mb-4" style={{ color: theme.textMuted }}>{title}</h4>
<ResponsiveContainer width="100%" height="90%">
<AreaChart data={data}>
<CartesianGrid strokeDasharray="3 3" stroke={theme.borderColor} vertical={false} opacity={0.5} />
<XAxis dataKey="x" hide />
<YAxis hide />
<Tooltip contentStyle={{ backgroundColor: theme.cardBg, border: `1px solid ${theme.borderColor}`, fontSize: '10px' }} />
<Area
type="monotone"
dataKey="y"
stroke={CHART_COLORS[0]}
fill={CHART_COLORS[0]}
fillOpacity={0.1}
strokeWidth={2}
/>
</AreaChart>
</ResponsiveContainer>
</div>
);
default:
return (
<div className="p-4 border rounded-2xl h-full flex items-center justify-center" style={{ borderColor: theme.borderColor }}>
<span className="text-xs" style={{ color: theme.textMuted }}>Widget: {chart_type}</span>
</div>
);
}
};
return (
<div className={getSizeClass()}>
{renderWidget()}
</div>
);
};
|