/* ============================================================ AUTH + APP SHELL ============================================================ */ (function(){ const {Icon,Btn,Avatar,RoleBadge,Field,Input,Banner}=window; const {useState}=React; /* ---------------- Login (real auth) ---------------- */ function Login(){ const {auth,go,toast}=window.useStore(); const [email,setEmail]=useState(''); const [password,setPassword]=useState(''); const [busy,setBusy]=useState(false); const [err,setErr]=useState(''); async function doSignIn(em,pw){ if(busy) return; setBusy(true); setErr(''); const res=await auth.signIn(em,pw); setBusy(false); if(!res.ok){ setErr(res.error); return; } const land=window.GOV.ROLES[res.me.role].land; go(land); toast({kind:'audit', icon:'shield', title:'Signed in as '+window.GOV.ROLES[res.me.role].label, desc:'Login recorded to the audit trail.'}); } return
BHF

Sign in to BHF Hub

Partner Hospital case portal · invite-only access

{err &&
{err}
}
{e.preventDefault();doSignIn(email,password);}}> setEmail(e.target.value)} placeholder="you@hospital.org"/> setPassword(e.target.value)} placeholder="••••••••"/> {busy?'Signing in…':'Sign in'}
Invite-only access. If you're a partner hospital and need an account, contact the BHF team.
; } /* ---------------- App Shell ---------------- */ const TITLES={dashboard:'Dashboard',submit:'Submit New Patient',success:'Request submitted',requests:'Requests', detail:'Request detail',queue:'My Queue',partners:'Partners',users:'Users',reports:'Reports',audit:'Audit Log',settings:'Settings'}; function AppShell({title, children}){ const {state,me,route,go,sel,navOpen,setNavOpen,dispatch,toast,auth}=window.useStore(); const [notifOpen,setNotifOpen]=useState(false); const nav=window.GOV.NAV[me.role]; // counts const myReqs=sel.visibleRequests(); const counts={ requests: me.role==='partner'? myReqs.length : state.requests.length, queue: state.requests.filter(r=>r.reviewerId===me.id).length, needs: myReqs.filter(r=>r.status==='needs_info').length, }; // notifications: needs-info for partner; new submissions / assignments for team const notifs = me.role==='partner' ? myReqs.filter(r=>r.status==='needs_info').map(r=>({id:r.id,t:r.id+' needs your information',d:r.patient.ref,to:r.id})) : state.requests.filter(r=>['submitted'].includes(r.status)||r.reviewerId===me.id&&r.status==='needs_info') .slice(0,6).map(r=>({id:r.id,t:r.id+' · '+window.GOV.STATUS[r.status].label,d:sel.hospitalName(r.hospitalId),to:r.id})); function navItem(it){ if(it.sec) return
{it.sec}
; const active=route.screen===it.key || (route.screen==='detail'&&['requests','queue'].includes(it.key)&&false); let count=null,alert=false; if(it.key==='requests'&&counts.requests) count=counts.requests; if(it.key==='queue'&&counts.queue) count=counts.queue; if(it.key==='requests'&&me.role==='partner'&&counts.needs){count=counts.needs;alert=true;} return
go(it.key)}> {it.label} {count!=null && {count}}
; } return
setNavOpen(false)}/>
{title}
{me.role!=='partner' &&
}
{notifOpen && {setNotifOpen(false);go('detail',id);}} onClose={()=>setNotifOpen(false)}/>}
{children}
; } function Notif({notifs,onGo,onClose}){ return <>
Notifications
{notifs.length===0 ?
You're all caught up.
: notifs.map(n=>
onGo(n.to)} style={{padding:'11px 14px',borderBottom:'1px solid var(--border-default)',cursor:'pointer',display:'flex',gap:10,alignItems:'flex-start'}} className="notif-row">
{n.t}
{n.d}
)}
; } window.Login=Login; window.AppShell=AppShell; window.SHELL_TITLES=TITLES; })();