import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, Cell, } from 'recharts'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { CHART_PALETTE, formatCurrency, formatNumber } from './chart-utils'; import type { Scenario } from '@/types/api'; interface ComparisonMetric { key: string; name: string; value: number; } interface ScenarioComparison { scenario: Scenario; metrics: ComparisonMetric[]; } interface ComparisonBarChartProps { scenarios: ScenarioComparison[]; metricKey: string; title?: string; description?: string; isCurrency?: boolean; } interface ChartDataPoint { name: string; value: number; color: string; } // Tooltip component defined outside main component interface BarTooltipProps { active?: boolean; payload?: Array<{ payload: ChartDataPoint }>; formatter?: (value: number) => string; } function BarTooltip({ active, payload, formatter }: BarTooltipProps) { if (active && payload && payload.length && formatter) { const item = payload[0].payload; return (

{item.name}

{formatter(item.value)}

); } return null; } export function ComparisonBarChart({ scenarios, metricKey, title = 'Scenario Comparison', description, isCurrency = false, }: ComparisonBarChartProps) { const chartData: ChartDataPoint[] = scenarios.map((s, index) => ({ name: s.scenario.name, value: s.metrics.find((m) => m.key === metricKey)?.value || 0, color: CHART_PALETTE[index % CHART_PALETTE.length], })); const formatter = isCurrency ? formatCurrency : formatNumber; // Find min/max for color coding const values = chartData.map((d) => d.value); const minValue = Math.min(...values); const maxValue = Math.max(...values); const getBarColor = (value: number) => { // For cost metrics, lower is better (green), higher is worse (red) // For other metrics, higher is better if (metricKey.includes('cost')) { if (value === minValue) return '#10B981'; // Green for lowest cost if (value === maxValue) return '#EF4444'; // Red for highest cost } else { if (value === maxValue) return '#10B981'; // Green for highest value if (value === minValue) return '#EF4444'; // Red for lowest value } return '#F59E0B'; // Yellow for middle values }; return ( {title} {description && (

{description}

)}
} /> {chartData.map((entry, index) => ( ))}
Best Average Worst
); } // Horizontal grouped bar chart for multi-metric comparison export function GroupedComparisonChart({ scenarios, metricKeys, title = 'Multi-Metric Comparison', description, }: { scenarios: ScenarioComparison[]; metricKeys: Array<{ key: string; name: string; isCurrency?: boolean }>; title?: string; description?: string; }) { // Transform data for grouped bar chart const chartData = scenarios.map((s) => { const dataPoint: Record = { name: s.scenario.name, }; metricKeys.forEach((mk) => { const metric = s.metrics.find((m) => m.key === mk.key); dataPoint[mk.key] = metric?.value || 0; }); return dataPoint; }); return ( {title} {description && (

{description}

)}
{metricKeys.map((mk, index) => ( ))}
); }