spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import Link from 'next/link';2import { Section, Note } from '@/components/ui/section';3import { EmptyState } from '@/components/ui/empty-state';4import { Freshness } from '@/components/ui/freshness';5import { Badge } from '@/components/ui/badge';6import { ApprovalsTable } from '@/components/data/approvals-table';7import { approvalsForCancer } from '@/lib/queries/drugs';8import { therapyMentionsForCancer } from '@/lib/queries/evidence';9import { loadProvenance } from '@/lib/queries/provenance';10import { fmtInt } from '@/lib/format';11import type { CancerBundle } from '../load';1213export async function DrugsTab({ b, jurisdiction, aPage = 1 }: { b: CancerBundle; jurisdiction: string | null; aPage?: number }) {14 // Therapies mentioned in curated evidence (not approvals) — aggregated in SQL (no evidence rows15 // are shipped to the page), listed separately and never called "approved".16 const [approvals, therapies] = await Promise.all([approvalsForCancer(b.descendants), therapyMentionsForCancer(b.descendants)]);17 const jurisdictions = [...new Set(approvals.map((a) => a.jurisdiction))].sort();18 const selected = jurisdiction && jurisdictions.includes(jurisdiction) ? jurisdiction : null;19 const shownApprovals = selected ? approvals.filter((a) => a.jurisdiction === selected) : approvals;2021 if (approvals.length === 0 && therapies.length === 0) {22 return (23 <Section id="drugs" kicker="Drugs" title="Regulatory approvals and therapies in evidence">24 <EmptyState knows={[{ label: 'Variants & evidence', href: `/cancer/${b.cancer.slug}/evidence` }, { label: 'Trials', href: `/cancer/${b.cancer.slug}/trials` }, { label: 'Drugs index', href: '/drugs' }]}>25 No regulatory approval or evidence-linked therapy is recorded for this entity or its descendants. Approvals are always shown with jurisdiction, authority and indication text — a drug is never marked simply "approved".26 </EmptyState>27 </Section>28 );29 }30 const prov = await loadProvenance(approvals.map((a) => a.provenance_id));31 return (32 <div className="space-y-8">33 <Section id="approvals" kicker="Regulatory" title="Approvals by jurisdiction" description={approvals.length ? `${fmtInt(approvals.length)} approval records across ${jurisdictions.length} jurisdiction${jurisdictions.length === 1 ? '' : 's'}, including tumor-agnostic approvals.` : undefined}>34 {approvals.length ? (35 <>36 <nav aria-label="Jurisdiction" className="mb-3 flex flex-wrap gap-1.5 text-[12.5px]">37 <Link href={`/cancer/${b.cancer.slug}/drugs`} aria-current={!selected ? 'page' : undefined} className="ci-chip">38 All jurisdictions39 </Link>40 {jurisdictions.map((j) => (41 <Link key={j} href={`/cancer/${b.cancer.slug}/drugs?jurisdiction=${encodeURIComponent(j)}`} aria-current={selected === j ? 'page' : undefined} className="ci-chip ci-mono">42 {j}43 </Link>44 ))}45 </nav>46 <ApprovalsTable rows={shownApprovals} prov={prov} page={aPage} hrefFor={(p) => `/cancer/${b.cancer.slug}/drugs?${new URLSearchParams({ ...(selected ? { jurisdiction: selected } : {}), ...(p > 1 ? { aPage: String(p) } : {}) }).toString()}#approvals`} />47 <Freshness dataUpdatedAt={approvals.reduce((m, a) => (a.updated_at > m ? a.updated_at : m), approvals[0]!.updated_at)} />48 </>49 ) : (50 <EmptyState compact>No regulatory approval recorded for this entity yet.</EmptyState>51 )}52 </Section>5354 <Section id="therapies-in-evidence" kicker="Curated evidence" title="Therapies appearing in curated evidence" description="Counts of CIViC evidence items mentioning each therapy for this entity or its descendants. Presence here is not an approval.">55 {therapies.length ? (56 <div className="ci-table-wrap">57 <table className="ci-table">58 <thead>59 <tr>60 <th scope="col">Therapy</th>61 <th scope="col" className="num">62 Evidence items (count)63 </th>64 <th scope="col" className="num">65 Sensitivity / response66 </th>67 <th scope="col" className="num">68 Resistance69 </th>70 </tr>71 </thead>72 <tbody>73 {therapies.map((t) => (74 <tr key={t.slug}>75 <td>76 <Link className="ci-link" href={`/drug/${t.slug}`}>77 {t.name}78 </Link>79 </td>80 <td className="num">{fmtInt(t.n)}</td>81 <td className="num">{fmtInt(t.sensitivity)}</td>82 <td className="num">{fmtInt(t.resistance)}</td>83 </tr>84 ))}85 </tbody>86 </table>87 </div>88 ) : (89 <EmptyState compact>No therapy appears in curated evidence for this entity.</EmptyState>90 )}91 <p className="mt-2 text-[12px] text-ink-3">92 <Badge>Curated</Badge> Items are counted regardless of level or direction; see the evidence tab for the detail.93 </p>94 </Section>95 <Note tone="warn">Regulatory status is jurisdiction-specific and changes over time. This page is not treatment guidance.</Note>96 </div>97 );98}99