// All the non-home pages. Kept light but complete enough to feel like a real app.
// Pages: Portfolio, Projects (list + detail v1 + detail v2), Initiatives (list + detail v1 + detail v2),
// Ideas (list + detail), Components (list + detail), Tickets, Help, Admin.
// ── PORTFOLIO ────────────────────────────────────────────────────────
const PortfolioPage = ({ goto }) => (
{APM_INITIATIVES.map(ini => {
const projs = projectsByInitiative(ini.id);
return (
goto('initiative', { id: ini.id })}>
{ini.code}
{ini.name}
{ini.summary}
Health
{ini.health}
{fmtMoney(ini.spent)} / {fmtMoney(ini.budget)}
target {ini.target}
{PERSON_BY_ID[ini.owner].name} · {projs.length} projects
);
})}
);
// ── PROJECTS LIST ────────────────────────────────────────────────────
const ProjectsPage = ({ goto }) => {
const [view, setView] = React.useState('table');
const [phase, setPhase] = React.useState(null);
const filtered = phase ? APM_PROJECTS.filter(p => p.phase === phase) : APM_PROJECTS;
return (
} onClick={() => goto('__new_project__')}>New project}
/>
{/* Phase pipeline strip */}
{APM_PHASES.map((ph, i) => {
const cnt = APM_PROJECTS.filter(p => p.phase === ph).length;
const active = phase === ph;
return (
setPhase(active ? null : ph)} style={{
flex: 1, minWidth: 90,
padding: '10px 8px',
background: active ? 'var(--apm-bg-sunken)' : 'transparent',
border: '1px solid ' + (active ? 'var(--apm-line-strong)' : 'transparent'),
borderRadius: 'var(--apm-radius)', cursor: 'pointer',
display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
fontFamily: 'var(--apm-font-body)',
}}>
{ph}
{cnt}
);
})}
{phase && (
}>
{phase} setPhase(null)} style={{ marginLeft: 4, background: 'transparent', border: 'none', cursor: 'pointer', color: 'inherit' }}>
)}
} style={{ width: 240 }} />
{view === 'table' ? (
Project
Initiative
Phase
Health
Owner
Sensitivity
Target
{filtered.map((p, i, a) => (
goto('project', { id: p.id })} style={{
display: 'grid', gridTemplateColumns: '2fr 1fr 0.8fr 0.8fr 1fr 1fr 0.8fr',
padding: 'var(--apm-row-pad) var(--apm-card-pad)', alignItems: 'center', cursor: 'pointer',
borderBottom: i < a.length - 1 ? '1px solid var(--apm-line)' : 'none',
transition: 'background .1s',
}}
onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'}
onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
{INI_BY_ID[p.initiative].name}
{PERSON_BY_ID[p.owner].name.split(' ')[0]}
{p.sensitivity.map(s => )}
{p.target}
))}
) : (
{['Intake','Design','IT Review','Security','HIPAA/PII','Cost & Ops','RA/QA','UAT','Go-Live','Active'].map(ph => {
const items = APM_PROJECTS.filter(p => p.phase === ph);
return (
{items.map(p => (
goto('project', { id: p.id })} style={{ padding: 10 }}>
{p.name}
))}
);
})}
)}
);
};
// ── PROJECT DETAIL — variant A (gates-first) ────────────────────────
const ProjectDetail = ({ id, tab = 'overview', variant = 'a', goto }) => {
const p = PROJ_BY_ID[id] || APM_PROJECTS[0];
const ini = INI_BY_ID[p.initiative];
const [activeTab, setActiveTab] = React.useState(tab);
const phaseIdx = APM_PHASES.indexOf(p.phase);
const tabs = [
{ id: 'overview', label: 'Overview' },
{ id: 'gates', label: 'Phase gates', count: 3 },
{ id: 'tickets', label: 'Tickets', count: p.openTickets },
{ id: 'components', label: 'Components', count: p.components.length },
{ id: 'team', label: 'Team' },
{ id: 'docs', label: 'Documents' },
];
if (variant === 'b') return ;
return (
goto('initiative', { id: ini.id })} style={{ color: 'var(--apm-muted)', cursor: 'pointer', textDecoration: 'underline', textUnderlineOffset: 2 }}>{ini.name} · {p.code}>}
title={p.name}
subtitle={p.summary}
meta={<>
· updated {p.updated}
· target {p.target}
{p.sensitivity.map(s => )}
>}
action={
} onClick={() => goto('project', { id, variant: 'b' })}>Compact view
}>Submit gate
}
/>
{/* Phase pipeline */}
Phase pipeline
{APM_PHASES.slice(0, 10).map((ph, i) => {
const passed = i < phaseIdx;
const current = i === phaseIdx;
return (
);
})}
{activeTab === 'overview' && }
{activeTab === 'gates' && }
{activeTab === 'tickets' && }
{activeTab === 'components' && }
{activeTab === 'team' && }
{activeTab === 'docs' && }
);
};
const ProjectOverviewTab = ({ p, ini, goto }) => (
We're closing out the RA/QA review with two open conditions: (1) evidence that the consent ledger
covers ML-training scope retroactively and (2) a routing plan for adverse-event signals
surfaced by the model. Both have owners; no scope changes.
}>Open response doc
View 7 prior gate responses
{APM_ACTIVITY.slice(0, 5).map((a, i) =>
)}
{PERSON_BY_ID[p.owner].name}
Project Owner
{p.raqa && (
{PERSON_BY_ID[p.raqa].name}
RA/QA
)}
);
const ProjectGatesTab = ({ p, phaseIdx }) => (
{APM_PHASES.slice(0, 10).map((ph, i) => {
const passed = i < phaseIdx;
const current = i === phaseIdx;
const future = i > phaseIdx;
return (
{passed ? : i + 1}
{ph}
{passed &&
Passed }
{current &&
Active · 2 conditions }
{future &&
Locked }
{passed && `Cleared ${i + 2} weeks ago · signed by ${PERSON_BY_ID[p.owner].name}`}
{current && 'In review by Jenna Rowe · 2 conditions outstanding · target close: tomorrow'}
{future && 'Will activate when prior gate clears'}
{current && (
Conditions
Submit response
Request extension
)}
);
})}
);
const ProjectTicketsTab = ({ p, goto }) => {
const tix = APM_TICKETS.filter(t => t.project === p.id);
if (!tix.length) return } title="No open tickets" body="When a clinic, RA/QA reviewer, or component owner opens a ticket against this project it will show up here." />;
return (
{tix.map((t,i,a) => (
goto('tickets', { id: t.id })} style={{ display: 'grid', gridTemplateColumns: '60px 1fr 100px 80px 80px', padding: 'var(--apm-row-pad) var(--apm-card-pad)', alignItems: 'center', gap: 12, cursor: 'pointer', borderBottom: i
e.currentTarget.style.background = 'var(--apm-bg-sunken)'} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
{t.priority}
{t.title}
opened by {PERSON_BY_ID[t.from].name} · {t.age}
{t.status}
{t.assignee ? : — }
{t.id}
))}
);
};
const ProjectComponentsTab = ({ p, goto }) => (
{p.components.map(cid => {
const c = COMP_BY_ID[cid];
return (
goto('components', { id: cid })}>
{c.name}
{c.version}
{c.summary}
);
})}
);
const ProjectTeamTab = ({ p }) => (
{[p.owner, p.raqa, 'p_kira', 'p_alex', 'p_diego'].filter(Boolean).map(pid => (
{PERSON_BY_ID[pid].name}
{PERSON_BY_ID[pid].title}
))}
);
const ProjectDocsTab = ({ p }) => (
} title="No documents linked" body="Link spec docs, pen-test reports, RA/QA evidence, and CER files. They'll be visible to all gate reviewers automatically." action={ }>Upload} />
);
// ── PROJECT DETAIL — variant B (timeline-first) ─────────────────────
const ProjectDetailB = ({ p, ini, activeTab, setActiveTab, tabs, phaseIdx, goto }) => (
{/* Left rail */}
{ini.name} · {p.code}
{p.name}
{p.summary}
Owner
{PERSON_BY_ID[p.owner].name}
Sensitivity
{p.sensitivity.map(s => )}
}>Submit gate
} onClick={() => goto('project', { id: p.id, variant: 'a' })}>Switch to dashboard
{/* Right — vertical timeline of phases */}
Lifecycle
{APM_PHASES.slice(0, 10).map((ph, i) => {
const passed = i < phaseIdx; const current = i === phaseIdx;
return (
{ph}
{passed &&
Passed }
{current &&
Active }
{current && 2 outstanding conditions · in review by Jenna Rowe
}
{passed && Cleared {i + 2}w ago
}
);
})}
);
// ── INITIATIVES LIST ─────────────────────────────────────────────────
const InitiativesPage = ({ goto }) => (
}>New initiative}
/>
{APM_INITIATIVES.map(ini => {
const projs = projectsByInitiative(ini.id);
return (
goto('initiative', { id: ini.id })}>
{ini.code}
{ini.name}
{ini.summary}
OKRs
{ini.okrs.map(o => (
))}
Health
{ini.health}
{projs.length} projects · {fmtMoney(ini.spent)} / {fmtMoney(ini.budget)}
{PERSON_BY_ID[ini.owner].name}
);
})}
);
// ── INITIATIVE DETAIL — variant A (rollup) and B (storyboard) ──────
const InitiativeDetail = ({ id, goto, variant = 'a' }) => {
const ini = INI_BY_ID[id] || APM_INITIATIVES[0];
const projs = projectsByInitiative(ini.id);
if (variant === 'b') return (
} onClick={() => goto('initiative', { id, variant: 'a' })}>Rollup view}
/>
{ini.okrs.map((o, i) => (
{i+1}
OKR · target {o.target}
{o.text}
Backed by: {projs.slice(0,3).map(p => p.name).join(', ')}
))}
);
return (
· target {ini.target}
· {fmtMoney(ini.spent)} of {fmtMoney(ini.budget)}
>}
action={ } onClick={() => goto('initiative', { id, variant: 'b' })}>Storyboard view}
/>
{ini.okrs.map(o => (
{o.text}
= 60 ? 'var(--apm-ok)' : o.progress >= 30 ? 'var(--apm-warn)' : 'var(--apm-risk)' }}>{o.progress}%
target {o.target}
))}
{projs.map((p, i) => (
goto('project', { id: p.id })} style={{
display: 'grid', gridTemplateColumns: '2fr 1fr 0.8fr 0.8fr 1fr',
padding: 'var(--apm-row-pad) var(--apm-card-pad)', alignItems: 'center', cursor: 'pointer',
borderBottom: i < projs.length - 1 ? '1px solid var(--apm-line)' : 'none',
}}
onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'}
onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
{p.target}
))}
Spend tracking on plan. Projected to land at {fmtMoney(Math.round(ini.spent * 2.4))} EOY.
{PERSON_BY_ID[ini.owner].name}
Initiative Owner
{PERSON_BY_ID[ini.sponsor].name}
Executive Sponsor
{APM_ACTIVITY.slice(0, 4).map((a, i) =>
)}
);
};
Object.assign(window, { PortfolioPage, ProjectsPage, ProjectDetail, InitiativesPage, InitiativeDetail });