@fleetbase/fleetops-engine 0.6.38 → 0.6.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/addon/components/activity/form.hbs +2 -12
  2. package/addon/components/activity/logic-builder.hbs +1 -1
  3. package/addon/components/custom-entity/form.hbs +4 -20
  4. package/addon/components/device/form.hbs +3 -15
  5. package/addon/components/device/panel-header.hbs +13 -2
  6. package/addon/components/driver/details.hbs +33 -2
  7. package/addon/components/driver/form.hbs +42 -0
  8. package/addon/components/driver/panel-header.hbs +8 -1
  9. package/addon/components/driver/schedule.hbs +115 -76
  10. package/addon/components/driver/schedule.js +349 -157
  11. package/addon/components/driver-onboard-settings.hbs +2 -8
  12. package/addon/components/entity-field-editing-settings.hbs +2 -5
  13. package/addon/components/equipment/card.hbs +49 -0
  14. package/addon/components/equipment/card.js +6 -0
  15. package/addon/components/equipment/details.hbs +83 -44
  16. package/addon/components/equipment/form.hbs +111 -41
  17. package/addon/components/equipment/form.js +78 -10
  18. package/addon/components/equipment/panel-header.hbs +36 -0
  19. package/addon/components/equipment/panel-header.js +2 -0
  20. package/addon/components/fleet/driver-listing.hbs +3 -1
  21. package/addon/components/fleet/vehicle-listing.hbs +4 -7
  22. package/addon/components/fleet-panel/vehicle-listing.hbs +1 -6
  23. package/addon/components/fuel-report/form.hbs +1 -5
  24. package/addon/components/layout/fleet-ops-sidebar.hbs +40 -36
  25. package/addon/components/layout/fleet-ops-sidebar.js +61 -10
  26. package/addon/components/maintenance/cost-panel.hbs +176 -0
  27. package/addon/components/maintenance/cost-panel.js +241 -0
  28. package/addon/components/maintenance/details.hbs +123 -60
  29. package/addon/components/maintenance/form.hbs +138 -78
  30. package/addon/components/maintenance/form.js +131 -6
  31. package/addon/components/maintenance/panel-header.hbs +31 -0
  32. package/addon/components/maintenance/panel-header.js +2 -0
  33. package/addon/components/maintenance-schedule/details.hbs +260 -0
  34. package/addon/components/maintenance-schedule/details.js +158 -0
  35. package/addon/components/maintenance-schedule/form.hbs +287 -0
  36. package/addon/components/maintenance-schedule/form.js +199 -0
  37. package/addon/components/map/container.hbs +1 -1
  38. package/addon/components/map/drawer/device-event-listing.hbs +1 -1
  39. package/addon/components/map/drawer/driver-listing.hbs +1 -6
  40. package/addon/components/map/drawer/place-listing.hbs +1 -6
  41. package/addon/components/map/drawer/vehicle-listing.hbs +1 -6
  42. package/addon/components/map/drawer.hbs +8 -1
  43. package/addon/components/map/leaflet-live-map.hbs +2 -1
  44. package/addon/components/map/toolbar/visibility-control-panel.hbs +1 -1
  45. package/addon/components/map/toolbar.hbs +4 -29
  46. package/addon/components/modals/add-driver-shift.hbs +155 -0
  47. package/addon/components/modals/add-driver-shift.js +210 -0
  48. package/addon/components/modals/bulk-assign-orders.hbs +67 -0
  49. package/addon/components/modals/driver-shift.hbs +43 -0
  50. package/addon/components/modals/driver-shift.js +56 -0
  51. package/addon/components/modals/entity-form.hbs +5 -28
  52. package/addon/components/modals/orchestrator-import.hbs +351 -0
  53. package/addon/components/modals/orchestrator-import.js +807 -0
  54. package/addon/components/modals/order-config-new-status.hbs +1 -5
  55. package/addon/components/modals/scheduling-conflict.hbs +47 -0
  56. package/addon/components/modals/scheduling-conflict.js +53 -0
  57. package/addon/components/modals/send-work-order.hbs +91 -0
  58. package/addon/components/modals/send-work-order.js +3 -0
  59. package/addon/components/modals/service-area-form.hbs +1 -6
  60. package/addon/components/modals/set-driver-availability.hbs +50 -0
  61. package/addon/components/modals/set-driver-availability.js +57 -0
  62. package/addon/components/modals/update-order-activity.hbs +13 -9
  63. package/addon/components/modals/user-form.hbs +1 -5
  64. package/addon/components/modals/vehicle-form.hbs +17 -102
  65. package/addon/components/modals/vendor-form.hbs +15 -82
  66. package/addon/components/orchestrator/card-fields-settings.hbs +76 -0
  67. package/addon/components/orchestrator/card-fields-settings.js +134 -0
  68. package/addon/components/orchestrator/order-pool.hbs +264 -0
  69. package/addon/components/orchestrator/order-pool.js +394 -0
  70. package/addon/components/orchestrator/phase-builder.hbs +162 -0
  71. package/addon/components/orchestrator/phase-builder.js +162 -0
  72. package/addon/components/orchestrator/plan-viewer.hbs +278 -0
  73. package/addon/components/orchestrator/plan-viewer.js +342 -0
  74. package/addon/components/orchestrator/resource-panel.hbs +301 -0
  75. package/addon/components/orchestrator/resource-panel.js +106 -0
  76. package/addon/components/orchestrator-workbench.hbs +318 -0
  77. package/addon/components/orchestrator-workbench.js +1087 -0
  78. package/addon/components/order/details/custom-fields.hbs +10 -1
  79. package/addon/components/order/details/detail.hbs +37 -2
  80. package/addon/components/order/details/detail.js +0 -1
  81. package/addon/components/order/details/integrated-vendor-details.hbs +4 -4
  82. package/addon/components/order/details/notes.hbs +1 -7
  83. package/addon/components/order/details/route.hbs +1 -5
  84. package/addon/components/order/form/details.hbs +44 -10
  85. package/addon/components/order/form/details.js +57 -0
  86. package/addon/components/order/form/notes.hbs +1 -7
  87. package/addon/components/order/form/payload.hbs +1 -7
  88. package/addon/components/order/form/route.hbs +3 -15
  89. package/addon/components/order/header.hbs +1 -7
  90. package/addon/components/order/route-editor.hbs +4 -25
  91. package/addon/components/order/schedule-card.hbs +102 -95
  92. package/addon/components/order/schedule-card.js +8 -3
  93. package/addon/components/order-config-manager/details.hbs +2 -10
  94. package/addon/components/order-config-manager/entities.hbs +1 -7
  95. package/addon/components/order-config-manager.hbs +1 -6
  96. package/addon/components/part/card.hbs +49 -0
  97. package/addon/components/part/card.js +6 -0
  98. package/addon/components/part/details.hbs +102 -56
  99. package/addon/components/part/form.hbs +131 -56
  100. package/addon/components/part/form.js +78 -11
  101. package/addon/components/part/panel-header.hbs +36 -0
  102. package/addon/components/part/panel-header.js +2 -0
  103. package/addon/components/place/form.hbs +1 -7
  104. package/addon/components/sensor/details.hbs +1 -1
  105. package/addon/components/sensor/form.hbs +5 -3
  106. package/addon/components/sensor/panel-header.hbs +8 -1
  107. package/addon/components/service-area/form.hbs +1 -6
  108. package/addon/components/service-rate/form.hbs +12 -60
  109. package/addon/components/telematic/form.hbs +6 -2
  110. package/addon/components/vehicle/details/maintenance-history.hbs +42 -0
  111. package/addon/components/vehicle/details/maintenance-history.js +32 -0
  112. package/addon/components/vehicle/details/schedules.hbs +40 -0
  113. package/addon/components/vehicle/details/schedules.js +32 -0
  114. package/addon/components/vehicle/details/work-orders.hbs +42 -0
  115. package/addon/components/vehicle/details/work-orders.js +32 -0
  116. package/addon/components/vehicle/details.hbs +30 -0
  117. package/addon/components/vehicle/form.hbs +39 -0
  118. package/addon/components/vehicle/panel-header.hbs +19 -49
  119. package/addon/components/warranty/details.hbs +3 -2
  120. package/addon/components/warranty/form.hbs +3 -17
  121. package/addon/components/work-order/details.hbs +135 -40
  122. package/addon/components/work-order/form.hbs +178 -45
  123. package/addon/components/work-order/form.js +197 -4
  124. package/addon/components/work-order/panel-header.hbs +31 -0
  125. package/addon/components/work-order/panel-header.js +2 -0
  126. package/addon/controllers/connectivity/devices/index/details.js +1 -1
  127. package/addon/controllers/maintenance/equipment/index/details/index.js +0 -1
  128. package/addon/controllers/maintenance/equipment/index/details.js +36 -1
  129. package/addon/controllers/maintenance/equipment/index/edit.js +56 -1
  130. package/addon/controllers/maintenance/equipment/index/new.js +32 -1
  131. package/addon/controllers/maintenance/equipment/index.js +127 -113
  132. package/addon/controllers/maintenance/maintenances/index/details/index.js +3 -0
  133. package/addon/controllers/maintenance/maintenances/index/details.js +54 -0
  134. package/addon/controllers/maintenance/maintenances/index/edit.js +68 -0
  135. package/addon/controllers/maintenance/maintenances/index/new.js +34 -0
  136. package/addon/controllers/maintenance/maintenances/index.js +191 -0
  137. package/addon/controllers/maintenance/parts/index/details/index.js +0 -1
  138. package/addon/controllers/maintenance/parts/index/details.js +36 -1
  139. package/addon/controllers/maintenance/parts/index/edit.js +56 -1
  140. package/addon/controllers/maintenance/parts/index/new.js +32 -1
  141. package/addon/controllers/maintenance/parts/index.js +135 -113
  142. package/addon/controllers/maintenance/schedules/index/details.js +115 -0
  143. package/addon/controllers/maintenance/schedules/index/edit.js +41 -0
  144. package/addon/controllers/maintenance/schedules/index/new.js +33 -0
  145. package/addon/controllers/maintenance/schedules/index.js +280 -0
  146. package/addon/controllers/maintenance/work-orders/index/details.js +41 -1
  147. package/addon/controllers/maintenance/work-orders/index/edit.js +67 -1
  148. package/addon/controllers/maintenance/work-orders/index/new.js +43 -1
  149. package/addon/controllers/maintenance/work-orders/index.js +105 -113
  150. package/addon/controllers/management/drivers/index/details.js +6 -1
  151. package/addon/controllers/management/vehicles/index/details.js +65 -0
  152. package/addon/controllers/management/vehicles/index.js +18 -0
  153. package/addon/controllers/operations/orchestrator.js +10 -0
  154. package/addon/controllers/operations/orders/index.js +6 -0
  155. package/addon/controllers/operations/scheduler/fleet-schedule.js +341 -0
  156. package/addon/controllers/operations/scheduler/index.js +799 -275
  157. package/addon/controllers/operations/scheduler.js +21 -0
  158. package/addon/controllers/settings/orchestrator.js +70 -0
  159. package/addon/controllers/settings/scheduling.js +155 -0
  160. package/addon/extension.js +19 -0
  161. package/addon/instance-initializers/register-vroom-allocation.js +27 -0
  162. package/addon/models/maintenance-schedule.js +61 -0
  163. package/addon/routes/maintenance/equipment/index/details.js +27 -1
  164. package/addon/routes/maintenance/equipment/index/edit.js +27 -1
  165. package/addon/routes/maintenance/maintenances/index/details/index.js +3 -0
  166. package/addon/routes/maintenance/maintenances/index/details.js +29 -0
  167. package/addon/routes/maintenance/maintenances/index/edit.js +29 -0
  168. package/addon/routes/maintenance/maintenances/index/new.js +3 -0
  169. package/addon/routes/maintenance/maintenances/index.js +23 -0
  170. package/addon/routes/maintenance/maintenances.js +3 -0
  171. package/addon/routes/maintenance/parts/index/details.js +27 -1
  172. package/addon/routes/maintenance/parts/index/edit.js +27 -1
  173. package/addon/routes/maintenance/schedules/index/details/index.js +2 -0
  174. package/addon/routes/maintenance/schedules/index/details/work-orders.js +11 -0
  175. package/addon/routes/maintenance/schedules/index/details.js +25 -0
  176. package/addon/routes/maintenance/schedules/index/edit.js +25 -0
  177. package/addon/routes/maintenance/schedules/index/new.js +2 -0
  178. package/addon/routes/maintenance/schedules/index.js +21 -0
  179. package/addon/routes/maintenance/schedules.js +2 -0
  180. package/addon/routes/maintenance/work-orders/index/details.js +27 -1
  181. package/addon/routes/maintenance/work-orders/index/edit.js +27 -1
  182. package/addon/routes/management/vehicles/index/details/maintenance-history.js +3 -0
  183. package/addon/routes/management/vehicles/index/details/schedules.js +3 -0
  184. package/addon/routes/management/vehicles/index/details/work-orders.js +3 -0
  185. package/addon/routes/operations/orchestrator.js +23 -0
  186. package/addon/routes/operations/scheduler/fleet-schedule.js +28 -0
  187. package/addon/routes/operations/scheduler/index.js +48 -26
  188. package/addon/routes/operations/scheduler.js +14 -1
  189. package/addon/routes/settings/orchestrator.js +27 -0
  190. package/addon/routes/settings/scheduling.js +3 -0
  191. package/addon/routes.js +31 -1
  192. package/addon/services/driver-actions.js +40 -7
  193. package/addon/services/driver-scheduling.js +4 -1
  194. package/addon/services/equipment-actions.js +15 -5
  195. package/addon/services/leaflet-map-manager.js +14 -6
  196. package/addon/services/maintenance-actions.js +17 -14
  197. package/addon/services/maintenance-schedule-actions.js +118 -0
  198. package/addon/services/orchestration-engine-interface.js +49 -0
  199. package/addon/services/orchestration-engine.js +74 -0
  200. package/addon/services/order-actions.js +15 -0
  201. package/addon/services/order-allocation.js +116 -0
  202. package/addon/services/part-actions.js +12 -2
  203. package/addon/services/scheduling.js +316 -0
  204. package/addon/services/vehicle-actions.js +70 -7
  205. package/addon/services/vroom-allocation-engine.js +45 -0
  206. package/addon/services/work-order-actions.js +80 -0
  207. package/addon/styles/fleetops-engine.css +1658 -0
  208. package/addon/templates/analytics/reports/index/edit.hbs +1 -1
  209. package/addon/templates/analytics/reports/index/new.hbs +1 -1
  210. package/addon/templates/application.hbs +6 -1
  211. package/addon/templates/connectivity/devices/index/details/events.hbs +0 -1
  212. package/addon/templates/connectivity/devices.hbs +0 -1
  213. package/addon/templates/connectivity/events/index/details.hbs +0 -1
  214. package/addon/templates/connectivity/events.hbs +0 -1
  215. package/addon/templates/connectivity/sensors.hbs +0 -1
  216. package/addon/templates/connectivity/telematics/index/details/devices.hbs +0 -1
  217. package/addon/templates/connectivity/telematics/index/details/events.hbs +0 -1
  218. package/addon/templates/connectivity/telematics/index/details/sensors.hbs +0 -1
  219. package/addon/templates/connectivity/telematics.hbs +0 -1
  220. package/addon/templates/connectivity/tracking.hbs +0 -1
  221. package/addon/templates/connectivity.hbs +0 -1
  222. package/addon/templates/maintenance/equipment/index/details/index.hbs +1 -2
  223. package/addon/templates/maintenance/equipment/index/details.hbs +15 -2
  224. package/addon/templates/maintenance/equipment/index/edit.hbs +12 -2
  225. package/addon/templates/maintenance/equipment/index/new.hbs +1 -2
  226. package/addon/templates/maintenance/equipment/index.hbs +48 -13
  227. package/addon/templates/maintenance/equipment.hbs +0 -1
  228. package/addon/templates/maintenance/maintenances/index/details/index.hbs +1 -0
  229. package/addon/templates/maintenance/maintenances/index/details.hbs +15 -0
  230. package/addon/templates/maintenance/maintenances/index/edit.hbs +12 -0
  231. package/addon/templates/maintenance/maintenances/index/new.hbs +11 -0
  232. package/addon/templates/maintenance/maintenances/index.hbs +14 -0
  233. package/addon/templates/maintenance/maintenances.hbs +1 -0
  234. package/addon/templates/maintenance/parts/index/details/index.hbs +1 -2
  235. package/addon/templates/maintenance/parts/index/details.hbs +15 -2
  236. package/addon/templates/maintenance/parts/index/edit.hbs +12 -2
  237. package/addon/templates/maintenance/parts/index/new.hbs +1 -2
  238. package/addon/templates/maintenance/parts/index.hbs +48 -13
  239. package/addon/templates/maintenance/parts.hbs +0 -1
  240. package/addon/templates/maintenance/schedules/index/details/index.hbs +1 -0
  241. package/addon/templates/maintenance/schedules/index/details/work-orders.hbs +39 -0
  242. package/addon/templates/maintenance/schedules/index/details.hbs +14 -0
  243. package/addon/templates/maintenance/schedules/index/edit.hbs +12 -0
  244. package/addon/templates/maintenance/schedules/index/new.hbs +11 -0
  245. package/addon/templates/maintenance/schedules/index.hbs +40 -0
  246. package/addon/templates/maintenance/schedules.hbs +1 -0
  247. package/addon/templates/maintenance/work-orders/index/details.hbs +2 -1
  248. package/addon/templates/maintenance/work-orders/index/edit.hbs +2 -4
  249. package/addon/templates/maintenance/work-orders/index/new.hbs +1 -2
  250. package/addon/templates/maintenance/work-orders.hbs +0 -1
  251. package/addon/templates/management/contacts/customers/edit.hbs +1 -2
  252. package/addon/templates/management/contacts/customers/new.hbs +1 -2
  253. package/addon/templates/management/contacts/customers.hbs +1 -1
  254. package/addon/templates/management/contacts/index/edit.hbs +1 -2
  255. package/addon/templates/management/contacts/index/new.hbs +1 -2
  256. package/addon/templates/management/drivers/index/details/orders.hbs +0 -1
  257. package/addon/templates/management/drivers/index/edit.hbs +1 -2
  258. package/addon/templates/management/drivers/index/new.hbs +1 -2
  259. package/addon/templates/management/fleets/index/edit.hbs +1 -2
  260. package/addon/templates/management/fleets/index/new.hbs +1 -2
  261. package/addon/templates/management/fleets/index.hbs +1 -2
  262. package/addon/templates/management/fuel-reports/index/edit.hbs +1 -2
  263. package/addon/templates/management/fuel-reports/index/new.hbs +1 -2
  264. package/addon/templates/management/fuel-reports/index.hbs +1 -2
  265. package/addon/templates/management/issues/index/edit.hbs +1 -2
  266. package/addon/templates/management/issues/index/new.hbs +1 -2
  267. package/addon/templates/management/issues/index.hbs +1 -2
  268. package/addon/templates/management/places/index/details/activity.hbs +0 -1
  269. package/addon/templates/management/places/index/details/comments.hbs +0 -1
  270. package/addon/templates/management/places/index/details/documents.hbs +0 -1
  271. package/addon/templates/management/places/index/details/map.hbs +0 -1
  272. package/addon/templates/management/places/index/details/operations.hbs +0 -1
  273. package/addon/templates/management/places/index/details/performance.hbs +0 -1
  274. package/addon/templates/management/places/index/details/rules.hbs +0 -1
  275. package/addon/templates/management/vehicles/index/details/equipment.hbs +0 -1
  276. package/addon/templates/management/vehicles/index/details/maintenance-history.hbs +2 -0
  277. package/addon/templates/management/vehicles/index/details/schedules.hbs +2 -0
  278. package/addon/templates/management/vehicles/index/details/work-orders.hbs +2 -0
  279. package/addon/templates/management/vehicles/index/details.hbs +1 -1
  280. package/addon/templates/management/vehicles/index/edit.hbs +1 -2
  281. package/addon/templates/management/vehicles/index/new.hbs +1 -2
  282. package/addon/templates/management/vendors/index/edit.hbs +1 -2
  283. package/addon/templates/management/vendors/index/new.hbs +1 -2
  284. package/addon/templates/management/vendors/index.hbs +1 -2
  285. package/addon/templates/management/vendors/integrated.hbs +1 -2
  286. package/addon/templates/operations/orchestrator.hbs +1 -0
  287. package/addon/templates/operations/orders/index.hbs +6 -1
  288. package/addon/templates/operations/scheduler/fleet-schedule.hbs +41 -0
  289. package/addon/templates/operations/scheduler/index.hbs +147 -88
  290. package/addon/templates/operations/scheduler.hbs +7 -1
  291. package/addon/templates/settings/avatars.hbs +1 -1
  292. package/addon/templates/settings/orchestrator.hbs +65 -0
  293. package/addon/templates/settings/payments/index.hbs +1 -5
  294. package/addon/templates/settings/scheduling.hbs +82 -0
  295. package/addon/utils/create-full-calendar-event-from-order.js +52 -14
  296. package/addon/utils/create-full-calendar-event-from-schedule-item.js +50 -0
  297. package/addon/utils/fleet-ops-options.js +254 -0
  298. package/addon/utils/route-colors.js +99 -0
  299. package/addon/utils/to-calendar-date.js +70 -0
  300. package/app/components/driver/schedule.js +1 -0
  301. package/app/components/maintenance/cost-panel.js +1 -0
  302. package/app/components/maintenance/panel-header.js +1 -0
  303. package/app/components/maintenance-schedule/details.js +1 -0
  304. package/app/components/maintenance-schedule/form.js +1 -0
  305. package/app/components/modals/add-driver-shift.js +1 -0
  306. package/app/components/modals/bulk-assign-orders.js +1 -0
  307. package/app/components/modals/driver-shift.js +1 -0
  308. package/app/components/modals/orchestrator-import.js +1 -0
  309. package/app/components/modals/scheduling-conflict.js +1 -0
  310. package/app/components/modals/send-work-order.js +1 -0
  311. package/app/components/modals/set-driver-availability.js +1 -0
  312. package/app/components/orchestrator/card-fields-settings.js +1 -0
  313. package/app/components/orchestrator/order-pool.js +1 -0
  314. package/app/components/orchestrator/phase-builder.js +1 -0
  315. package/app/components/orchestrator/plan-viewer.js +1 -0
  316. package/app/components/orchestrator/resource-panel.js +1 -0
  317. package/app/components/orchestrator-workbench.js +1 -0
  318. package/app/components/vehicle/details/maintenance-history.js +1 -0
  319. package/app/components/vehicle/details/schedules.js +1 -0
  320. package/app/components/vehicle/details/work-orders.js +1 -0
  321. package/app/controllers/operations/orchestrator.js +1 -0
  322. package/app/controllers/settings/orchestrator.js +1 -0
  323. package/app/controllers/settings/scheduling.js +1 -0
  324. package/app/routes/operations/orchestrator.js +1 -0
  325. package/app/routes/settings/orchestrator.js +1 -0
  326. package/app/routes/settings/scheduling.js +1 -0
  327. package/app/services/maintenance-schedule-actions.js +1 -0
  328. package/app/services/orchestration-engine-interface.js +1 -0
  329. package/app/services/orchestration-engine.js +1 -0
  330. package/app/services/order-allocation.js +1 -0
  331. package/app/services/scheduling.js +1 -0
  332. package/app/services/vroom-allocation-engine.js +1 -0
  333. package/app/templates/settings/scheduling.js +1 -0
  334. package/app/utils/create-full-calendar-event-from-schedule-item.js +1 -0
  335. package/app/utils/route-colors.js +1 -0
  336. package/composer.json +5 -3
  337. package/extension.json +1 -1
  338. package/package.json +6 -5
  339. package/server/config/fleetops.php +20 -1
  340. package/server/migrations/2025_08_28_054927_create_parts_table.php +2 -2
  341. package/server/migrations/2025_08_28_054932_add_public_id_to_maintenance_tables.php +45 -0
  342. package/server/migrations/2025_09_01_000001_create_maintenance_schedules_table.php +88 -0
  343. package/server/migrations/2026_04_01_000001_fix_monetary_columns_in_parts_table.php +48 -0
  344. package/server/migrations/2026_04_01_000003_add_photo_uuid_to_equipment_and_parts_tables.php +61 -0
  345. package/server/migrations/2026_04_01_000004_add_public_id_to_equipments_table.php +38 -0
  346. package/server/migrations/2026_04_01_000005_add_missing_columns_to_parts_table.php +67 -0
  347. package/server/migrations/2026_04_04_000001_add_reminder_offsets_to_maintenance_schedules.php +44 -0
  348. package/server/migrations/2026_04_08_000001_add_orchestrator_columns_to_vehicles_table.php +58 -0
  349. package/server/migrations/2026_04_08_000002_add_orchestrator_columns_to_drivers_table.php +41 -0
  350. package/server/migrations/2026_04_08_000003_add_orchestrator_columns_to_orders_table.php +38 -0
  351. package/server/migrations/2026_04_08_000004_add_orchestrator_columns_to_payloads_table.php +41 -0
  352. package/server/migrations/2026_04_08_000005_add_orchestrator_columns_to_waypoints_table.php +38 -0
  353. package/server/migrations/2026_04_09_000001_create_manifests_table.php +48 -0
  354. package/server/migrations/2026_04_09_000002_create_manifest_stops_table.php +48 -0
  355. package/server/migrations/2026_04_09_000003_add_manifest_uuid_to_orders_table.php +28 -0
  356. package/server/migrations/2026_04_13_000001_add_pod_notes_columns_to_waypoints_table.php +39 -0
  357. package/server/resources/views/mail/maintenance-schedule-reminder.blade.php +59 -0
  358. package/server/resources/views/mail/work-order-dispatched.blade.php +67 -0
  359. package/server/src/Auth/Schemas/FleetOps.php +44 -0
  360. package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +150 -0
  361. package/server/src/Console/Commands/SendMaintenanceReminders.php +128 -0
  362. package/server/src/Http/Controllers/Internal/v1/DriverController.php +1 -0
  363. package/server/src/Http/Controllers/Internal/v1/EquipmentController.php +27 -0
  364. package/server/src/Http/Controllers/Internal/v1/LiveController.php +9 -2
  365. package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +165 -0
  366. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +304 -0
  367. package/server/src/Http/Controllers/Internal/v1/ManifestController.php +138 -0
  368. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +975 -0
  369. package/server/src/Http/Controllers/Internal/v1/OrderController.php +42 -0
  370. package/server/src/Http/Controllers/Internal/v1/PartController.php +27 -0
  371. package/server/src/Http/Controllers/Internal/v1/SettingController.php +118 -0
  372. package/server/src/Http/Controllers/Internal/v1/Traits/DriverSchedulingTrait.php +214 -0
  373. package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +68 -0
  374. package/server/src/Http/Resources/v1/Driver.php +1 -0
  375. package/server/src/Http/Resources/v1/Maintenance.php +138 -0
  376. package/server/src/Http/Resources/v1/MaintenanceSchedule.php +137 -0
  377. package/server/src/Http/Resources/v1/Orchestrator/Order.php +116 -0
  378. package/server/src/Http/Resources/v1/Order.php +7 -4
  379. package/server/src/Http/Resources/v1/Waypoint.php +7 -0
  380. package/server/src/Http/Resources/v1/WorkOrder.php +136 -0
  381. package/server/src/Imports/EquipmentImport.php +32 -0
  382. package/server/src/Imports/MaintenanceImport.php +32 -0
  383. package/server/src/Imports/MaintenanceScheduleImport.php +32 -0
  384. package/server/src/Imports/PartImport.php +32 -0
  385. package/server/src/Imports/WorkOrderImport.php +32 -0
  386. package/server/src/Jobs/ProcessAllocationJob.php +119 -0
  387. package/server/src/Listeners/HandleDeliveryCompletion.php +47 -0
  388. package/server/src/Listeners/NotifyDriverOnShiftChange.php +63 -0
  389. package/server/src/Mail/MaintenanceScheduleReminder.php +68 -0
  390. package/server/src/Mail/WorkOrderDispatched.php +58 -0
  391. package/server/src/Models/Asset.php +2 -2
  392. package/server/src/Models/Device.php +1 -1
  393. package/server/src/Models/Driver.php +82 -4
  394. package/server/src/Models/Equipment.php +62 -2
  395. package/server/src/Models/Maintenance.php +127 -9
  396. package/server/src/Models/MaintenanceSchedule.php +353 -0
  397. package/server/src/Models/Manifest.php +214 -0
  398. package/server/src/Models/ManifestStop.php +162 -0
  399. package/server/src/Models/Order.php +70 -0
  400. package/server/src/Models/OrderConfig.php +5 -2
  401. package/server/src/Models/Part.php +69 -3
  402. package/server/src/Models/Payload.php +7 -2
  403. package/server/src/Models/Place.php +1 -1
  404. package/server/src/Models/Sensor.php +1 -1
  405. package/server/src/Models/ServiceQuote.php +1 -1
  406. package/server/src/Models/Vehicle.php +20 -1
  407. package/server/src/Models/Warranty.php +1 -1
  408. package/server/src/Models/Waypoint.php +7 -1
  409. package/server/src/Models/WorkOrder.php +122 -12
  410. package/server/src/Notifications/DriverShiftChanged.php +110 -0
  411. package/server/src/Observers/WorkOrderObserver.php +107 -0
  412. package/server/src/Orchestration/Contracts/OrchestrationEngineInterface.php +63 -0
  413. package/server/src/Orchestration/Engines/DriverAssignmentEngine.php +265 -0
  414. package/server/src/Orchestration/Engines/GreedyOrchestrationEngine.php +155 -0
  415. package/server/src/Orchestration/Engines/RouteSequencingEngine.php +272 -0
  416. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +192 -0
  417. package/server/src/Orchestration/OrchestrationEngineRegistry.php +83 -0
  418. package/server/src/Orchestration/Support/OrchestrationPayloadBuilder.php +290 -0
  419. package/server/src/Providers/EventServiceProvider.php +7 -1
  420. package/server/src/Providers/FleetOpsServiceProvider.php +42 -15
  421. package/server/src/routes.php +65 -4
  422. package/translations/ar-ae.yml +44 -12
  423. package/translations/bg-bg.yaml +51 -10
  424. package/translations/en-us.yaml +444 -1
  425. package/translations/fr-fr.yaml +51 -10
  426. package/translations/mn-mn.yaml +51 -10
  427. package/translations/pt-br.yaml +51 -10
  428. package/translations/ru-ru.yaml +51 -10
  429. package/translations/vi-vn.yaml +48 -12
