Admin
Megan Henley · Scout
Admin Dashboard
▪ Portfolio
📊 MedSync Analytics
🔬 Lot Lifecycle
📋 Activity Log

Operations
🛒 Weekly Order
📦 Receiving
🏥 Hospital Receiver
⚠️ Goods Lost

Settings
⚙️ Admin Settings
MedSync Portfolio dashboard — all locations

Step 1 — Choose a task

SCOUT Receiver

Lincoln Park

What would you like to do today?

Select one to continue

Notification email → IL + COD

MedSync · Auto-notification

Delivery received · Lincoln Park · Sarah K.

MWI delivery · May 28, 2026 · 10:42am

Received by: Sarah K.

✓ Cerenia 16mg tabs6 packs
✓ Maropitant Inj4 vials
✗ Carprofen 25mg — Damaged2 bottles
⚠ Ondansetron 8mgNo open PO
Goods lost logged · Carprofen 25mg · Damaged/Spilled · 2 bottles · Sarah K.
1 item unmatched · Review before shelving
Standalone goods lost submissions send a separate notification at time of submission.
'); w.document.write(doc.innerHTML); w.document.write(''); w.document.close(); w.focus(); setTimeout(() => { w.print(); }, 400); } function showToast(html) { const t = document.getElementById('export-toast'); document.getElementById('export-toast-msg').innerHTML = html; t.style.display = 'flex'; t.style.background = '#E8E4F8'; } function hideToast() { document.getElementById('export-toast').style.display = 'none'; } const allLogs = [ { ts:'May 28 · 10:47am', loc:'Lincoln Park', user:'Megan H.', role:'Admin / COD', type:'Export', tag:'log-exp', action:'Exported MedSync Analytics report — MTD · All locations · PDF + QuickBooks' }, { ts:'May 28 · 10:42am', loc:'Lincoln Park', user:'Sarah K.', role:'Hospital Receiver', type:'Inventory', tag:'log-inv', action:'Receiving session completed — MWI delivery · 3 items confirmed · 1 damaged (Carprofen 25mg) · 1 unmatched PO' }, { ts:'May 28 · 10:18am', loc:'Old Orchard', user:'Jamie K.', role:'Inventory Lead', type:'Procurement', tag:'log-proc', action:'Weekly order submitted to Vetcove — $847.32 · 6 line items · 1 SKU substitution accepted · 8 min before 1pm cutoff' }, { ts:'May 28 · 09:54am', loc:'West Loop', user:'Alex M.', role:'Inventory Lead', type:'Inventory', tag:'log-inv', action:'Goods lost submitted — Gabapentin Solu 50mg/mL · Expired · 966mL · $319.00' }, { ts:'May 28 · 09:31am', loc:'Lincoln Park', user:'Megan H.', role:'Admin / COD', type:'System', tag:'log-sys', action:'White goods consumption rate updated — Gauze 4×4: Old Orchard rate adjusted from 1.8 to 2.1 per 100 appts' }, { ts:'May 28 · 09:14am', loc:'Wheaton', user:'Sam R.', role:'Inventory Lead', type:'Inventory', tag:'log-inv', action:'Cycle count completed — Cat A + B · 22 products verified · 0 discrepancies · 14 min' }, { ts:'May 27 · 4:52pm', loc:'Old Orchard', user:'Jamie K.', role:'Inventory Lead', type:'System', tag:'log-sys', action:'Min/Max updated — Maropitant Inj 10mg/mL: Max reduced from 8 to 5 vials per Admin recommendation' }, { ts:'May 27 · 2:08pm', loc:'West Loop', user:'Marcus T.', role:'Hospital Receiver', type:'User session', tag:'log-user', action:'Hospital Receiver session started — Goods lost selected · Carprofen 25mg · Damaged/Spilled · 2 bottles · $28.40' }, { ts:'May 27 · 1:58pm', loc:'Old Orchard', user:'Jamie K.', role:'Inventory Lead', type:'Procurement', tag:'log-proc', action:'⚠ Late submission — Vetcove order submitted at 1:58pm · 58 min past cutoff · Next-day delivery at risk' }, { ts:'May 27 · 11:30am', loc:'Lincoln Park', user:'Brianna L.', role:'Inventory Lead', type:'Inventory', tag:'log-inv', action:'Receiving scan completed — PO #4421 · 5 of 7 items confirmed · 1 discrepancy flagged (Ondansetron 8mg vs 4mg ordered) · PO line open' }, { ts:'May 27 · 09:00am', loc:'All locations', user:'Megan H.', role:'Admin / COD', type:'System', tag:'log-sys', action:'COGs denominator changed — gross production → gross revenue · Historical COGs recalculated across all locations' }, { ts:'May 26 · 3:40pm', loc:'Lincoln Park', user:'Brianna L.', role:'Inventory Lead', type:'Inventory', tag:'log-inv', action:'Goods lost submitted — Catalyst CHEM 10 clips · Diagnostic duplicate · Equipment flag triggered · 3 clips · $41.00' }, ]; function renderLog(rows) { const tbody = document.getElementById('log-tbody'); tbody.innerHTML = rows.map(r => ` ${r.ts} ${r.loc} ${r.user} ${r.role} ${r.type} ${r.action} `).join(''); } function logFilter() { const loc = document.getElementById('log-loc').value; const role = document.getElementById('log-role').value; const type = document.getElementById('log-type').value; const filtered = allLogs.filter(r => (loc === 'All locations' || r.loc === loc || r.loc === 'All locations') && (role === 'All roles' || r.role === role) && (type === 'All types' || r.type === type) ); document.getElementById('log-nav-label').textContent = 'Activity log · ' + loc + ' · ' + document.getElementById('log-date').value; renderLog(filtered); } renderLog(allLogs); renderGlTop5('Today', 'all'); function fsSelect(n) { [1,2,3].forEach(i => { const el = document.getElementById('fs-m' + i); if (!el) return; if (i === n) { el.style.border = '2px solid #1C2B4A'; el.style.background = '#F0EEF8'; if (!el.querySelector('.fs-selected')) { const dot = document.createElement('div'); dot.className = 'fs-selected'; dot.style.cssText = 'margin-top:10px;display:flex;align-items:center;gap:6px;'; dot.innerHTML = '
Selected'; el.appendChild(dot); } } else { el.style.border = '0.5px solid #C8C4D8'; el.style.background = '#fff'; const dot = el.querySelector('.fs-selected'); if (dot) dot.remove(); } }); } let hrTask = null; function hrSelectTask(task, btn) { hrTask = task; document.querySelectorAll('#screen3b button[onclick^="hrSelectTask"]').forEach(b => { b.style.borderColor = '#C8C4D8'; b.style.background = '#fff'; }); btn.style.borderColor = '#1C2B4A'; btn.style.background = '#f0f7f5'; document.getElementById('hr-name-entry').style.display = 'block'; } function hrProceed() { document.getElementById('hr-name-entry').style.display = 'none'; document.querySelectorAll('#screen3b button[onclick^="hrSelectTask"]').forEach(b => b.style.display = 'none'); document.querySelector('#screen3b .mob-body p:first-child').style.display = 'none'; document.querySelector('#screen3b .mob-body p:nth-child(2)').style.display = 'none'; if (hrTask === 'receive') { document.getElementById('hr-receive-panel').style.display = 'block'; } else { document.getElementById('hr-goods-panel').style.display = 'block'; } } function hrMarkDamaged(row) { row.style.display = 'none'; document.getElementById('hr-damage-confirm').style.display = 'block'; } function hrShowDiagSub() { const sub = document.getElementById('hr-diag-sub'); sub.style.display = sub.style.display === 'none' ? 'block' : 'none'; } function userScanPair() { const btn = event.target.closest('button'); btn.innerHTML = ' Searching...'; btn.disabled = true; setTimeout(() => { document.getElementById('us-device-sub').textContent = 'ScanAvenger SA9000 · BT:4A:2F:91'; document.getElementById('us-status-pill').innerHTML = '
Connected'; document.getElementById('us-instructions').style.display = 'none'; document.getElementById('us-actions').innerHTML = ''; document.getElementById('us-test-area').style.display = 'block'; ['us-w1','us-w2','us-w3'].forEach(id => { const el = document.getElementById(id); if(el) el.outerHTML = 'Ready'; }); }, 2200); } function testScan() { document.getElementById('us-test-result').style.fontStyle = 'normal'; document.getElementById('us-test-result').style.color = '#4A5568'; document.getElementById('us-test-result').textContent = 'Scanning...'; setTimeout(() => { document.getElementById('us-test-result').style.color = '#1C2B4A'; document.getElementById('us-test-result').innerHTML = 'Maropitant 10mg/mL 20mL · NDC 61106-0006-01 · Lot #MRP2241 · Exp Mar 2028 · ✓ Scanner working correctly'; }, 800); } function adminPingScanner(name, location) { const t = document.getElementById('admin-ping-toast'); if (!t) return; t.style.display = 'block'; t.innerHTML = 'Ping sent to ' + name + ' at ' + location + '.'; setTimeout(() => { t.style.display = 'none'; }, 5000); } function showForgot() { // Visual feedback only in mockup — handled by panel 2 display } function submitForgot() { const email = document.getElementById('forgot-email').value.trim(); if (!email) { document.getElementById('forgot-email').style.borderColor = '#a33030'; return; } document.getElementById('forgot-email').style.borderColor = '#C8C4D8'; document.getElementById('forgot-confirm').style.display = 'block'; } function umShowInvite() { document.getElementById('um-invite-panel').style.display = 'block'; document.getElementById('um-invite-confirm').style.display = 'none'; document.getElementById('um-email-input').value = ''; document.getElementById('um-role-select').value = ''; } function umHideInvite() { document.getElementById('um-invite-panel').style.display = 'none'; } function umSendInvite() { const email = document.getElementById('um-email-input').value.trim(); const role = document.getElementById('um-role-select').value; if (!email || !role) { document.getElementById('um-email-input').style.borderColor = email ? '#C8C4D8' : '#a33030'; document.getElementById('um-role-select').style.borderColor = role ? '#C8C4D8' : '#a33030'; return; } const conf = document.getElementById('um-invite-confirm'); document.getElementById('um-invite-msg').textContent = 'Invitation sent to ' + email + ' as ' + role + '. They\'ll receive an email with a link to complete their account setup.'; conf.style.display = 'flex'; } // ── Unified Platform Sidebar ────────────────────────────── // Sidebar definitions per role const sidebarDefs = { admin: { role: 'Admin', loc: 'Megan H. · All locations', groups: [ { label: 'Admin Dashboard', items: [ { icon: 'ti-layout-dashboard', label: 'Portfolio dashboard', href: '#screen1' }, { icon: 'ti-chart-bar', label: 'MedSync Analytics', href: '#screen2' }, { icon: 'ti-microscope', label: 'Lot lifecycle analysis', href: '#screen3' }, { icon: 'ti-list-details', label: 'Activity log', href: '#screen4' }, ]}, { label: 'Operations', items: [ { icon: 'ti-shopping-cart', label: 'Weekly order', href: '#screen5' }, { icon: 'ti-clipboard-list', label: 'Formulary setup', href: '#screen10b' }, { icon: 'ti-package', label: 'Receiving', href: '#screen6' }, { icon: 'ti-clipboard-x', label: 'Goods lost', href: '#screen8' }, ]}, { label: 'Settings', items: [ { icon: 'ti-settings', label: 'Admin settings', href: '#screen10' }, ]}, ] }, clinical: { role: 'Clinical Support', loc: 'Jordan T. · Lincoln Park', groups: [ { label: 'Operations', items: [ { icon: 'ti-shopping-cart', label: 'Weekly order', href: '#screen5' }, { icon: 'ti-clipboard-list', label: 'Formulary setup', href: '#screen10b' }, { icon: 'ti-package', label: 'Receiving', href: '#screen6' }, { icon: 'ti-rotate-clockwise', label: 'Cycle count', href: '#screen5' }, { icon: 'ti-clipboard-x', label: 'Goods lost', href: '#screen8' }, ]}, { label: 'Support', items: [ { icon: 'ti-key', label: 'Reset password', href: '#screen10' }, ]}, { label: 'Settings', items: [ { icon: 'ti-settings', label: 'User settings', href: '#screen9' }, ]}, ] }, il: { role: 'Inventory Lead', loc: 'Brianna L. · Lincoln Park', groups: [ { label: 'Operations', items: [ { icon: 'ti-shopping-cart', label: 'Weekly order', href: '#screen5' }, { icon: 'ti-clipboard-list', label: 'Formulary setup', href: '#screen10b' }, { icon: 'ti-package', label: 'Receiving', href: '#screen6' }, { icon: 'ti-rotate-clockwise', label: 'Cycle count', href: '#screen5' }, { icon: 'ti-clipboard-x', label: 'Goods lost', href: '#screen8' }, ]}, { label: 'Settings', items: [ { icon: 'ti-settings', label: 'User settings', href: '#screen9' }, ]}, ] }, receiver: { role: 'Hospital Receiver', loc: 'Lincoln Park', groups: [ { label: 'Workflows', items: [ { icon: 'ti-package', label: 'Receive a delivery', href: '#screen6' }, { icon: 'ti-clipboard-x', label: 'Submit goods lost', href: '#screen6b' }, ]}, ] }, }; function buildSidebar(containerId, role, activeHref) { const def = sidebarDefs[role]; if (!def) return; const container = document.getElementById(containerId); if (!container) return; let html = `
${def.role}
${def.loc}
`; def.groups.forEach(g => { html += `
${g.label}
`; g.items.forEach(item => { const active = item.href === activeHref ? ' active' : ''; html += ` ${item.label} `; }); html += `
`; }); html += `
`; container.insertAdjacentHTML('afterbegin', html); } // Build sidebars after DOM loads document.addEventListener('DOMContentLoaded', () => { buildSidebar('sb-admin-s1', 'admin', '#screen1'); buildSidebar('sb-admin-s2', 'admin', '#screen2'); buildSidebar('sb-admin-s3', 'admin', '#screen3'); buildSidebar('sb-admin-s4', 'admin', '#screen4'); buildSidebar('sb-il-s5', 'il', '#screen5'); buildSidebar('sb-il-s6', 'il', '#screen6'); buildSidebar('sb-il-s7', 'il', null); buildSidebar('sb-il-s8', 'il', '#screen8'); buildSidebar('sb-il-s9', 'il', '#screen9'); buildSidebar('sb-admin-s10', 'admin', '#screen10'); buildSidebar('sb-admin-s10b', 'admin', '#screen10b'); buildSidebar('sb-recv-s6b', 'receiver', '#screen6b'); }); // ── Boot ────────────────────────────────────────────────────── (function boot() { var user = {}; try { user = JSON.parse(localStorage.getItem('medsync_user') || '{}'); } catch(e) {} if (user.full_name) { var av = document.getElementById('ms-avatar'); if (av) av.textContent = user.full_name.split(' ').map(function(w){return w[0];}).join('').slice(0,2).toUpperCase(); } if (user.role) { var rb = document.getElementById('ms-role'); if (rb) rb.textContent = user.role === 'admin' ? 'Admin' : 'Manager'; } showScreen('portfolio'); })();