import { WorldMap, type MapMarker } from '@/components/map/world-map'; import { num } from '@/lib/format'; import { routes } from '@/lib/site'; import type { LaunchSiteRow } from '@/lib/types'; /** All launch sites as markers sized by launch count (sqrt scale). Sites without coordinates are listed, not plotted. */ export function SitesMap({ sites, highlight, labelTop = 8 }: { sites: LaunchSiteRow[]; highlight?: string; labelTop?: number }) { const plotted = sites.filter((s) => s.latitude !== null && s.longitude !== null); const max = Math.max(1, ...plotted.map((s) => num(s.launches) ?? 0)); const ranked = [...plotted].sort((a, b) => (num(b.launches) ?? 0) - (num(a.launches) ?? 0)); const labelled = new Set(ranked.slice(0, labelTop).map((s) => s.slug)); const markers: MapMarker[] = ranked .reverse() // draw big ones first so small markers stay clickable on top .map((s) => { const n = num(s.launches) ?? 0; const active = s.slug === highlight; return { lat: s.latitude!, lon: s.longitude!, size: Math.max(2.5, 2.5 + Math.sqrt(n / max) * 11), color: active ? 'var(--accent)' : n >= max * 0.25 ? 'var(--series-4)' : 'var(--series-2)', href: routes.launchSite(s.slug), label: active || labelled.has(s.slug) ? s.name.replace(/\s*\(.*\)$/, '') : undefined, pulse: active, }; }); const missing = sites.length - plotted.length; return (
Marker area ∝ launches. {plotted.length} sites plotted{missing > 0 ? `; ${missing} site${missing > 1 ? 's' : ''} without coordinates in SATCAT (listed below)` : ''}.