@@ -13,18 +13,8 @@
13
13
  @disabled={{cannot "fleet-ops update order-config"}}
14
14
  {{on "input" this.setActivityCode}}
15
15
  />
16
- <InputGroup
17
- @name={{t "activity.form.status"}}
18
- @value={{@resource.status}}
19
- @disabled={{cannot "fleet-ops update order-config"}}
20
- @helpText={{t "activity.form.status-help-text"}}
21
- />
22
- <InputGroup
23
- @name={{t "activity.form.details"}}
24
- @value={{@resource.details}}
25
- @disabled={{cannot "fleet-ops update order-config"}}
26
- @helpText={{t "activity.form.details-help-text"}}
27
- />
16
+ <InputGroup @name={{t "activity.form.status"}} @value={{@resource.status}} @disabled={{cannot "fleet-ops update order-config"}} @helpText={{t "activity.form.status-help-text"}} />
17
+ <InputGroup @name={{t "activity.form.details"}} @value={{@resource.details}} @disabled={{cannot "fleet-ops update order-config"}} @helpText={{t "activity.form.details-help-text"}} />
28
18
  <InputGroup>
29
19
  <Toggle @isToggled={{@resource.complete}} @onToggle={{fn (mut @resource.complete)}} @disabled={{cannot "fleet-ops update order-config"}}>
