import React from 'react'; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Area, AreaChart, Cell, PieChart, Pie, } from 'recharts'; import { TrendingUp, Award, Target, Zap } from 'lucide-react'; import { Card, CardHeader, CardContent } from '@/components/ui/Card'; import { Badge } from '@/components/ui/Badge'; import { useEpisodeRewards, useCurrentEpisode } from '@/hooks/useEpisode'; import { formatReward } from '@/utils/helpers'; interface RewardChartProps { className?: string; } const COLORS = [ '#10a37f', '#6366f1', '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4', '#ec4899', '#84cc16', ]; const CustomTooltip: React.FC<{ active?: boolean; payload?: Array<{ value: number; name: string; color: string }>; label?: string; }> = ({ active, payload, label }) => { if (!active || !payload || payload.length === 0) return null; return (
Step {label}
{payload.map((entry, i) => (
{entry.name}: = 0 ? 'text-green-400' : 'text-red-400'} > {formatReward(entry.value)}
))}
); }; export const RewardChart: React.FC = ({ className }) => { const { data: episode } = useCurrentEpisode(); const { data: rewards, isLoading } = useEpisodeRewards(episode?.id); const chartData = React.useMemo(() => { if (!rewards || rewards.length === 0) return []; return rewards.map((r, i) => ({ step: i + 1, total: r.total, cumulative: r.cumulative, ...r.components.reduce( (acc, c) => ({ ...acc, [c.name]: c.value }), {} as Record ), })); }, [rewards]); const componentNames = React.useMemo(() => { if (!rewards || rewards.length === 0) return []; const names = new Set(); rewards.forEach((r) => r.components.forEach((c) => names.add(c.name))); return Array.from(names); }, [rewards]); const latestReward = rewards?.[rewards.length - 1]; const componentBreakdown = latestReward?.components ?? []; const pieData = componentBreakdown.map((c, i) => ({ name: c.name, value: Math.abs(c.value), fill: COLORS[i % COLORS.length], originalValue: c.value, })); const stats = React.useMemo(() => { if (!rewards || rewards.length === 0) { return { total: 0, avg: 0, max: 0, min: 0 }; } const totals = rewards.map((r) => r.total); return { total: rewards[rewards.length - 1]?.cumulative ?? 0, avg: totals.reduce((a, b) => a + b, 0) / totals.length, max: Math.max(...totals), min: Math.min(...totals), }; }, [rewards]); return ( } action={ latestReward && ( = 0 ? 'success' : 'error'} size="sm" > {formatReward(latestReward.total)} ) } /> {/* Stats Grid */}
Total
= 0 ? 'text-green-400' : 'text-red-400' }`} > {formatReward(stats.total)}
Avg
{formatReward(stats.avg)}
Max
{formatReward(stats.max)}
Min
{formatReward(stats.min)}
{/* Cumulative Reward Chart */} {isLoading ? (
) : chartData.length === 0 ? (

No reward data

) : ( <>
} />
{/* Component Breakdown Bar Chart */} {componentNames.length > 0 && (
Reward Components
} /> {componentNames.map((name, i) => ( ))}
)} {/* Pie Chart for Latest Breakdown */} {pieData.length > 0 && (
{pieData.map((entry, i) => ( ))}
{componentBreakdown.map((c, i) => (
{c.name} = 0 ? 'text-green-400' : 'text-red-400' } > {formatReward(c.value)}
))}
)} )} ); }; export default RewardChart;