/* ============================================================ 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 = '
| ' + c + ' | ').join('') + '
|---|
| ' + r[c] + ' | ').join('') + '
Week of ${Engine.fmtFull(Engine.snapToMonday(weekStart))} · ${rows.length} legs · NC ⇄ NJ
| ' + c + ' | ').join('')}
|---|