30
20
  <span class="dark:text-gray-100 text-sm ml-2">{{t "activity.form.completes-order"}}</span>
@@ -126,7 +126,7 @@
126
126
  {{else}}
127
127
  <div class="min-h-24 p-4">
128
128
  <div class="flex items-center justify-center border border-dashed border-gray-300 dark:border-gray-600 p-6 rounded-xl bg-gray-50 dark:bg-gray-800">
129
- <div class="flex flex-col items-center justify-center ">
129
+ <div class="flex flex-col items-center justify-center">
130
130
  <FaIcon @icon="layer-group" @size="2x" class="text-gray-400 mb-2" />
131
131
  <div class="text-sm text-gray-600 dark:text-gray-400 font-medium">
132
132
  No activity logic
@@ -21,32 +21,16 @@
21
21
  </ContentPanel>
22
22
  <ContentPanel @title={{t "custom-entity.fields.measurements"}} @open={{true}} @wrapperClass="bordered-top">
23
23
  <div class="grid grid-cols-2 gap-2">
24
- <InputGroup
25
- @name={{t "custom-entity.fields.length"}}
26
- @helpText={{t "custom-entity.fields.length-text"}}
27
- @wrapperClass="mb-2"
28
- >
24
+ <InputGroup @name={{t "custom-entity.fields.length"}} @helpText={{t "custom-entity.fields.length-text"}} @wrapperClass="mb-2">
29
25
  <UnitInput class="w-full" @value={{@resource.length}} @unit={{@resource.dimensions_unit}} @canSelectUnit={{true}} @onUnitChange={{this.updateCustomEntityDimensionsUnit}} />
