spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import Link from 'next/link';2import { Section } from '@/components/ui/section';3import { Badge } from '@/components/ui/badge';4import { EmptyState } from '@/components/ui/empty-state';5import { listSnapshots } from '@/lib/queries/rankings';6import { fmtDateTime, fmtInt, scopeLabel } from '@/lib/format';78export default async function AdminRankingsPage() {9 const snaps = await listSnapshots(300);10 return (11 <div className="space-y-6">12 <header className="pt-4">13 <h1 className="text-3xl">Ranking snapshots</h1>14 <p className="mt-1 text-[13.5px] text-ink-2">Every snapshot ever generated (current and superseded). Run `pnpm cix rank` to compute.</p>15 </header>16 <Section id="snapshots" title={`${fmtInt(snaps.length)} snapshots`} kicker="Newest first">17 {snaps.length ? (18 <div className="ci-table-wrap">19 <table className="ci-table">20 <thead>21 <tr>22 <th className="num">Id</th>23 <th>Metric</th>24 <th>Scope</th>25 <th>Formula</th>26 <th className="num">Eligible</th>27 <th className="num">Rows</th>28 <th>Current</th>29 <th>Generated</th>30 <th>Inputs hash</th>31 </tr>32 </thead>33 <tbody>34 {snaps.map((s) => (35 <tr key={s.id}>36 <td className="num">{s.id}</td>37 <td>38 <Link className="ci-link" href={`/rankings/${s.metric_slug}?scope=${encodeURIComponent(s.scope_key)}`}>39 {s.metric_name}40 </Link>41 </td>42 <td className="text-[12.5px]">{scopeLabel(s.scope_key)}</td>43 <td className="ci-mono text-[11.5px]">{s.formula_version}</td>44 <td className="num">{fmtInt(s.eligible_entities)}</td>45 <td className="num">{fmtInt(s.row_count)}</td>46 <td>{s.is_current ? <Badge tone="ok">current</Badge> : <Badge tone="outline">superseded</Badge>}</td>47 <td className="whitespace-nowrap text-[12.5px]">{fmtDateTime(s.generated_at)}</td>48 <td className="ci-mono text-[11px] text-ink-3">{s.inputs_hash}</td>49 </tr>50 ))}51 </tbody>52 </table>53 </div>54 ) : (55 <EmptyState compact title="No snapshot">The ranking engine has not produced any snapshot on this environment.</EmptyState>56 )}57 </Section>58 </div>59 );60}61