/* ============================================================ Dispatcher's Work — daily task checklist (auto-saved) ============================================================ */ // Task legs: pickups/deliveries the dispatcher must track each day. // kind 'out' = NC→NJ outbound side, 'back' = NJ→NC return side. const DISPATCH_WEEK = [ { day: 'Monday', tasks: [ { driver: 1, action: 'Pickup from NC', loc: 'NC origin', kind: 'out' }, { driver: 1, action: 'Deliver in NJ', loc: 'NJ delivery', kind: 'out' }, { driver: 5, action: 'Deliver in NC', loc: 'NC return', kind: 'back' }, { driver: 6, action: 'Pickup from NJ', loc: 'NJ return load', kind: 'back' }, ]}, { day: 'Tuesday', tasks: [ { driver: 2, action: 'Pickup from NC', loc: 'NC origin', kind: 'out' }, { driver: 2, action: 'Deliver in NJ', loc: 'NJ delivery', kind: 'out' }, { driver: 6, action: 'Deliver in NC', loc: 'NC return', kind: 'back' }, { driver: 1, action: 'Pickup from NJ', loc: 'NJ return load', kind: 'back' }, ]}, { day: 'Wednesday', tasks: [ { driver: 3, action: 'Pickup from NC', loc: 'NC origin', kind: 'out' }, { driver: 3, action: 'Deliver in NJ', loc: 'NJ delivery', kind: 'out' }, { driver: 1, action: 'Deliver in NC', loc: 'NC return', kind: 'back' }, { driver: 2, action: 'Pickup from NJ', loc: 'NJ return load', kind: 'back' }, ]}, { day: 'Thursday', tasks: [ { driver: 4, action: 'Pickup from NC', loc: 'NC origin', kind: 'out' }, { driver: 4, action: 'Deliver in NJ', loc: 'NJ delivery', kind: 'out' }, { driver: 2, action: 'Deliver in NC', loc: 'NC return', kind: 'back' }, { driver: 3, action: 'Pickup from NJ', loc: 'NJ return load', kind: 'back' }, ]}, { day: 'Friday', tasks: [ { driver: 5, action: 'Pickup from NC', loc: 'NC origin', kind: 'out' }, { driver: 5, action: 'Deliver in NJ', loc: 'NJ delivery', kind: 'out' }, { driver: 3, action: 'Deliver in NC', loc: 'NC return', kind: 'back' }, { driver: 4, action: 'Pickup from NJ', loc: 'NJ return load', kind: 'back' }, ]}, { day: 'Saturday', tasks: [ { driver: 6, action: 'Pickup from NC', loc: 'NC origin', kind: 'out' }, { driver: 6, action: 'Deliver in NJ', loc: 'NJ delivery', kind: 'out' }, { driver: 4, action: 'Deliver in NC', loc: 'NC return', kind: 'back' }, { driver: 5, action: 'Pickup from NJ', loc: 'NJ return load', kind: 'back' }, ]}, ]; const DW_STORE = 'ejay_dispatcher_v1'; function DispatcherView({ ctx }) { const done = ctx.dispatcherDone; const setDone = ctx.setDispatcherDone; const toggle = (key) => setDone(d => { const n = { ...d }; if (n[key]) delete n[key]; else n[key] = true; return n; }); const resetAll = () => setDone({}); const driverName = (id) => { const d = ctx.drivers.find(x => x.id === id); return d ? d.name : ('Driver ' + id); }; const monday = Engine.snapToMonday(ctx.weekStart); // "today" follows the live-sim clock while running, else NC (US Eastern) date const todayStr = ctx.simulating ? ctx.simDate : Engine.todayET(); const total = DISPATCH_WEEK.reduce((s, d) => s + d.tasks.length, 0); let completed = 0; DISPATCH_WEEK.forEach((d, di) => d.tasks.forEach((t, ti) => { if (done[di + '-' + ti]) completed++; })); const allDone = completed === total; const pct = Math.round((completed / total) * 100); // missed = tasks on a day that is already over (date < today) and still unchecked const missedDays = []; let missedTotal = 0; DISPATCH_WEEK.forEach((d, di) => { const dayDate = Engine.addDays(monday, di); if (dayDate < todayStr) { const miss = d.tasks.filter((t, ti) => !done[di + '-' + ti]).length; if (miss > 0) { missedDays.push({ day: d.day, count: miss }); missedTotal += miss; } } }); return (
{missedTotal > 0 && (
{missedTotal} task{missedTotal > 1 ? 's' : ''} missed
Incomplete on {missedDays.map(m => m.day + ' (' + m.count + ')').join(', ')}. These days are over — follow up with the drivers.
)} {allDone && (
All Tasks Completed
Every pickup and delivery for the week is checked off and saved.
)}
Weekly Task Checklist
What each driver must do, day by day — tick as you go.
Progress auto-saved
{/* overall progress */}
Week Progress
{pct}%
{completed} / {total}
{DISPATCH_WEEK.map((d, di) => { const dayDoneCount = d.tasks.filter((t, ti) => done[di + '-' + ti]).length; const dayAllDone = dayDoneCount === d.tasks.length; const dayDateStr = Engine.addDays(monday, di); const dayDate = Engine.fmtShort(dayDateStr); const isOver = dayDateStr < todayStr; const isToday = dayDateStr === todayStr; const dayMissed = isOver && !dayAllDone ? (d.tasks.length - dayDoneCount) : 0; let cardCls = 'card day-card'; if (dayMissed > 0) cardCls += ' missed'; else if (dayAllDone) cardCls += ' done'; return (
{d.day}{isToday && Today}
{dayDate} 2026
{dayMissed > 0 ? {dayMissed} Missed : dayAllDone ? All Tasks Completed : {dayDoneCount} / {d.tasks.length}}
{d.tasks.map((t, ti) => { const key = di + '-' + ti; const isDone = !!done[key]; const rowMissed = isOver && !isDone; return (
toggle(key)}>
{t.driver}
{t.action}
{driverName(t.driver)} · {t.kind === 'out' ? 'NC → NJ' : 'NJ → NC'}
); })}
); })}
); } Object.assign(window, { DispatcherView, DISPATCH_WEEK });