30
26
  </InputGroup>
31
- <InputGroup
32
- @name={{t "custom-entity.fields.width"}}
33
- @helpText={{t "custom-entity.fields.width-text"}}
34
- @wrapperClass="mb-2"
35
- >
27
+ <InputGroup @name={{t "custom-entity.fields.width"}} @helpText={{t "custom-entity.fields.width-text"}} @wrapperClass="mb-2">
36
28
  <UnitInput class="w-full" @value={{@resource.width}} @unit={{@resource.dimensions_unit}} @canSelectUnit={{true}} @onUnitChange={{this.updateCustomEntityDimensionsUnit}} />
37
29
  </InputGroup>
38
- <InputGroup
39
- @name={{t "custom-entity.fields.height"}}
40
- @helpText={{t "custom-entity.fields.height-text"}}
41
- @wrapperClass="mb-2"
42
- >
30
+ <InputGroup @name={{t "custom-entity.fields.height"}} @helpText={{t "custom-entity.fields.height-text"}} @wrapperClass="mb-2">
43
31
  <UnitInput class="w-full" @value={{@resource.height}} @unit={{@resource.dimensions_unit}} @canSelectUnit={{true}} @onUnitChange={{this.updateCustomEntityDimensionsUnit}} />
44
32
  </InputGroup>
