import type { Metadata } from 'next'; import Link from 'next/link'; import { HBars } from '@/components/charts/charts'; import { DEFAULT_METRIC, findMetric, METRICS, type Row } from '@/components/stats/rankings-config'; import { Chips, Derived, InlineRank, Note } from '@/components/stats/shared'; import { Container, PageHeader, Section } from '@/components/ui/section'; import { Unavailable } from '@/components/ui/unavailable'; import { api, safe } from '@/lib/api'; import { fmtAgo, fmtInt } from '@/lib/format'; import { routes, SITE_NAME, SITE_URL } from '@/lib/site'; export const revalidate = 600; type Search = Promise<{ metric?: string | string[] }>; function pick(v: string | string[] | undefined): string | undefined { return Array.isArray(v) ? v[0] : v; } export async function generateMetadata({ searchParams }: { searchParams: Search }): Promise { const m = findMetric(pick((await searchParams).metric) ?? DEFAULT_METRIC); const url = `${SITE_URL}${m.key === DEFAULT_METRIC ? routes.rankings() : routes.rankings(m.key)}`; const title = `${m.title} — Rankings`; return { title, description: m.description, alternates: { canonical: url }, openGraph: { title: `${title} | ${SITE_NAME}`, description: m.description, url, type: 'website', siteName: SITE_NAME }, twitter: { card: 'summary_large_image', title: `${title} | ${SITE_NAME}`, description: m.description }, }; } export default async function RankingsPage({ searchParams }: { searchParams: Search }) { const metricKey = pick((await searchParams).metric) ?? DEFAULT_METRIC; const m = findMetric(metricKey); const res = await safe(api.rankings(m.key, 50)); const rows: Row[] = res?.data.rows ?? []; const top = rows.slice(0, 10).map((r) => ({ label: m.name(r), value: m.primary(r), href: m.href(r) ?? undefined })); const chips = METRICS.map((x) => ({ href: x.key === DEFAULT_METRIC ? routes.rankings() : routes.rankings(x.key), label: x.label, active: x.key === m.key })); const hasDerived = m.columns.some((c) => c.derived); return (
{m.warn && {m.warn}} {!res ? (
) : rows.length === 0 ? (
) : ( <>
{m.columns.map((c) => ( ))} {rows.map((r, i) => ( {m.columns.map((c, ci) => ( ))} ))}
{c.label} {c.derived && }
{ci === 0 ? (
{c.render(r)}
) : ( c.render(r) )}
{(m.note || hasDerived) && ( {m.note ?? ( <> Columns marked are computed by SatelliteIndex. )}{' '} Methodology )}

Generated {fmtAgo(res.meta.generated_at)} · limit 50 · source: SatelliteIndex canonical catalogue (CelesTrak SATCAT + GP)

)}
); }