// ── Undo stack composable ──────────────────────────────────────────────────── import { ref, nextTick } from 'vue' import { updateJob } from 'src/api/dispatch' import { serializeAssistants } from './useHelpers' export function useUndo (store, invalidateRoutes) { const undoStack = ref([]) function pushUndo (action) { undoStack.value.push(action) if (undoStack.value.length > 30) undoStack.value.shift() } // Restore a single job to its previous state (unassign from current tech, re-assign if it had one) function _restoreJob (prev) { const job = store.jobs.find(j => j.id === prev.jobId) if (!job) return // Remove from all tech queues first store.technicians.forEach(t => { t.queue = t.queue.filter(q => q.id !== prev.jobId) }) if (prev.techId) { // Was assigned before — re-assign store.assignJobToTech(prev.jobId, prev.techId, prev.routeOrder, prev.scheduledDate) } else { // Was unassigned before — just mark as open job.assignedTech = null job.status = 'open' job.scheduledDate = prev.scheduledDate || null updateJob(job.name || job.id, { assigned_tech: null, status: 'open', scheduled_date: prev.scheduledDate || '' }).catch(() => {}) } if (prev.assistants?.length) { job.assistants = prev.assistants updateJob(job.name || job.id, { assistants: serializeAssistants(job.assistants) }).catch(() => {}) } } function performUndo () { const action = undoStack.value.pop() if (!action) return if (action.type === 'removeAssistant') { store.addAssistant(action.jobId, action.techId) nextTick(() => { const job = store.jobs.find(j => j.id === action.jobId) const a = job?.assistants.find(x => x.techId === action.techId) if (a) { a.duration = action.duration; a.note = action.note } updateJob(job.name || job.id, { assistants: serializeAssistants(job.assistants) }).catch(() => {}) }) } else if (action.type === 'optimizeRoute') { const tech = store.technicians.find(t => t.id === action.techId) if (tech) { tech.queue = action.prevQueue action.prevQueue.forEach((j, i) => { j.routeOrder = i }) } } else if (action.type === 'autoDistribute') { action.assignments.forEach(a => _restoreJob(a)) if (action.prevQueues) { store.technicians.forEach(t => { if (action.prevQueues[t.id]) t.queue = action.prevQueues[t.id] }) } } else if (action.type === 'batchAssign') { // Undo a multi-select drag — restore each job to previous state action.assignments.forEach(a => _restoreJob(a)) } else if (action.type === 'unassignJob') { _restoreJob(action) } // Rebuild assistJobs on all techs store.technicians.forEach(t => { t.assistJobs = store.jobs.filter(j => j.assistants.some(a => a.techId === t.id)) }) invalidateRoutes() } return { undoStack, pushUndo, performUndo } }