45
- <InputGroup
46
- @name={{t "custom-entity.fields.weight"}}
47
- @helpText={{t "custom-entity.fields.weight-text"}}
48
- @wrapperClass="mb-2"
49
- >
33
+ <InputGroup @name={{t "custom-entity.fields.weight"}} @helpText={{t "custom-entity.fields.weight-text"}} @wrapperClass="mb-2">
50
34
  <UnitInput
51
35
  class="w-full"
52
36
  @value={{@resource.weight}}
@@ -15,7 +15,7 @@
15
15
  >
16
16
  <div class="space-x-2 text-sm">
17
17
  <div class="inline-block align-top">
18
- <div class="hide-from-trigger h-1.5 w-full" />
18
+ <div class="hide-from-trigger h-1.5 w-full"></div>
19
19
  <Image src={{model.provider_descriptor.icon}} class="w-5 h-5" />
20
20
  </div>
21
21
  <div class="inline-block">
@@ -82,13 +82,7 @@
82
82
  </div>
83
83
  <div class="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-2 no-input-group-padding text-xs">
84
84
  <InputGroup @name={{t "device.fields.device-name"}}>
85
- <Input
86
- @value={{@resource.name}}
87
- @type="text"
88
- class="w-full form-input"
89
- placeholder={{t "device.fields.device-name-placeholder"}}
90
- disabled={{cannot-write @resource}}
91
- />
85
+ <Input @value={{@resource.name}} @type="text" class="w-full form-input" placeholder={{t "device.fields.device-name-placeholder"}} disabled={{cannot-write @resource}} />
92
86
  </InputGroup>
