diff --git a/frontend/src/components/dashboard/FleetDashboardShell.jsx b/frontend/src/components/dashboard/FleetDashboardShell.jsx index 6b424a2..068615b 100644 --- a/frontend/src/components/dashboard/FleetDashboardShell.jsx +++ b/frontend/src/components/dashboard/FleetDashboardShell.jsx @@ -442,6 +442,20 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page () => scopedWorkOrders.slice((currentPage - 1) * pageSize, currentPage * pageSize), [scopedWorkOrders, currentPage] ); + + // Map: workOrderId → array of unique crane objects (own + cross-crane task links) + const workOrderSharedCranes = useMemo(() => { + const craneById = new Map(cranes.map((c) => [String(c.id), c])); + const map = new Map(); + tasks.forEach((task) => { + if (!task.work_order || !task.vehicle) return; + const woId = String(task.work_order); + if (!map.has(woId)) map.set(woId, new Map()); + const craneObj = craneById.get(String(task.vehicle)); + if (craneObj) map.get(woId).set(String(task.vehicle), craneObj); + }); + return map; + }, [tasks, cranes]); const serviceRecordWorkOrders = useMemo(() => { // Show ALL open work orders so a task can be linked to any work order regardless of crane. // Cross-crane sharing is intentional: a servicer may use one travel order for multiple cranes. @@ -973,10 +987,30 @@ export default function FleetDashboardShell({ initialSection = 'dashboard', page - {[workOrder.craneInfo?.make, workOrder.craneInfo?.model].filter(Boolean).join(' ') || workOrder.craneLabel || workOrder.craneInfo?.registration_number || `#${workOrder.crane || workOrder.vehicle}`} + {(() => { + const sharedCranes = workOrderSharedCranes.get(String(workOrder.id)); + if (sharedCranes && sharedCranes.size > 0) { + return [...sharedCranes.values()].map((c) => ( + [c.make, c.model].filter(Boolean).join(' ') || c.registration_number || `#${c.id}` + )).join(' • '); + } + return [workOrder.craneInfo?.make, workOrder.craneInfo?.model].filter(Boolean).join(' ') + || workOrder.craneLabel + || workOrder.craneInfo?.registration_number + || `#${workOrder.crane || workOrder.vehicle}`; + })()} - {workOrder.craneInfo?.crane_serial_number || '-'} + {(() => { + const sharedCranes = workOrderSharedCranes.get(String(workOrder.id)); + if (sharedCranes && sharedCranes.size > 0) { + const sns = [...sharedCranes.values()] + .map((c) => c.crane_serial_number) + .filter(Boolean); + return sns.length > 0 ? sns.join(' • ') : '-'; + } + return workOrder.craneInfo?.crane_serial_number || '-'; + })()} {formatDate(workOrder.date)}