import Link from 'next/link'; import { Fragment, type ReactNode } from 'react'; import { Badge, ClaimBadge, MatchBadge, StatusBadge, isExactMatch } from '@/components/ui/badge'; import { SourceBadge, TableProvenance } from '@/components/ui/source-badge'; import { EVIDENCE_LEVEL_LABEL, EVIDENCE_DESCRIPTION_CHARS, groupEvidence, therapyKey, type EvidenceItem, type EvidenceGroupBy } from '@/lib/queries/evidence'; import type { ProvRow } from '@/lib/queries/provenance'; import { toInfo } from '@/lib/queries/provenance'; import { humanize } from '@/lib/format'; const CIVIC = { sourceSlug: 'civic', sourceName: 'CIViC' }; function Direction({ e }: { e: EvidenceItem }) { const dir = e.evidence_direction ?? '—'; const sig = e.significance ?? ''; const tone = dir === 'DOES_NOT_SUPPORT' ? 'warn' : sig.includes('RESIST') ? 'danger' : sig.includes('SENSITIV') ? 'ok' : 'neutral'; return ( <> {humanize(dir)} {sig ? ( <> {' '} {humanize(sig.replace('SENSITIVITYRESPONSE', 'SENSITIVITY_RESPONSE'))} ) : null} ); } /** * CIViC evidence in ONE dense table. Rows are grouped (by molecular profile → therapy, or by cancer * on variant pages) with a `` per group and a row-group header, instead of one table per * group: a table header is rendered once, which halves the markup for pages with many small groups * (every element ships twice — HTML + RSC payload). Levels, directions and significance are shown * in their native form (§3, never collapsed to works/doesn't). One provenance popover for the whole * table (all rows come from one CIViC release); rows carry a compact badge. * * `summary` replaces the default "N evidence items" sentence — pass the page window when the caller * paginates ("Showing 1–50 of 405 evidence items"). */ export function EvidenceTable({ items, prov, showCancer = false, groupBy = 'variant', summary }: { items: EvidenceItem[]; prov: Map; showCancer?: boolean; groupBy?: EvidenceGroupBy; summary?: ReactNode }) { const groups = groupEvidence(items, groupBy); const first = items[0] ? toInfo(prov.get(items[0].provenance_id)) : null; const cancerCol = showCancer && groupBy !== 'cancer'; const profileCol = groupBy === 'cancer'; const cols = 7 + (cancerCol ? 1 : 0) + (profileCol ? 1 : 0); return (
}> {summary ?? `${items.length} evidence item${items.length === 1 ? '' : 's'}`} · levels, directions and significance as curated at the source; each row links to its CIViC record.
{profileCol ? : null} {cancerCol ? : null} {groups.map((g) => ( {groupBy !== 'none' ? ( ) : null} {g.items.map((e, i) => { const prevKey = i > 0 ? therapyKey(g.items[i - 1]!) : null; const sameTherapy = prevKey === therapyKey(e) && groupBy === 'variant'; const desc = e.description ?? ''; const cut = desc.length >= EVIDENCE_DESCRIPTION_CHARS; return ( {profileCol ? : null} {cancerCol ? ( ) : null} ); })} ))}
Molecular profileTherapyCancerType Level Direction · significance Rating (1–5) Status Evidence Source
{g.href ? ( {g.label} ) : ( {g.label} )} {g.genes.length > 1 ? g.genes.map((s) => ( {s} )) : null} {g.items.length} {g.unmapped ? ( unmapped disease ) : null}
{e.molecular_profile_name ?? e.name ?? '—'} {sameTherapy ? ( 〃 ) : e.therapy_slugs?.length ? ( e.therapy_slugs.map((s, j) => ( {j > 0 ? ' + ' : ''} {e.therapy_slug_names?.[j] ?? s} )) ) : ( {therapyLabel(e)} )} {e.therapy_interaction_type && !sameTherapy ? {humanize(e.therapy_interaction_type)} : null} {e.cancer_slug ? ( {e.cancer_name} ) : ( {e.disease_name ?? '—'} )} {/* Exact mappings are the norm; only non-exact ones (alias, broader, probabilistic, unresolved) carry the caveat badge. */} {!isExactMatch(e.cancer_match_type) ? : null} {humanize(e.evidence_type)} {e.evidence_level ?? '—'} {e.evidence_rating ?? '—'}
EID{e.civic_id}

{desc ? `${desc}${cut ? '…' : ''}` : 'No description at source.'} {cut ? (full text at CIViC) : null}

{e.pmid ? ( <> PMID{' '} {e.pmid} {e.source_citation ? · {e.source_citation} : null} {' · '} ) : null} Open in CIViC

); } function therapyLabel(e: EvidenceItem): string { if (e.therapy_names.length) return e.therapy_names.join(' + '); return e.evidence_type === 'PREDICTIVE' ? 'Unspecified therapy' : `(${(e.evidence_type ?? 'evidence').toLowerCase()})`; }