93
87
 
94
88
  <InputGroup @name={{t "device.fields.device-id"}}>
@@ -112,13 +106,7 @@
112
106
  </InputGroup>
113
107
 
114
108
  <InputGroup @name={{t "device.fields.device-model"}}>
115
- <Input
116
- @value={{@resource.model}}
117
- @type="text"
118
- class="w-full form-input"
119
- placeholder={{t "device.fields.device-model-placeholder"}}
120
- disabled={{cannot-write @resource}}
121
- />
109
+ <Input @value={{@resource.model}} @type="text" class="w-full form-input" placeholder={{t "device.fields.device-model-placeholder"}} disabled={{cannot-write @resource}} />
122
110
  </InputGroup>
123
111
 
124
112
  <InputGroup @name={{t "device.fields.manufacturer"}}>
@@ -2,7 +2,14 @@
2
2
  <div class="flex flex-1 flex-row items-start justify-between">
3
3
  <div class="flex flex-row space-x-3">
4
4
  <div class="flex items-start justify-start rounded-full">
5
- <Image src={{@resource.photo_url}} @fallbackSrc={{config "defaultValues.placeholderImage"}} alt={{@resource.displayName}} height="48" width="48" class="h-14 w-14 rounded-full shadow-sm" />
5
+ <Image
6
+ src={{@resource.photo_url}}
7
+ @fallbackSrc={{config "defaultValues.placeholderImage"}}
8
+ alt={{@resource.displayName}}
9
+ height="48"
10
+ width="48"
11
+ class="h-14 w-14 rounded-full shadow-sm"
12
+ />
6
13
  <Attach::Tooltip @class="clean" @animation="scale" @placement="top">
7
14
  <InputInfo @text={{@resource.displayName}} />
8
15
  </Attach::Tooltip>
@@ -10,7 +17,11 @@
10
17
  <div class="flex flex-col">
11
18
  <h1 class="text-gray-900 dark:text-white font-semibold text-lg">{{@resource.displayName}}</h1>
12
19
  <div>
13
- <div class="text-xs text-gray-400 dark:text-gray-500">{{concat (n-a (titleize @resource.provider)) " " (n-a (get-fleet-ops-option-label "deviceTypes" @resource.type))}}</div>
20
+ <div class="text-xs text-gray-400 dark:text-gray-500">{{concat
21
+ (n-a (titleize @resource.provider))
22
+ " "
23
+ (n-a (get-fleet-ops-option-label "deviceTypes" @resource.type))
24
+ }}</div>
14
25
  <div class="text-xs text-gray-400 dark:text-gray-500">{{n-a @resource.serial_number}}</div>
15
26
  </div>
16
27
  <Badge @status={{if @resource.online "online" "offline"}}>{{if @resource.online (t "common.online") (t "common.offline")}}</Badge>
@@ -51,14 +51,45 @@
51
51
  </div>
52
52
  </div>
53
53
  </ContentPanel>
54
-
55
54
  <CustomField::Yield @subject={{@resource}} @viewMode={{true}} @wrapperClass="bordered-top" />
56
55
 
57
56
  <RegistryYield @registry="fleet-ops:component:driver:details" as |RegistryComponent|>
58
57
  <RegistryComponent @resource={{@resource}} @controller={{@controller}} @permission={{get-write-permission @resource}} />
59
58
  </RegistryYield>
60
59
 
