import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, } from 'recharts'; import { epochDayToDate } from '../../lib/formatters'; export interface PerAnimeDataPoint { epochDay: number; animeTitle: string; value: number; } interface StackedTrendChartProps { title: string; data: PerAnimeDataPoint[]; } const LINE_COLORS = [ '#8aadf4', '#c6a0f6', '#a6da95', '#f5a97f', '#f5bde6', '#91d7e3', '#ee99a0', '#f4dbd6', ]; function buildLineData(raw: PerAnimeDataPoint[]) { const totalByAnime = new Map(); for (const entry of raw) { totalByAnime.set(entry.animeTitle, (totalByAnime.get(entry.animeTitle) ?? 0) + entry.value); } const sorted = [...totalByAnime.entries()].sort((a, b) => b[1] - a[1]); const topTitles = sorted.slice(0, 7).map(([title]) => title); const topSet = new Set(topTitles); const byDay = new Map>(); for (const entry of raw) { if (!topSet.has(entry.animeTitle)) continue; const row = byDay.get(entry.epochDay) ?? {}; row[entry.animeTitle] = (row[entry.animeTitle] ?? 0) + Math.round(entry.value * 10) / 10; byDay.set(entry.epochDay, row); } const points = [...byDay.entries()] .sort(([a], [b]) => a - b) .map(([epochDay, values]) => ({ label: epochDayToDate(epochDay).toLocaleDateString(undefined, { month: 'short', day: 'numeric' }), ...values, })); return { points, seriesKeys: topTitles }; } export function StackedTrendChart({ title, data }: StackedTrendChartProps) { const { points, seriesKeys } = buildLineData(data); const tooltipStyle = { background: '#363a4f', border: '1px solid #494d64', borderRadius: 6, color: '#cad3f5', fontSize: 12, }; if (points.length === 0) { return (

{title}

No data
); } return (

{title}

{seriesKeys.map((key, i) => ( ))}
{seriesKeys.map((key, i) => ( {key} ))}
); }