// HLA Typing Lab — hub dashboards. // // One component per built lab hub, rendered by HubHome in place of the Cascade // dashboards (see the LAB_HUB_DASH lookup at the bottom). Plain JSX and the // .lab-* classes in newhub.css — no framework injection, because these pages // are representative rather than a port of a design document. // // Data comes from lab_data.jsx. Nothing here computes: the numbers are written // down, the same way Cascade's dashboards read from generated content. function LabStatRow({ stats }) { return (
{stats.map((s) => (
{s.label} {s.value} {s.sub}
))}
); } function LabPanel({ title, sub, children, action }) { return (

{title}

{sub &&

{sub}

}
{action}
{children}
); } function LabTable({ cols, rows, render }) { return (
{cols.map((c) => )}{rows.map(render)}
{c}
); } // ── Typing hub ──────────────────────────────────────────────────────────── function LabTypingDashboard() { const rr = window.LAB_RERESOLVE; const [reresolved, setReresolved] = React.useState(false); return (
{/* The claim the whole lab model rests on, made visible: a new release lands and the archive re-derives instead of going stale. */} setReresolved(true)} disabled={reresolved}> {reresolved ? 'Re-resolved ✓' : 'Re-resolve archive'} }>
{rr.buckets.map((b) => (
{b.n} {b.kind} {b.note}
))}
( {r.id} {r.study} {r.a} {r.b} {r.c} {r.drb1} {r.dqb1} {r.res} {r.method} {r.release} {r.status} )} />
( {r.id} {r.locus} {r.str} {r.cause} {r.owner} {r.route} )} /> ( {r.method} {r.years} {r.runs} {r.first} {r.amb} {r.conc} )} />
); } // ── Studies & Cohorts hub ───────────────────────────────────────────────── function LabStudiesDashboard() { const studies = window.LAB_STUDIES; const active = studies.filter((s) => s.status === 'Active').length; const reusable = studies.filter((s) => s.reuse === 'Yes').reduce((n, s) => n + s.n, 0); return (
n + s.n, 0).toLocaleString(), sub: 'typed for someone else’s question' }, { label: 'Reusable', value: reusable.toLocaleString(), sub: 'consent covers secondary use' }, { label: 'Locked', value: '186', sub: 'closed cohort — deliver, don’t reuse' }, ]} /> ( {s.id} {s.name} {s.pi} {s.n} {s.need} {s.out} {s.reuse} {s.status} )} />
subjects where A*02:01 and DRB1*04:01 and consent.reuse = true → 61 subjects across HSCT-2026, VAX-COV, HIV-PROG ARBO-OUT is excluded: 186 subjects, typed, matching — and not reusable. That exclusion is the model doing its job.
); } const LAB_HUB_DASH = { Typing: LabTypingDashboard, 'Studies & Cohorts': LabStudiesDashboard, }; window.LabTypingDashboard = LabTypingDashboard; window.LabStudiesDashboard = LabStudiesDashboard; window.LAB_HUB_DASH = LAB_HUB_DASH;