spb/satelliteindex
Public
TypeScript 66.5%
Python 30.9%
JavaScript 1.4%
CSS 0.7%
1import Link from 'next/link';2import { fmtDate, fmtInt, num } from '@/lib/format';3import { routes } from '@/lib/site';4import type { LaunchRow } from '@/lib/types';56/** Launch rows (list page, site detail, launch detail siblings). `ownerHref` lets the caller scope owner chips to its context. */7export function LaunchesTable({ rows, ownerHref = (code) => routes.launches(`owner=${encodeURIComponent(code)}`), showSite = true }: { rows: LaunchRow[]; ownerHref?: (code: string) => string; showSite?: boolean }) {8 return (9 <div className="overflow-x-auto scrollbar-thin">10 <table className="data-table stack">11 <thead>12 <tr>13 <th>Date</th>14 <th>COSPAR</th>15 <th>Primary payload</th>16 <th className="num">Payloads</th>17 <th className="num">Objects</th>18 <th className="num">On orbit</th>19 {showSite && <th>Site</th>}20 <th>Owners</th>21 </tr>22 </thead>23 <tbody>24 {rows.map((l) => {25 const owners = l.owner_codes ?? [];26 const onOrbit = num(l.on_orbit_count);27 const objects = num(l.object_count);28 return (29 <tr key={l.id}>30 <td data-label="Date" className="mono text-xs">{fmtDate(l.launch_date)}</td>31 <td data-label="COSPAR"><Link href={routes.launch(l.cospar_launch_id)} className="link mono text-xs">{l.cospar_launch_id}</Link></td>32 <td data-label="Primary payload" className="primary"><Link href={routes.launch(l.cospar_launch_id)} className="link font-medium">{l.primary_name ?? <span className="text-ink-3">unnamed</span>}</Link></td>33 <td data-label="Payloads" className="num mono text-xs">{fmtInt(l.payload_count)}</td>34 <td data-label="Objects" className="num mono text-xs">{fmtInt(l.object_count)}</td>35 <td data-label="On orbit" className={`num mono text-xs ${onOrbit === 0 && objects ? 'text-ink-3' : ''}`}>{fmtInt(l.on_orbit_count)}</td>36 {showSite && <td data-label="Site" className="text-xs">{l.site_slug ? <Link href={routes.launchSite(l.site_slug)} className="link">{l.site_name}</Link> : l.site_name ?? '—'}</td>}37 <td data-label="Owners" className="text-xs">38 {owners.length ? (39 <span className="flex flex-wrap gap-1">40 {owners.slice(0, 4).map((c) => (41 <Link key={c} href={ownerHref(c)} className="mono rounded border border-rule px-1.5 py-px text-[11px] text-ink-2 hover:border-rule-strong hover:text-ink">{c}</Link>42 ))}43 {owners.length > 4 && <span className="text-ink-3">+{owners.length - 4}</span>}44 </span>45 ) : (46 '—'47 )}48 </td>49 </tr>50 );51 })}52 </tbody>53 </table>54 </div>55 );56}57