/* ============================================================ App root — state, scheduler wiring, simulation, exports ============================================================ */ /* ════════════════════════════════════════════════════════════ 🔑 SET YOUR DASHBOARD PASSWORD HERE Change the text between the quotes to whatever you want. Anyone opening the dashboard must type this to get in. ════════════════════════════════════════════════════════════ */ const ACCESS_PASSWORD = 'ejay2026'; const DEFAULT_WEEK = '2026-06-15'; // Monday function defaultTrucks() { return [ { id: 'T1', name: 'Truck 1 — Cascadia', code: 'T-01', plate: 'NC 8842-RF' }, { id: 'T2', name: 'Truck 2 — Volvo VNL', code: 'T-02', plate: 'NC 5519-KM' }, { id: 'T3', name: 'Truck 3 — Kenworth', code: 'T-03', plate: 'NC 7203-PB' }, ]; } function defaultDrivers() { return [ { id: 1, name: 'Marcus Bell', phone: '(704) 555-0142', license: 'CDL-A', status: 'Active', assignedTruck: 'T1' }, { id: 2, name: 'Luis Romero', phone: '(919) 555-0188', license: 'CDL-A', status: 'Active', assignedTruck: 'T2' }, { id: 3, name: 'Andre Whitfield', phone: '(336) 555-0173', license: 'CDL-A', status: 'Active', assignedTruck: 'T3' }, { id: 4, name: 'Devon Clarke', phone: '(704) 555-0119', license: 'CDL-A', status: 'Active', assignedTruck: 'T1' }, { id: 5, name: 'Ray Sandoval', phone: '(910) 555-0156', license: 'CDL-A', status: 'Active', assignedTruck: 'T2' }, { id: 6, name: 'Tyler Hodge', phone: '(828) 555-0134', license: 'CDL-A', status: 'Active', assignedTruck: 'T3' }, ]; } function App() { const [authed, setAuthed] = useState(() => { try { return sessionStorage.getItem('ejay_auth') === '1'; } catch (_) { return false; } }); const [password, setPassword] = useState(() => { try { return localStorage.getItem('ejay_pw') || ACCESS_PASSWORD; } catch (_) { return ACCESS_PASSWORD; } }); const [view, setView] = useState('dashboard'); const [theme, setTheme] = useState('dark'); const [weekStart, setWeekStartRaw] = useState(DEFAULT_WEEK); const [drivers, setDrivers] = useState(defaultDrivers()); const [trucks, setTrucks] = useState(defaultTrucks()); const [schedule, setSchedule] = useState(() => Engine.generate(DEFAULT_WEEK, defaultDrivers(), defaultTrucks())); const [simulating, setSimulating] = useState(false); const [simDate, setSimDate] = useState(DEFAULT_WEEK); const [toast, setToast] = useState(null); const [mobileOpen, setMobileOpen] = useState(false); const [dispatcherDone, setDispatcherDone] = useState(() => { try { return JSON.parse(localStorage.getItem('ejay_dispatcher_v1') || '{}'); } catch (e) { return {}; } }); const toastTimer = useRef(null); useEffect(() => { try { localStorage.setItem('ejay_dispatcher_v1', JSON.stringify(dispatcherDone)); } catch (e) {} }, [dispatcherDone]); useEffect(() => { document.documentElement.setAttribute('data-theme', theme); }, [theme]); const flash = (msg) => { setToast(msg); clearTimeout(toastTimer.current); toastTimer.current = setTimeout(() => setToast(null), 2200); }; const regenerate = (ws, drv, trk) => { const start = Engine.snapToMonday(ws || weekStart); setSchedule(Engine.generate(start, drv || drivers, trk || trucks)); }; const setWeekStart = (d) => { setWeekStartRaw(d); }; const generate = () => { setSimulating(false); const start = Engine.snapToMonday(weekStart); setSchedule(Engine.generate(start, drivers, trucks)); setSimDate(start); flash('Weekly schedule generated'); }; const reset = () => { setSimulating(false); const d = defaultDrivers(), t = defaultTrucks(); setDrivers(d); setTrucks(t); setWeekStartRaw(DEFAULT_WEEK); setSchedule(Engine.generate(DEFAULT_WEEK, d, t)); setSimDate(DEFAULT_WEEK); flash('Reset to default demo'); }; /* ---- driver CRUD ---- */ const addDriver = (form) => { const id = drivers.reduce((m, d) => Math.max(m, d.id), 0) + 1; const nd = [...drivers, { id, ...form }]; setDrivers(nd); regenerate(null, nd, null); flash('Driver added'); }; const updateDriver = (id, form) => { const nd = drivers.map(d => d.id === id ? { ...d, ...form } : d); setDrivers(nd); regenerate(null, nd, null); flash('Driver updated'); }; const deleteDriver = (id) => { const nd = drivers.filter(d => d.id !== id); setDrivers(nd); regenerate(null, nd, null); flash('Driver removed'); }; /* ---- truck CRUD ---- */ const addTruck = (form) => { const id = 'T' + (trucks.reduce((m, t) => Math.max(m, +String(t.id).replace(/\D/g, '') || 0), 0) + 1); const nt = [...trucks, { id, ...form }]; setTrucks(nt); regenerate(null, null, nt); flash('Truck added'); }; const updateTruck = (id, form) => { const nt = trucks.map(t => t.id === id ? { ...t, ...form } : t); setTrucks(nt); regenerate(null, null, nt); flash('Truck updated'); }; const deleteTruck = (id) => { const nt = trucks.filter(t => t.id !== id); const nd = drivers.map(d => d.assignedTruck === id ? { ...d, assignedTruck: null } : d); setTrucks(nt); setDrivers(nd); regenerate(null, nd, nt); flash('Truck removed'); }; const autoAssign = () => { const nd = Engine.autoAssignTrucks(drivers, trucks); setDrivers(nd); regenerate(null, nd, null); flash('Drivers auto-assigned'); }; const overrideLeg = (id, patch) => { setSchedule(s => s.map(l => l.id === id ? { ...l, ...patch } : l)); flash('Load status updated'); }; /* ---- access password ---- */ const changePassword = (current, next) => { if (current !== password) return 'wrong-current'; if (!next || next.length < 4) return 'too-short'; setPassword(next); try { localStorage.setItem('ejay_pw', next); } catch (_) {} flash('Password updated'); return 'ok'; }; const resetPasswordDefault = () => { setPassword(ACCESS_PASSWORD); try { localStorage.removeItem('ejay_pw'); } catch (_) {} flash('Password reset to default'); }; const lockDashboard = () => { try { sessionStorage.setItem('ejay_auth', '0'); } catch (_) {} setAuthed(false); }; /* ---- simulation ---- */ const toggleSim = () => { if (simulating) { setSimulating(false); return; } const dates = Engine.scheduleDates(schedule); if (!dates.length) return; setSimDate(dates[0]); setSchedule(s => Engine.applyClock(s, dates[0])); setSimulating(true); }; useEffect(() => { if (!simulating) return; const dates = Engine.scheduleDates(schedule); const id = setInterval(() => { setSimDate(prev => { let idx = dates.indexOf(prev); idx = (idx + 1) % (dates.length + 1); const next = idx >= dates.length ? dates[dates.length - 1] : dates[idx]; const clockDate = idx >= dates.length ? Engine.addDays(dates[dates.length - 1], 1) : dates[idx]; setSchedule(s => Engine.applyClock(s, clockDate)); if (idx >= dates.length) { setSimulating(false); return dates[dates.length - 1]; } return next; }); }, 1700); return () => clearInterval(id); }, [simulating]); /* ---- exports ---- */ const buildRows = () => { return [...schedule].sort((a, b) => a.date < b.date ? -1 : 1).map(l => { const drv = drivers.find(d => d.id === l.driverId) || {}; const trk = trucks.find(t => t.id === l.truckId) || {}; const st = l.delayed && l.status !== 'completed' ? 'Delayed' : (STATUS_META[l.status] || {}).label; return { Date: Engine.fmtFull(l.date), Driver: 'Driver ' + l.driverId + ' — ' + (drv.name || ''), Truck: trk.code || '', Activity: l.leg === 'outbound' ? 'Outbound' : 'Backhaul', Route: l.from + ' → ' + l.to, Status: st, }; }); }; const exportExcel = () => { const rows = buildRows(); const cols = ['Date', 'Driver', 'Truck', 'Activity', 'Route', 'Status']; let html = '' + cols.map(c => '').join('') + ''; rows.forEach(r => { html += '' + cols.map(c => '').join('') + ''; }); html += '
' + c + '
' + r[c] + '
'; const blob = new Blob(['\ufeff' + html + ''], { type: 'application/vnd.ms-excel' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'Ejay-Dispatch-' + weekStart + '.xls'; a.click(); flash('Excel exported'); }; const exportPdf = () => { const rows = buildRows(); const cols = ['Date', 'Driver', 'Truck', 'Activity', 'Route', 'Status']; const w = window.open('', '_blank'); const body = rows.map(r => '' + cols.map(c => '' + r[c] + '').join('') + '').join(''); w.document.write(`Ejay Logistics — Weekly Dispatch

