import Link from 'next/link'; import { FreshnessBadge, MissionLabel, OrbitBadge, StatusBadge, TypeBadge } from '@/components/ui/badges'; import { fmt1, fmtAgo, fmtDate, fmtDateTime, fmtDeg, fmtInt, fmtKm, fmtMinutes, num } from '@/lib/format'; import { routes } from '@/lib/site'; import type { SatelliteDetail } from '@/lib/types'; import { DL, Derived, Row } from './primitives'; export const OPS_STATUS: Record = { '+': 'Operational', '-': 'Non-operational', P: 'Partially operational', B: 'Backup / standby', S: 'Spare', X: 'Extended mission', D: 'Decayed', '?': 'Unknown', }; function KeyStat({ label, value, unit, hint }: { label: string; value: string; unit?: string; hint?: string }) { return (

{label}

{value} {unit && value !== '—' && {unit}}

{hint &&

{hint}

}
); } export function Hero({ d }: { d: SatelliteDetail }) { const os = d.orbital_state; const live = d.live && d.live.error == null ? d.live : null; const epochAge = live?.epoch_age_hours ?? (os ? (Date.now() - new Date(os.epoch).getTime()) / 3.6e6 : null); return (

{d.object_type === 'PAYLOAD' || d.object_type === 'STATION' || d.object_type === 'CREWED' ? 'Satellite' : d.object_type === 'ROCKET_BODY' ? 'Rocket body' : d.object_type === 'DEBRIS' ? 'Debris object' : 'Catalogued object'} {d.norad_id !== null && <> · NORAD {d.norad_id}} {d.cospar_id && <> · COSPAR {d.cospar_id}}

{d.name}

{os ? ( Orbit updated {fmtAgo(os.updated_at)} · element epoch {fmtDateTime(os.epoch)} {epochAge !== null && <> ({fmt1(epochAge)} h old)} ) : ( No orbital element set on file{d.decay_date ? ` — decayed ${fmtDate(d.decay_date)}` : ''}. )} · Metadata updated {fmtAgo(d.freshness.metadata.updated_at)}

); } /** Right-hand "terminal" panel: a compact readout of the object's state. Sticky on desktop. */ export function TelemetryPanel({ d }: { d: SatelliteDetail }) { const os = d.orbital_state; const live = d.live && d.live.error == null ? d.live : null; return (

Telemetry readout

{d.ops_status_code && {OPS_STATUS[d.ops_status_code] ?? d.ops_status_code}}} /> } /> Orbit class } mono={false} value={} /> {live && } {live && } {d.rcs_m2 !== null && } {d.decay_date && }

NORAD {d.norad_id ?? '—'} · {d.cospar_id ?? 'no COSPAR id'}

Sources: {Array.from(new Set(d.sources.map((s) => s.name))).join(', ') || 'none linked to this record'} · methodology

); }