61
- <ContentPanel @title={{t "common.metadata"}} @open={{true}} @actionButtons={{this.metadataButtons}} @wrapperClass="bordered-top" @panelBodyWrapperClass={{unless (is-object-empty @resource.meta) "px-0i" ""}}>
60
+ {{! ORCHESTRATOR CONSTRAINTS (read-only view) }}
61
+ {{#if (or @resource.skills.length @resource.max_distance @resource.max_travel_time)}}
62
+ <ContentPanel @title="Orchestrator Constraints" @open={{true}} @wrapperClass="bordered-top">
63
+ <div class="grid grid-cols-2 gap-2 text-xs dark:text-gray-100">
64
+ {{#if @resource.skills.length}}
65
+ <div class="field-info-container col-span-2">
66
+ <div class="field-name">Skills & Certifications</div>
67
+ <div class="field-value">{{join @resource.skills ", "}}</div>
68
+ </div>
69
+ {{/if}}
70
+ {{#if @resource.max_travel_time}}
71
+ <div class="field-info-container">
72
+ <div class="field-name">Max Driving Time</div>
73
+ <div class="field-value">{{@resource.max_travel_time}} s</div>
74
+ </div>
75
+ {{/if}}
76
+ {{#if @resource.max_distance}}
77
+ <div class="field-info-container">
78
+ <div class="field-name">Max Distance</div>
79
+ <div class="field-value">{{@resource.max_distance}} m</div>
80
+ </div>
81
+ {{/if}}
82
+ </div>
83
+ </ContentPanel>
84
+ {{/if}}
85
+
86
+ <ContentPanel
87
+ @title={{t "common.metadata"}}
88
+ @open={{true}}
89
+ @actionButtons={{this.metadataButtons}}
90
+ @wrapperClass="bordered-top"
91
+ @panelBodyWrapperClass={{unless (is-object-empty @resource.meta) "px-0i" ""}}
92
+ >
62
93
  <MetadataViewer @metadata={{@resource.meta}} />
63
94
  </ContentPanel>
64
95
  </div>
@@ -166,6 +166,48 @@
166
166
  </RegistryYield>
167
167
  </ContentPanel>
168
168
 
169
+ {{! ORCHESTRATOR CONSTRAINTS }}
170
+ <ContentPanel @title="Orchestrator Constraints" @open={{true}} @wrapperClass="bordered-top">
171
+ <div class="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-2 no-input-group-padding text-xs">
172
+ <div class="col-span-1 lg:col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-1">
173
+ Skills & Certifications
174
+ </div>
175
+ <div class="col-span-1 lg:col-span-2">
176
+ <InputGroup @name="Driver Skills" @helpText="Skills and certifications this driver holds (e.g. refrigerated, hazmat, forklift). Used by the Orchestrator for order matching.">
177
+ <MultiSelect
178
+ @options={{get-fleet-ops-options "driverSkills"}}
179
+ @selected={{@resource.skills}}
180
+ @onChange={{fn (mut @resource.skills)}}
181
+ @placeholder="Select skills…"
182
+ @triggerClass="form-select form-input"
183
+ @disabled={{cannot-write @resource}}
184
+ as |option|
185
+ >
186
+ {{option.label}}
187
+ </MultiSelect>
188
+ </InputGroup>
189
+ </div>
190
+ <div class="col-span-1 lg:col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
191
+ Route Limits
192
+ </div>
193
+ <div class="col-span-1 lg:col-span-2 text-xs text-gray-500 dark:text-gray-400 -mt-1">
194
+ Hard caps applied by the Orchestrator when building a single route. These are separate from the driver's shift schedule, which controls availability windows.
195
+ </div>
196
+ <InputGroup
197
+ @name="Max Driving Time (seconds)"
198
+ @helpText="Maximum total driving time in seconds the Orchestrator may assign to this driver in a single route. Leave blank for no limit. Example: 28800 = 8 hours."
199
+ >
200
+ <Input @value={{@resource.max_travel_time}} @type="number" class="form-input w-full" placeholder="e.g. 28800 (8 h)" disabled={{cannot-write @resource}} />
201
+ </InputGroup>
202
+ <InputGroup
203
+ @name="Max Distance (metres)"
204
+ @helpText="Maximum total route distance in metres the Orchestrator may assign to this driver in a single route. Leave blank for no limit."
205
+ >
206
+ <Input @value={{@resource.max_distance}} @type="number" class="form-input w-full" placeholder="e.g. 150000 (150 km)" disabled={{cannot-write @resource}} />
207
+ </InputGroup>
208
+ </div>
209
+ </ContentPanel>
210
+
169
211
  <CustomField::Yield @subject={{@resource}} @wrapperClass="bordered-top" />
170
212
 
171
213
  <RegistryYield @registry="fleet-ops:component:driver:form" as |RegistryComponent|>
@@ -2,7 +2,14 @@
2
2
  <div class="flex flex-1 flex-row items-start justify-between">
3
3
  <div class="flex flex-row space-x-3">
4
4
  <div class="flex items-start justify-start rounded-full">
5
- <Image src={{@resource.photo_url}} @fallbackSrc={{config "defaultValues.driverImage"}} alt={{@resource.name}} height="48" width="48" class="h-14 w-14 rounded-full shadow-sm" />
5
+ <Image
6
+ src={{@resource.photo_url}}
7
+ @fallbackSrc={{config "defaultValues.driverImage"}}
8
+ alt={{@resource.name}}
9
+ height="48"
10
+ width="48"
11
+ class="h-14 w-14 rounded-full shadow-sm"
12
+ />
6
13
  <Attach::Tooltip @class="clean" @animation="scale" @placement="top">
7
14
  <InputInfo @text={{@resource.name}} />
8
15
  </Attach::Tooltip>
@@ -1,100 +1,139 @@
1
1
  <div class="driver-schedule-container" ...attributes>
2
- <ContentPanel @title="Hours of Service Status" @open={{true}} @isLoading={{this.loadHOSStatus.isRunning}} @wrapperClass="bordered-top">
3
- {{#if this.hosStatus}}
4
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
5
- <div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded">
6
- <div>
7
- <div class="text-sm text-gray-500 dark:text-gray-400">Daily Driving Hours</div>
8
- <div class="text-2xl font-bold">{{this.hosStatus.daily_hours}}/11</div>
9
- </div>
10
- <div class="w-16 h-16">
11
- <CircularProgress @value={{this.hosStatus.daily_hours}} @max={{11}} />
12
- </div>
13
- </div>
14
2
 
15
- <div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded">
16
- <div>
17
- <div class="text-sm text-gray-500 dark:text-gray-400">Weekly Hours</div>
18
- <div class="text-2xl font-bold">{{this.hosStatus.weekly_hours}}/70</div>
19
- </div>
20
- <div class="w-16 h-16">
21
- <CircularProgress @value={{this.hosStatus.weekly_hours}} @max={{70}} />
22
- </div>
23
- </div>
3
+ {{! ── Upcoming Shifts Panel ───────────────────────────────────────────── }}
4
+ <ContentPanel
5
+ @title={{t "scheduler.upcoming-shifts"}}
6
+ @open={{true}}
7
+ @isLoading={{this.loadDriverSchedule.isRunning}}
8
+ @actionButtons={{this.shiftActionButtons}}
9
+ @wrapperClass="bordered-top"
10
+ >
11
+ {{! Week navigation row }}
12
+ <div class="flex items-center justify-end space-x-1 mb-3">
13
+ <Button @icon="chevron-left" @size="xs" @type="link" {{on "click" this.prevWeek}} />
14
+ <span class="text-xs text-gray-500 dark:text-gray-400 tabular-nums">{{this.weekRangeLabel}}</span>
15
+ <Button @icon="chevron-right" @size="xs" @type="link" {{on "click" this.nextWeek}} />
16
+ </div>
24
17
 
25
- <div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded">
26
- <div>
27
- <div class="text-sm text-gray-500 dark:text-gray-400">Compliance Status</div>
18
+ {{! 7-day compact calendar grid }}
19
+ <div class="grid grid-cols-7 gap-px bg-gray-200 dark:bg-gray-700 rounded overflow-hidden text-xs">
20
+ {{#each this.weekDays as |day|}}
21
+ <div class="bg-white dark:bg-gray-800 p-1.5 min-h-16">
22
+ {{! Single-line day header: "Mon 6" }}
23
+ <div class="flex items-center space-x-0.5 mb-1.5">
24
+ <span class="text-gray-400 dark:text-gray-500 uppercase tracking-wide text-[9px]">{{day.label}}</span>
28
25
  <span
29
- class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-{{this.hosComplianceBadge.color}}-100 text-{{this.hosComplianceBadge.color}}-800"
30
- >
31
- {{this.hosComplianceBadge.text}}
32
- </span>
26
+ class="{{if
27
+ day.isToday
28
+ 'flex items-center justify-center w-4 h-4 rounded-full bg-indigo-600 text-white font-bold leading-none text-xs'
29
+ 'text-gray-500 dark:text-gray-400'
30
+ }}"
31
+ >{{day.dayNum}}</span>
33
32
  </div>
33
+ {{! Shift chips — badge info style (light/dark via CSS) }}
34
+ {{#each day.shifts as |shift|}}
35
+ <div class="driver-schedule-shift-chip">
36
+ <span class="shift-chip-time">
37
+ {{format-date-fns shift.start_at "HH:mm"}}–{{format-date-fns shift.end_at "HH:mm"}}
38
+ </span>
39
+ <div class="shift-chip-actions">
40
+ <button type="button" class="shift-chip-action-btn edit" title={{t "scheduler.edit-shift"}} {{on "click" (fn this.editShift shift)}}>
41
+ <FaIcon @icon="pencil" @size="xs" />
42
+ </button>
43
+ <button type="button" class="shift-chip-action-btn delete" title={{t "scheduler.delete-shift"}} {{on "click" (fn this.deleteShift shift)}}>
44
+ <FaIcon @icon="trash" @size="xs" />
45
+ </button>
46
+ </div>
47
+ </div>
48
+ {{/each}}
34
49
  </div>
35
- </div>
36
- {{/if}}
37
- </ContentPanel>
38
- <ContentPanel @title="Schedule Calendar" @open={{true}} @isLoading={{this.loadDriverSchedule.isRunning}} @actionButtons={{this.scheduleActionButtons}} @wrapperClass="bordered-top">
39
- <ScheduleCalendar @items={{this.scheduleItems}} @view="timeGridWeek" @onItemClick={{this.handleItemClick}}>
40
- <:item as |ctx|>
41
- <div class="schedule-item-content">
42
- <div class="font-medium">{{ctx.item.title}}</div>
43
- <div class="text-xs">{{ctx.item.duration}} min</div>
44
- </div>
45
- </:item>
46
- </ScheduleCalendar>
50
+ {{/each}}
51
+ </div>
47
52
  </ContentPanel>
48
53
 
49
- <ContentPanel @title="Upcoming Shifts" @open={{true}} @actionButtons={{this.shiftActionButtons}} @wrapperClass="bordered-top">
50
- {{#if this.upcomingShifts.length}}
51
- <div class="space-y-2">
52
- {{#each this.upcomingShifts as |shift|}}
53
- <ScheduleItemCard @item={{shift}} @onClick={{this.handleItemClick}}>
54
- <:actions>
55
- <button type="button" class="text-blue-600 hover:text-blue-800 text-sm" {{on "click" (fn this.editScheduleItem shift)}}>
56
- Edit
57
- </button>
58
- </:actions>
59
- </ScheduleItemCard>
60
- {{/each}}
54
+ {{! ── HOS Status Panel ────────────────────────────────────────────────── }}
55
+ <ContentPanel @title={{t "scheduler.hours-of-service"}} @open={{true}} @wrapperClass="bordered-top" @isLoading={{this.loadHOSStatus.isRunning}}>
56
+ <div class="grid grid-cols-3 gap-2 text-xs dark:text-gray-100">
57
+ <div class="flex flex-col p-3 bg-gray-50 dark:bg-gray-700 rounded">
58
+ <div class="text-gray-500 dark:text-gray-400">{{t "scheduler.daily-driving-hours"}}</div>
59
+ <div class="text-lg font-bold">{{this.hosStatus.daily_hours}}<span class="text-gray-400 font-normal">/11h</span></div>
61
60
  </div>
62
- {{else}}
63
- <div class="text-center py-4 text-gray-500 dark:text-gray-400">
64
- No upcoming shifts scheduled
61
+ <div class="flex flex-col p-3 bg-gray-50 dark:bg-gray-700 rounded">
62
+ <div class="text-gray-500 dark:text-gray-400">{{t "scheduler.weekly-hours"}}</div>
63
+ <div class="text-lg font-bold">{{this.hosStatus.weekly_hours}}<span class="text-gray-400 font-normal">/70h</span></div>
65
64
  </div>
66
- {{/if}}
65
+ <div class="flex flex-col p-3 bg-gray-50 dark:bg-gray-700 rounded">
66
+ <div class="text-gray-500 dark:text-gray-400">{{t "scheduler.compliance-status"}}</div>
67
+ <span
68
+ class="mt-1 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-{{this.hosComplianceBadge.color}}-100 text-{{this.hosComplianceBadge.color}}-800 dark:bg-{{this.hosComplianceBadge.color}}-900 dark:text-{{this.hosComplianceBadge.color}}-200"
69
+ >
70
+ {{this.hosComplianceBadge.label}}
71
+ </span>
72
+ </div>
73
+ </div>
67
74
  </ContentPanel>
68
75
 
69
- <ContentPanel @title="Availability & Time Off" @open={{true}} @actionButtons={{this.availabilityActionButtons}} @wrapperClass="bordered-top">
70
- {{#if this.availability.length}}
71
- <div class="space-y-2">
72
- {{#each this.availability as |avail|}}
73
- <div class="flex items-center justify-between p-2 bg-gray-50 dark:bg-gray-700 rounded">
74
- <div>
75
- <div class="font-medium">
76
- {{#if avail.is_available}}
77
- <span class="text-green-600">Available</span>
78
- {{else}}
79
- <span class="text-red-600">Unavailable</span>
80
- {{/if}}
76
+ {{! ── Time Off & Exceptions Panel ─────────────────────────────────────── }}
77
+ <ContentPanel
78
+ @title={{t "scheduler.time-off-exceptions"}}
79
+ @open={{true}}
80
+ @isLoading={{this.loadDriverSchedule.isRunning}}
81
+ @actionButtons={{this.exceptionActionButtons}}
82
+ @wrapperClass="bordered-top"
83
+ >
84
+ {{#if this.exceptions.length}}
85
+ <div class="space-y-1">
86
+ {{#each this.exceptions as |exception|}}
87
+ <div class="flex items-center justify-between p-2 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-xs dark:text-gray-100">
88
+ <div class="flex items-center space-x-3">
89
+ <div
90
+ class="w-2 h-2 rounded-full flex-shrink-0
91
+ {{if (eq exception.status 'approved') 'bg-green-500' (if (eq exception.status 'rejected') 'bg-red-500' 'bg-yellow-500')}}"
92
+ >
81
93
  </div>
82
- <div class="text-sm text-gray-500">
83
- {{format-date-fns avail.start_at "MMM DD, YYYY"}}
84
- -
85
- {{format-date-fns avail.end_at "MMM DD, YYYY"}}
94
+ <div>
95
+ <div class="font-medium">
96
+ {{exception.typeLabel}}
97
+ {{#if exception.reason}}
98
+ <span class="text-gray-400 font-normal"> — {{exception.reason}}</span>
99
+ {{/if}}
100
+ </div>
101
+ <div class="text-gray-500 dark:text-gray-400">
102
+ {{format-date-fns exception.start_at "MMM d"}}
103
+
104
+ {{format-date-fns exception.end_at "MMM d, yyyy"}}
105
+ </div>
86
106
  </div>
87
- {{#if avail.reason}}
88
- <div class="text-xs text-gray-400">{{avail.reason}}</div>
107
+ </div>
108
+ <div class="flex items-center space-x-1">
109
+ <span
110
+ class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium
111
+ {{if
112
+ (eq exception.status 'approved')
113
+ 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
114
+ (if
115
+ (eq exception.status 'rejected')
116
+ 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
117
+ 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200'
118
+ )
119
+ }}"
120
+ >
121
+ {{exception.status}}
122
+ </span>
123
+ {{#if exception.isPending}}
124
+ <Button @icon="check" @size="xs" @type="link" @scheme="success" {{on "click" (fn this.approveException exception)}} />
125
+ <Button @icon="xmark" @size="xs" @type="link" @scheme="danger" {{on "click" (fn this.rejectException exception)}} />
89
126
  {{/if}}
127
+ <Button @icon="trash" @size="xs" @type="link" @scheme="danger" {{on "click" (fn this.deleteException exception)}} />
90
128
  </div>
91
129
  </div>
92
130
  {{/each}}
93
131
  </div>
94
132
  {{else}}
95
- <div class="text-center py-4 text-gray-500 dark:text-gray-400">
96
- No availability restrictions set
133
+ <div class="text-center py-6 text-xs text-gray-500 dark:text-gray-400">
134
+ {{t "scheduler.no-exceptions"}}
97
135
  </div>
98
136
  {{/if}}
99
137
  </ContentPanel>
138
+
100
139
  </div>