import Link from 'next/link'; import { Bars, StackedBars } from '@/components/charts/charts'; import { fmtInt, num } from '@/lib/format'; import { routes } from '@/lib/site'; import type { StatsSnapshot } from '@/lib/types'; import { ChartBlock, Derived, Note, TwoCol } from './shared'; /** Full-history charts (since 1957) + derived growth-rate table. */ export function StatsHistory({ snapshot }: { snapshot: StatsSnapshot }) { const launches = [...snapshot.launches_by_year].sort((a, b) => a.year - b.year); const payloads = [...snapshot.payloads_by_launch_year].sort((a, b) => a.year - b.year); const decays = [...snapshot.decays_by_year].sort((a, b) => a.year - b.year); const first = launches[0]?.year; const last = launches[launches.length - 1]?.year; const span = first && last ? `${first}–${last}` : undefined; const launchSeries = launches.map((r) => ({ x: r.year, y: num(r.launches) ?? 0 })); const payloadStack = payloads.map((r) => { const p = num(r.payloads) ?? 0; const a = num(r.still_active) ?? 0; return { x: r.year, still_active: a, retired: Math.max(0, p - a) }; }); const decaySeries = decays.map((r) => ({ x: r.year, y: num(r.decayed) ?? 0 })); // Derived: year-over-year change of payloads launched (last 10 complete + current year). const growth = payloads .map((r, i) => { const cur = num(r.payloads) ?? 0; const prev = i > 0 ? (num(payloads[i - 1]?.payloads) ?? 0) : null; const pct = prev && prev > 0 ? ((cur - prev) / prev) * 100 : null; return { year: r.year, payloads: cur, prev, pct, active: num(r.still_active) ?? 0 }; }) .slice(-10) .reverse(); const currentYear = new Date().getUTCFullYear(); return (
| Year | Payloads launched | Previous year | YoY change | Still active |
|---|---|---|---|---|
| {g.year} {g.year === currentYear && year to date} | {fmtInt(g.payloads)} | {g.prev === null ? '—' : fmtInt(g.prev)} | {g.pct === null ? — : = 0 ? 'text-active' : 'text-danger'}>{g.pct >= 0 ? '+' : ''}{g.pct.toFixed(1)}%} | {fmtInt(g.active)} |