// Cancer Types & Identification Guide — ported from main project // (frontend/components/cancer-types-guide.tsx). Data lives in // cancer_types_data.js so both apps stay in sync from one source. // // View states: // • grid — searchable card grid (default, what user landed on) // • detail — full reference for one cancer type (clicked "View Full Guide") const _CG = window; // Lucide-style line icons mapped from the data's icon name strings. const _CGIcon = ({ d, size = 24 }) => ( {typeof d === 'string' ? : d} ); const ICON_MAP = { heart: , wind: , activity: , shield: , droplets: <>, dna: <>, brain: <>, eye: <>, bone: , baby: <>, pill: <>, syringe: <>, microscope: <>, stethoscope: <>, target: <>, radiation: <>, trendingup: <>, filetext: <>, bookopen: <>, users: <>, // Generic fallback so unknown icon names still render something __default: , }; const _CGIconByName = ({ name, size = 24 }) => { const d = ICON_MAP[(name || '').toLowerCase()] || ICON_MAP.__default; return <_CGIcon d={d} size={size}/>; }; // ─── Detail view ───────────────────────────────────────────────────────────── const _CGDetail = ({ ct, onBack }) => { const t = window.useLanguage().t; const Section = ({ title, children }) => (
{t(title)}
{children}
); return (
<_CGIconByName name={ct.icon} size={28}/>

{ct.name}

{ct.category}
{t('Prevalence')}
{ct.prevalence}
{t('Survival Rate')}
{ct.survival_rate}

{ct.overview}

{ct.subtypes?.length > 0 && (
    {ct.subtypes.map((s, i) =>
  • {s}
  • )}
)} {ct.risk_factors?.length > 0 && (
{ct.risk_factors.map((s, i) => {s})}
)}
{ct.early_symptoms?.length > 0 && (
    {ct.early_symptoms.map((s, i) =>
  • {s}
  • )}
)} {ct.advanced_symptoms?.length > 0 && (
    {ct.advanced_symptoms.map((s, i) =>
  • {s}
  • )}
)}
{ct.screening_methods?.length > 0 && (
    {ct.screening_methods.map((s, i) =>
  • {s}
  • )}
)} {ct.diagnostic_tests?.length > 0 && (
{ct.diagnostic_tests.map((d, i) => ( ))}
{t('Test')}{t('Purpose')}{t('When')}
{d.test}{d.purpose}{d.when}
)} {ct.biomarkers?.length > 0 && (
{ct.biomarkers.map((b, i) => ( ))}
{t('Marker')}{t('Significance')}{t('Actionable')}
{b.marker} {b.significance} {b.actionable ? ● {t('Yes')} : }
)} {ct.staging?.length > 0 && (
{ct.staging.map((s, i) => ( ))}
{t('Stage')}{t('Description')}{t('Treatment Approach')}
{s.stage}{s.description}{s.treatment_approach}
)} {ct.treatment_options?.length > 0 && (
{ct.treatment_options.map((s, i) => {s})}
)} {ct.key_mutations?.length > 0 && (
{ct.key_mutations.map((s, i) => {s})}
)} {ct.prevention?.length > 0 && (
    {ct.prevention.map((s, i) =>
  • {s}
  • )}
)}
); }; // ─── Grid view ─────────────────────────────────────────────────────────────── const CancerGuide = () => { const t = window.useLanguage().t; const [q, setQ] = React.useState(''); const [active, setActive] = React.useState(null); // currently-detailed cancer object const data = window.CANCER_TYPES || []; const filtered = React.useMemo(() => { if (!q.trim()) return data; const needle = q.toLowerCase(); return data.filter(c => { const haystack = [ c.name, c.category, c.overview, ...(c.key_mutations || []), ...(c.subtypes || []), ...(c.biomarkers || []).map(b => b.marker), ].join(' ').toLowerCase(); return haystack.includes(needle); }); }, [q, data]); if (active) return <_CGDetail ct={active} onBack={() => setActive(null)}/>; return (
<_CGIconByName name="bookopen" size={26}/>

{t('Cancer Types & Identification Guide')}

{t('End-to-end reference: symptoms, diagnosis, biomarkers, staging, treatment')}
setQ(e.target.value)} />
{filtered.map(ct => (
setActive(ct)}>
<_CGIconByName name={ct.icon} size={22}/>
{ct.biomarkers?.length > 0 && ( {ct.biomarkers.length} {t('Biomarkers')} )}

{ct.name}

{ct.category}

{ct.overview}

{t('Subtypes')}
{ct.subtypes?.length ?? 0}
{t('Key Genes')}
{ct.key_mutations?.length ?? 0}
))}
{filtered.length === 0 && (
{t('No matches.')}
)}
); }; window.CancerGuide = CancerGuide;