spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import Link from 'next/link';2import type { ReactNode } from 'react';3import { Badge, ClaimBadge } from '@/components/ui/badge';4import { SourceBadge, TableProvenance, type ProvenanceInfo } from '@/components/ui/source-badge';5import type { PublicationListRow } from '@/lib/queries/publications';6import { fmtDate, fmtInt } from '@/lib/format';78const PUBMED: ProvenanceInfo = { sourceSlug: 'pubmed', sourceName: 'PubMed (NLM)', dataset: 'PubMed E-utilities', layer: 'normalized' };910/**11 * Publication list. Bibliographic rows all come from PubMed, so one provenance popover sits in the12 * caption and each row carries a compact badge. Link method / validation status stay per row.13 * Layout classes live in globals.css (.ci-pub) — the list is repeated 25× per page.14 */15export function PublicationList({ rows, summary }: { rows: PublicationListRow[]; summary?: ReactNode }) {16 const latest = rows.reduce<Date | string | null>((m, p) => (m == null || String(p.updated_at) > String(m) ? p.updated_at : m), null);17 return (18 <div>19 <TableProvenance p={{ ...PUBMED, retrievedAt: latest }} claim={<ClaimBadge kind="published" />}>20 {summary ?? `${fmtInt(rows.length)} publication${rows.length === 1 ? '' : 's'}`} · bibliographic data as recorded by PubMed; abstracts are not reproduced.21 </TableProvenance>22 <ol className="ci-pubs">23 {rows.map((p) => (24 <li key={p.id} className="ci-pub">25 <div>26 {p.pmid ? (27 <Link href={`/publication/${p.pmid}`} className="ci-link font-medium">28 {p.title}29 </Link>30 ) : (31 <span className="font-medium">{p.title}</span>32 )}33 {p.retracted ? <Badge tone="danger">Retracted</Badge> : null}34 {p.is_preprint ? <Badge tone="warn">Preprint</Badge> : null}35 </div>36 <p>37 {p.authors.map((a) => a.name).join(', ')}38 {p.author_count > 3 ? ' et al.' : ''}39 {p.journal_iso || p.journal ? ` · ${p.journal_iso ?? p.journal}` : ''}40 {p.pub_date ? ` · ${fmtDate(p.pub_date)}` : p.pub_year ? ` · ${p.pub_year}` : ''}41 {p.pmid ? ` · PMID ${p.pmid}` : ''}42 {p.edge_status ? (43 <>44 {' · '}45 <Badge tone={p.edge_status === 'validated' ? 'ok' : 'warn'}>{p.edge_status}</Badge>46 {p.method ? <span className="ci-mono"> {p.method}</span> : null}47 </>48 ) : null}{' '}49 <SourceBadge compact title={null} p={PUBMED} />50 </p>51 </li>52 ))}53 </ol>54 </div>55 );56}57