Ejay Logistics — Weekly Dispatch

Week of ${Engine.fmtFull(Engine.snapToMonday(weekStart))} · ${rows.length} legs · NC ⇄ NJ

${cols.map(c => '').join('')}${body}
' + c + '
`); w.document.close(); setTimeout(() => w.print(), 350); flash('PDF ready — use Save as PDF'); }; const ctx = { drivers, trucks, schedule, weekStart, theme, simulating, simDate, setView, setWeekStart, setTheme, generate, reset, autoAssign, addDriver, updateDriver, deleteDriver, addTruck, updateTruck, deleteTruck, overrideLeg, exportExcel, exportPdf, dispatcherDone, setDispatcherDone, changePassword, resetPasswordDefault, lockDashboard, defaultPassword: ACCESS_PASSWORD, }; // "today" follows the live-sim clock while running, else NC (US Eastern) date const todayStr = simulating ? simDate : Engine.todayET(); const dispMonday = Engine.snapToMonday(weekStart); let dispatcherAlerts = 0; (window.DISPATCH_WEEK || []).forEach((d, di) => { const dayDate = Engine.addDays(dispMonday, di); if (dayDate < todayStr) { d.tasks.forEach((t, ti) => { if (!dispatcherDone[di + '-' + ti]) dispatcherAlerts++; }); } }); const counts = { drivers: drivers.length, trucks: trucks.length, dispatcherAlerts: dispatcherAlerts }; if (!authed) { return setAuthed(true)} />; } let CurrentView; if (view === 'dashboard') CurrentView = ; else if (view === 'drivers') CurrentView = ; else if (view === 'trucks') CurrentView = ; else if (view === 'schedule') CurrentView = ; else if (view === 'board') CurrentView = ; else if (view === 'dispatcher') CurrentView = ; else CurrentView = ; return (
{mobileOpen &&
setMobileOpen(false)}>
} setMobileOpen(false)} />
setTheme(t => t === 'dark' ? 'light' : 'dark')} simulating={simulating} simDate={simDate} onMenu={() => setMobileOpen(true)} />
{CurrentView}
); } ReactDOM.createRoot(document.getElementById('root')).render(); // Fade out the preloader once the app has mounted and painted. requestAnimationFrame(() => setTimeout(() => { const pl = document.getElementById('ejay-preloader'); if (pl) { pl.classList.add('hide'); setTimeout(() => { pl.style.display = 'none'; }, 500); } }, 300));