/* ============================================================ Shared UI components + icon set ============================================================ */ const { useState, useRef, useEffect, useLayoutEffect } = React; /* ---- Icon set (simple line icons) ---- */ const ICONS = { dashboard: 'M3 3h7v8H3zM14 3h7v5h-7zM14 11h7v10h-7zM3 14h7v7H3z', drivers: 'M16 18a4 4 0 0 0-8 0 M12 11a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4', schedule: 'M4 5h16v15H4zM4 9h16M8 3v4M16 3v4M8 13h2M12 13h2M8 16h2', settings: 'M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6 M19 12a7 7 0 0 0-.1-1.2l2-1.6-2-3.4-2.4 1a7 7 0 0 0-2-1.2L16 1H8l-.5 2.6a7 7 0 0 0-2 1.2l-2.4-1-2 3.4 2 1.6A7 7 0 0 0 3 12a7 7 0 0 0 .1 1.2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 2 1.2L8 23h8l.5-2.6a7 7 0 0 0 2-1.2l2.4 1 2-3.4-2-1.6A7 7 0 0 0 19 12z', board: 'M3 4h6v16H3zM10 4h6v16h-6zM17 4h4v16h-4z', arrow: 'M5 12h14M13 6l6 6-6 6', calendar: 'M4 5h16v15H4zM4 9h16M8 3v4M16 3v4', play: 'M7 5l12 7-12 7z', pause: 'M7 5h4v14H7zM13 5h4v14h-4z', plus: 'M12 5v14M5 12h14', edit: 'M4 20h4l11-11-4-4L4 16zM14 5l4 4', trash: 'M4 7h16M9 7V4h6v3M6 7l1 14h10l1-14', download: 'M12 3v12M7 11l5 5 5-5M4 21h16', refresh: 'M21 12a9 9 0 1 1-3-6.7M21 4v4h-4', check: 'M5 12l5 5 9-11', x: 'M6 6l12 12M18 6L6 18', menu: 'M4 6h16M4 12h16M4 18h16', sun: 'M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8M12 2v2M12 20v2M4 12H2M22 12h-2M5 5l1.5 1.5M17.5 17.5L19 19M19 5l-1.5 1.5M6.5 17.5L5 19', moon: 'M21 13a8 8 0 1 1-9.5-9.5 6.5 6.5 0 0 0 9.5 9.5z', truck: 'M2 6h11v9H2zM13 9h4l4 3v3h-8zM7.5 18.5a1.6 1.6 0 1 0 0-3.2 1.6 1.6 0 0 0 0 3.2M17.5 18.5a1.6 1.6 0 1 0 0-3.2 1.6 1.6 0 0 0 0 3.2', pin: 'M12 21s-7-6.2-7-11a7 7 0 0 1 14 0c0 4.8-7 11-7 11zM12 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6', bolt: 'M13 2L4 14h6l-1 8 9-12h-6z', phone: 'M5 4h4l2 5-3 2a12 12 0 0 0 5 5l2-3 5 2v4a2 2 0 0 1-2 2A18 18 0 0 1 3 6a2 2 0 0 1 2-2z', clock: 'M12 7v5l3 2M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18', box: 'M3 7l9-4 9 4v10l-9 4-9-4zM3 7l9 4 9-4M12 11v10', chart: 'M4 20V10M10 20V4M16 20v-7M22 20H2', flag: 'M5 21V4M5 4h11l-2 4 2 4H5', collapse: 'M15 6l-6 6 6 6', filter: 'M3 5h18l-7 8v6l-4-2v-4z', tasks: 'M4 6l1.6 1.6L8 4M4 12l1.6 1.6L8 10M4 18l1.6 1.6L8 16M11 5h9M11 11h9M11 17h9', }; function Icon({ name, style }) { const d = ICONS[name] || ''; const paths = d.split(' M').map((seg, i) => (i === 0 ? seg : 'M' + seg)); return ( {paths.map((p, i) => )} ); } /* ---- Status helpers ---- */ const STATUS_META = { scheduled: { label: 'Scheduled', cls: 'b-gray' }, in_transit: { label: 'In Transit', cls: 'b-accent' }, completed: { label: 'Completed', cls: 'b-green' }, delayed: { label: 'Delayed', cls: 'b-amber' }, off: { label: 'Off Duty', cls: 'b-gray' }, }; function StatusBadge({ status }) { const m = STATUS_META[status] || STATUS_META.scheduled; return {m.label}; } function Route({ from, to }) { return ( {from} {to} ); } /* ---- Sidebar ---- */ function Sidebar({ view, setView, counts, collapsed, simulating, toggleSim, mobileOpen, closeMobile }) { const NAV = [ { id: 'dashboard', label: 'Dashboard', icon: 'dashboard' }, { id: 'drivers', label: 'Drivers', icon: 'drivers', count: counts.drivers }, { id: 'trucks', label: 'Trucks', icon: 'truck', count: counts.trucks }, { id: 'schedule', label: 'Schedule', icon: 'schedule' }, { id: 'board', label: 'Dispatch Board', icon: 'board' }, { id: 'dispatcher', label: "Dispatcher's Work", icon: 'tasks' }, ]; return ( ); } /* ---- NC (US Eastern) live clock ---- */ function NCClock() { const [now, setNow] = useState(Engine.nowET()); useEffect(() => { const id = setInterval(() => setNow(Engine.nowET()), 1000); return () => clearInterval(id); }, []); const today = Engine.fmtLong(Engine.todayET()); return (
{now} NC · {today}
); } /* ---- Topbar ---- */ const PAGE_META = { dashboard: { title: 'Dispatch Overview', sub: 'Weekly operations at a glance' }, drivers: { title: 'Driver Management', sub: 'Roster, assignments & duty status' }, trucks: { title: 'Truck Management', sub: 'Fleet & utilization tracking' }, schedule: { title: 'Schedule Viewer', sub: 'Per-driver weekly cycle' }, board: { title: 'Dispatch Board', sub: 'Live operations grid' }, dispatcher:{ title: "Dispatcher's Work", sub: 'Daily task checklist' }, settings: { title: 'Settings & Admin', sub: 'Week start, fleet & overrides' }, }; function Topbar({ view, weekStart, theme, toggleTheme, simulating, simDate, onMenu }) { const m = PAGE_META[view] || PAGE_META.dashboard; return (
{m.title}
{m.sub}
{simulating && (
LIVE · {Engine.fmtLong(simDate)}
)}
Week of {Engine.fmtShort(weekStart)} 2026
); } /* ---- KPI card ---- */ function Kpi({ label, value, icon, tone, foot }) { return (
{label}
{value}
{foot &&
{foot}
}
); } /* ---- Modal shell ---- */ function Modal({ title, onClose, children, footer }) { useEffect(() => { const h = e => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', h); return () => window.removeEventListener('keydown', h); }, []); return (
e.stopPropagation()}>

{title}

{children}
{footer &&
{footer}
}
); } /* ---- Toast ---- */ function Toast({ msg }) { if (!msg) return null; return
{msg}
; } /* ---- Login gate ---- */ function LoginGate({ expected, onSuccess }) { const [pw, setPw] = useState(''); const [err, setErr] = useState(false); const [show, setShow] = useState(false); const inputRef = useRef(null); useEffect(() => { inputRef.current && inputRef.current.focus(); }, []); const submit = (e) => { e.preventDefault(); if (pw === expected) { try { sessionStorage.setItem('ejay_auth', '1'); } catch (_) {} onSuccess(); } else { setErr(true); setPw(''); } }; return (
Ejay Logistics
Weekly Dispatch
Secure Access
Enter the dispatch password to continue.
{ setPw(e.target.value); setErr(false); }} />
{err &&
Incorrect password — try again.
}
Authorized personnel only · Ejay Logistics LLC
); } Object.assign(window, { Icon, ICONS, StatusBadge, STATUS_META, Route, Sidebar, Topbar, Kpi, Modal, Toast, LoginGate, NCClock, useState, useRef, useEffect, useLayoutEffect, });