@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
@@ -1,10 +1,24 @@
1
1
  import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { action } from '@ember/object';
2
5
  import { task } from 'ember-concurrency';
3
6
 
7
+ /**
8
+ * Maps a user-facing polymorphic type string to the Ember Data model name
9
+ * used by ModelSelect.
10
+ */
11
+ const TYPE_TO_MODEL = {
12
+ 'fleet-ops:vehicle': 'vehicle',
13
+ 'fleet-ops:equipment': 'equipment',
14
+ };
15
+
4
16
  export default class PartFormComponent extends Component {
5
- /**
6
- * Part type options
7
- */
17
+ @service fetch;
18
+ @service currentUser;
19
+ @service notifications;
20
+
21
+ /** Part type options. */
8
22
  partTypeOptions = [
9
23
  'filter',
10
24
  'tire',
@@ -24,21 +38,74 @@ export default class PartFormComponent extends Component {
24
38
  'other',
25
39
  ];
26
40
 
41
+ /** Status options for parts. */
42
+ statusOptions = ['in_stock', 'low_stock', 'out_of_stock', 'discontinued', 'on_order'];
43
+
27
44
  /**
28
- * Status options for parts
45
+ * Polymorphic asset type options the asset this part is compatible with.
46
+ * Each entry has a `value` (stored on the model) and a `label` (displayed in the UI).
29
47
  */
30
- statusOptions = ['in_stock', 'low_stock', 'out_of_stock', 'discontinued', 'on_order'];
48
+ assetTypeOptions = [
49
+ { value: 'fleet-ops:vehicle', label: 'Vehicle' },
50
+ { value: 'fleet-ops:equipment', label: 'Equipment' },
51
+ ];
52
+
53
+ /** Derived Ember Data model name for the currently selected asset type. */
54
+ @tracked assetModelName = null;
55
+
56
+ /** The currently selected asset type option object (drives the PowerSelect trigger label). */
57
+ @tracked selectedAssetType = null;
58
+
59
+ constructor(owner, args) {
60
+ super(owner, args);
61
+ const { resource } = args;
62
+ if (resource?.asset_type) {
63
+ this.assetModelName = TYPE_TO_MODEL[resource.asset_type] ?? null;
64
+ this.selectedAssetType = this.assetTypeOptions.find((o) => o.value === resource.asset_type) ?? null;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Handles a change to the asset type selector. Resets the asset
70
+ * relationship so a stale association is not persisted.
71
+ */
72
+ @action onAssetTypeChange(option) {
73
+ this.selectedAssetType = option;
74
+ this.args.resource.asset_type = option.value;
75
+ this.args.resource.asset_uuid = null;
76
+ this.args.resource.asset = null;
77
+ this.assetModelName = TYPE_TO_MODEL[option.value] ?? null;
78
+ }
79
+
80
+ /** Assigns the selected asset model to the resource. */
81
+ @action assignAsset(model) {
82
+ this.args.resource.asset = model;
83
+ this.args.resource.asset_uuid = model?.id ?? null;
84
+ }
31
85
 
32
86
  /**
33
- * Task to handle photo upload
87
+ * Handles photo upload using the Fleetbase fetch service upload pattern.
34
88
  */
35
89
  @task *handlePhotoUpload(file) {
36
90
  try {
37
- const response = yield file.upload(this.args.resource);
38
- this.args.resource.photo_uuid = response.uuid;
39
- this.args.resource.photo_url = response.url;
40
- } catch (error) {
41
- console.error('Photo upload failed:', error);
91
+ yield this.fetch.uploadFile.perform(
92
+ file,
93
+ {
94
+ path: `uploads/${this.currentUser.companyId}/parts/${this.args.resource.id}`,
95
+ subject_uuid: this.args.resource.id,
96
+ subject_type: 'fleet-ops:part',
97
+ type: 'part_photo',
98
+ },
99
+ (uploadedFile) => {
100
+ this.args.resource.setProperties({
101
+ photo_uuid: uploadedFile.id,
102
+ photo_url: uploadedFile.url,
103
+ photo: uploadedFile,
104
+ });
105
+ }
106
+ );
107
+ } catch (err) {
108
+ this.notifications.error('Unable to upload photo: ' + err.message);
42
109
  }
43
110
  }
44
111
  }
@@ -0,0 +1,36 @@
1
+ <div class="px-4 py-2">
2
+ <div class="flex flex-1 flex-row items-start justify-between">
3
+ <div class="flex flex-row space-x-3">
4
+ <div class="flex items-start justify-start rounded-full">
5
+ <Image
6
+ src={{@resource.photo_url}}
7
+ @fallbackSrc={{config "defaultValues.placeholderImage"}}
8
+ alt={{@resource.name}}
9
+ height="48"
10
+ width="48"
11
+ class="h-14 w-14 rounded-full shadow-sm"
12
+ />
13
+ </div>
14
+ <div class="flex flex-col">
15
+ <div class="flex flex-row items-center space-x-2">
16
+ <h1 class="text-gray-900 dark:text-white font-semibold text-lg">{{@resource.name}}</h1>
17
+ <Badge @status={{@resource.status}}>{{smart-humanize @resource.status}}</Badge>
18
+ </div>
19
+ <div class="text-xs text-gray-400 dark:text-gray-500">{{smart-humanize @resource.type}}</div>
20
+ <div class="text-xs text-gray-400 dark:text-gray-500">{{n-a @resource.part_number}}</div>
21
+ </div>
22
+ </div>
23
+ <div class="next-view-header-right">
24
+ <Layout::Resource::Panel::HeaderActions
25
+ @resource={{@resource}}
26
+ @saveTask={{@saveTask}}
27
+ @saveOptions={{@saveOptions}}
28
+ @saveDisabled={{@saveDisabled}}
29
+ @pojoResource={{@pojoResource}}
30
+ @authSchema={{@authSchema}}
31
+ @actionButtons={{@actionButtons}}
32
+ @onPressCancel={{@onPressCancel}}
33
+ />
34
+ </div>
35
+ </div>
36
+ </div>
@@ -0,0 +1,2 @@
1
+ import Component from '@glimmer/component';
2
+ export default class PartPanelHeaderComponent extends Component {}
@@ -17,13 +17,7 @@
17
17
  {{result.address}}
18
18
  </AutocompleteInput>
19
19
  </InputGroup>
20
- <InputGroup
21
- @name={{t "place.fields.street-2"}}
22
- @autocomplete="nope"
23
- @value={{@resource.street2}}
24
- @wrapperClass="col-span-3"
25
- @disabled={{cannot-write @resource}}
26
- />
20
+ <InputGroup @name={{t "place.fields.street-2"}} @autocomplete="nope" @value={{@resource.street2}} @wrapperClass="col-span-3" @disabled={{cannot-write @resource}} />
27
21
  <InputGroup @name={{t "place.fields.neighborhood"}} @autocomplete="nope" @value={{@resource.neighborhood}} @disabled={{cannot-write @resource}} />
28
22
  <InputGroup @name={{t "place.fields.building"}} @autocomplete="nope" @value={{@resource.building}} @disabled={{cannot-write @resource}} />
29
23
  <InputGroup @name={{t "place.fields.security-access-code"}} @autocomplete="nope" @value={{@resource.security_access_code}} @disabled={{cannot-write @resource}} />
@@ -1,7 +1,7 @@
1
1
  <div class="details-wrapper" ...attributes>
2
2
  <ContentPanel @title="Identity" @open={{true}} @wrapperClass="bordered-top">
3
3
  <div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
4
- <div class="field-info-container ">
4
+ <div class="field-info-container">
5
5
  <div class="field-name">Name</div>
6
6
  <div class="field-value">{{n-a @resource.name}}</div>
7
7
  </div>
@@ -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">
@@ -64,7 +64,7 @@
64
64
  <InputGroup @name="Serial Number" @value={{@resource.serial_number}} @wrapperClass="col-span-2" disabled={{cannot-write @resource}} />
65
65
  <InputGroup @name="Internal ID" @value={{@resource.internal_id}} disabled={{cannot-write @resource}} />
66
66
  <InputGroup @name="Unit" @value={{@resource.unit}} disabled={{cannot-write @resource}} />
67
- <InputGroup @name="Type" @wrapperClass="col-span-2">
67
+ <InputGroup @name="Type" @wrapperClass="col-span-2">
68
68
  <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
69
69
  <PowerSelect
70
70
  @options={{get-fleet-ops-options "sensorTypes"}}
@@ -149,7 +149,9 @@
149
149
  @disabled={{cannot-write @resource}}
150
150
  as |model|
151
151
  >
152
- {{model.policy_number}} - {{model.provider}}
152
+ {{model.policy_number}}
153
+ -
154
+ {{model.provider}}
153
155
  </ModelSelect>
154
156
  </InputGroup>
155
157
  </div>
@@ -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>
@@ -1,12 +1,7 @@
1
1
  <div class="form-wrapper" ...attributes>
2
2
  <ContentPanel @title={{t "service-area.fields.details"}} @open={{true}} @wrapperClass="bordered-top">
3
3
  <div class="space-y-2">
4
- <InputGroup
5
- @value={{@resource.name}}
6
- @name={{t "modals.service-area-form.name"}}
7
- @helpText={{t "modals.service-area-form.name-text"}}
8
- @required={{true}}
9
- />
4
+ <InputGroup @value={{@resource.name}} @name={{t "modals.service-area-form.name"}} @helpText={{t "modals.service-area-form.name-text"}} @required={{true}} />
10
5
  <InputGroup @name={{t "modals.service-area-form.type"}} @helpText={{t "modals.service-area-form.type-text"}}>
11
6
  <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
12
7
  <PowerSelect
@@ -29,11 +29,7 @@
29
29
  </div>
30
30
  </InputGroup>
31
31
 
32
- <InputGroup
33
- @name={{t "service-rate.fields.base-fee-label"}}
34
- @helpText={{t "service-rate.fields.base-fee-help-text"}}
35
- @required={{true}}
36
- >
32
+ <InputGroup @name={{t "service-rate.fields.base-fee-label"}} @helpText={{t "service-rate.fields.base-fee-help-text"}} @required={{true}}>
37
33
  <MoneyInput
38
34
  class="w-full"
39
35
  @value={{@resource.base_fee}}
@@ -44,11 +40,7 @@
44
40
  />
45
41
  </InputGroup>
46
42
 
47
- <InputGroup
48
- @name={{t "service-rate.fields.rate-calculation-label"}}
49
- @helpText={{t "service-rate.fields.rate-calculation-help-text"}}
50
- @required={{true}}
51
- >
43
+ <InputGroup @name={{t "service-rate.fields.rate-calculation-label"}} @helpText={{t "service-rate.fields.rate-calculation-help-text"}} @required={{true}}>
52
44
  <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
53
45
  <PowerSelect
54
46
  @options={{get-fleet-ops-options "serviceRateCalculationMethods"}}
@@ -97,11 +89,7 @@
97
89
  {{#if @resource.isFixedRate}}
98
90
  <ContentPanel @title={{t "service-rate.fields.fixed-meter"}} @open={{true}} @wrapperClass="bordered-top" @panelBodyWrapperClass="px-0i">
99
91
  <div class="px-2 mb-3">
100
- <InfoBlock
101
- class="mb-2"
102
- @text={{t "service-rate.fields.fixed-meter-text"}}
103
- @exampleText={{t "service-rate.fields.fixed-meter-example-text"}}
104
- />
92
+ <InfoBlock class="mb-2" @text={{t "service-rate.fields.fixed-meter-text"}} @exampleText={{t "service-rate.fields.fixed-meter-example-text"}} />
105
93
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-2">
106
94
  <InputGroup
107
95
  @name={{t "service-rate.fields.maximum-distance"}}
@@ -163,11 +151,7 @@
163
151
  {{else if @resource.isPerDrop}}
164
152
  <ContentPanel @title={{t "service-rate.fields.per-drop-off-title"}} @open={{true}} @wrapperClass="bordered-top" @panelBodyWrapperClass="px-0i">
165
153
  <div class="px-2 mb-3">
166
- <InfoBlock
167
- class="mb-3"
168
- @text={{t "service-rate.fields.per-drop-off-text"}}
169
- @exampleText={{t "service-rate.fields.per-drop-off-example-text"}}
170
- />
154
+ <InfoBlock class="mb-3" @text={{t "service-rate.fields.per-drop-off-text"}} @exampleText={{t "service-rate.fields.per-drop-off-example-text"}} />
171
155
 
172
156
  <div>
173
157
  <Button
@@ -227,26 +211,14 @@
227
211
  </ContentPanel>
228
212
  {{else if @resource.isPerMeter}}
229
213
  <ContentPanel @title={{t "service-rate.fields.per-meter"}} @open={{true}} @wrapperClass="bordered-top">
230
- <InfoBlock
231
- class="mb-5"
232
- @text={{t "service-rate.fields.per-meter-text"}}
233
- @exampleText={{t "service-rate.fields.per-meter-example-text"}}
234
- />
214
+ <InfoBlock class="mb-5" @text={{t "service-rate.fields.per-meter-text"}} @exampleText={{t "service-rate.fields.per-meter-example-text"}} />
235
215
 
236
216
  <div class="grid grid-cols-2 gap-2">
237
- <InputGroup
238
- @name={{t "service-rate.fields.per-meter-rate-fee"}}
239
- @helpText={{t "service-rate.fields.per-meter-rate-fee-help-text"}}
240
- @required={{true}}
241
- >
217
+ <InputGroup @name={{t "service-rate.fields.per-meter-rate-fee"}} @helpText={{t "service-rate.fields.per-meter-rate-fee-help-text"}} @required={{true}}>
242
218
  <MoneyInput class="w-full" @currency={{@resource.currency}} @value={{@resource.per_meter_flat_rate_fee}} disabled={{cannot-write @resource}} />
243
219
  </InputGroup>
244
220
 
245
- <InputGroup
246
- @name={{t "service-rate.fields.distance-unit"}}
247
- @helpText={{t "service-rate.fields.distance-unit-help-text"}}
248
- @required={{true}}
249
- >
221
+ <InputGroup @name={{t "service-rate.fields.distance-unit"}} @helpText={{t "service-rate.fields.distance-unit-help-text"}} @required={{true}}>
250
222
  <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
251
223
  <PowerSelect
252
224
  @options={{get-fleet-ops-options "distanceUnits"}}
@@ -302,11 +274,7 @@
302
274
  </div>
303
275
  </InfoBlock>
304
276
 
305
- <InputGroup
306
- @name={{t "service-rate.fields.algorithm-label"}}
307
- @helpText={{t "service-rate.fields.algorithm-help-text"}}
308
- @required={{true}}
309
- >
277
+ <InputGroup @name={{t "service-rate.fields.algorithm-label"}} @helpText={{t "service-rate.fields.algorithm-help-text"}} @required={{true}}>
310
278
  <Textarea
311
279
  @value={{@resource.algorithm}}
312
280
  placeholder={{t "service-rate.fields.algorithm-placeholder"}}
@@ -425,11 +393,7 @@
425
393
 
426
394
  {{#if @resource.has_cod_fee}}
427
395
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-2 mt-2">
428
- <InputGroup
429
- @name={{t "service-rate.fields.calculation-method-label"}}
430
- @helpText={{t "service-rate.fields.calculation-method-help-text"}}
431
- @required={{true}}
432
- >
396
+ <InputGroup @name={{t "service-rate.fields.calculation-method-label"}} @helpText={{t "service-rate.fields.calculation-method-help-text"}} @required={{true}}>
433
397
  <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
434
398
  <PowerSelect
435
399
  @options={{get-fleet-ops-options "serviceRateCodCalculationMethods"}}
@@ -449,11 +413,7 @@
449
413
  </InputGroup>
450
414
 
451
415
  {{#if @resource.hasCodFlatFee}}
452
- <InputGroup
453
- @name={{t "service-rate.fields.delivery-flat-fee"}}
454
- @helpText={{t "service-rate.fields.delivery-flat-fee-help-text"}}
455
- @required={{true}}
456
- >
416
+ <InputGroup @name={{t "service-rate.fields.delivery-flat-fee"}} @helpText={{t "service-rate.fields.delivery-flat-fee-help-text"}} @required={{true}}>
457
417
  <MoneyInput class="w-full" @currency={{@resource.currency}} @value={{@resource.cod_flat_fee}} disabled={{cannot-write @resource}} />
458
418
  </InputGroup>
459
419
  {{else if @resource.hasCodPercentageFee}}
@@ -501,11 +461,7 @@
501
461
  @required={{true}}
502
462
  />
503
463
 
504
- <InputGroup
505
- @name={{t "service-rate.fields.peak-hours-fee-label"}}
506
- @helpText={{t "service-rate.fields.peak-hours-fee-help-text"}}
507
- @required={{true}}
508
- >
464
+ <InputGroup @name={{t "service-rate.fields.peak-hours-fee-label"}} @helpText={{t "service-rate.fields.peak-hours-fee-help-text"}} @required={{true}}>
509
465
  <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
510
466
  <PowerSelect
511
467
  @options={{get-fleet-ops-options "serviceRatePeakHourCalculationMethods"}}
@@ -525,11 +481,7 @@
525
481
  </InputGroup>
526
482
 
527
483
  {{#if @resource.hasPeakHoursFlatFee}}
528
- <InputGroup
529
- @name={{t "service-rate.fields.flat-fee-label"}}
530
- @helpText={{t "service-rate.fields.flat-fee-help-text"}}
531
- @required={{true}}
532
- >
484
+ <InputGroup @name={{t "service-rate.fields.flat-fee-label"}} @helpText={{t "service-rate.fields.flat-fee-help-text"}} @required={{true}}>
533
485
  <MoneyInput class="w-full" @currency={{@resource.currency}} @value={{@resource.peak_hours_flat_fee}} disabled={{cannot-write @resource}} />
534
486
  </InputGroup>
535
487
  {{else if @resource.hasPeakHoursPercentageFee}}
@@ -14,7 +14,7 @@
14
14
  >
15
15
  <div class="space-x-2 text-sm">
16
16
  <div class="inline-block align-top">
17
- <div class="hide-from-trigger h-1.5 w-full" />
17
+ <div class="hide-from-trigger h-1.5 w-full"></div>
18
18
  <Image src={{provider.icon}} class="w-5 h-5" />
19
19
  </div>
20
20
  <div class="inline-block">
@@ -49,7 +49,11 @@
49
49
  <InputGroup @value={{@resource.name}} @name="Integration Name" />
50
50
 
51
51
  {{#if this.selectedProvider.supports_webhooks}}
52
- <InputGroup @name="Webhook URL" @helpText={{concat "Configure the URL in your " this.selectedProvider.label " dashboard to receive real-time updates."}} @wrapperClass="col-span-2">
52
+ <InputGroup
53
+ @name="Webhook URL"
54
+ @helpText={{concat "Configure the URL in your " this.selectedProvider.label " dashboard to receive real-time updates."}}
55
+ @wrapperClass="col-span-2"
56
+ >
53
57
  <ClickToCopy @value={{this.selectedProvider.webhook_url}} class="w-full">
54
58
  <Input @value={{this.selectedProvider.webhook_url}} class="form-input w-full" readonly />
55
59
  </ClickToCopy>
@@ -0,0 +1,42 @@
1
+ <div class="vehicle-details-maintenance-history p-4">
2
+ {{#if this.maintenanceHistory.isRunning}}
3
+ <div class="flex items-center justify-center py-10">
4
+ <Spinner />
5
+ </div>
6
+ {{else}}
7
+ {{#if this.maintenanceHistory.length}}
8
+ <table class="min-w-full text-xs">
9
+ <thead>
10
+ <tr class="border-b border-gray-200 dark:border-gray-700">
11
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Summary</th>
12
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Type</th>
13
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Odometer</th>
14
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Total Cost</th>
15
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Date</th>
16
+ <th class="py-2"></th>
17
+ </tr>
18
+ </thead>
19
+ <tbody>
20
+ {{#each this.maintenanceHistory as |record|}}
21
+ <tr class="border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-800">
22
+ <td class="py-2 pr-4 font-medium">{{record.summary}}</td>
23
+ <td class="py-2 pr-4 text-gray-500">{{humanize record.type}}</td>
24
+ <td class="py-2 pr-4 text-gray-500">{{n-a record.odometer_reading}} {{record.odometer_unit}}</td>
25
+ <td class="py-2 pr-4">{{format-currency record.total_cost record.currency}}</td>
26
+ <td class="py-2 pr-4 text-gray-500">{{n-a (format-date-fns record.completed_at "dd MMM yyyy")}}</td>
27
+ <td class="py-2">
28
+ <Button @icon="eye" @size="xs" @onClick={{fn this.maintenanceActions.transition.view record}} />
29
+ </td>
30
+ </tr>
31
+ {{/each}}
32
+ </tbody>
33
+ </table>
34
+ {{else}}
35
+ <div class="flex flex-col items-center justify-center py-10 text-gray-400 dark:text-gray-600">
36
+ <FaIcon @icon="history" @size="2x" class="mb-3" />
37
+ <p class="text-sm">No maintenance history for this vehicle.</p>
38
+ <Button @text="Log Maintenance" @icon="plus" @size="xs" @type="primary" class="mt-3" @onClick={{fn this.maintenanceActions.modal.create (hash maintainable=@vehicle)}} />
39
+ </div>
40
+ {{/if}}
41
+ {{/if}}
42
+ </div>
@@ -0,0 +1,32 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { task } from 'ember-concurrency';
5
+
6
+ export default class VehicleDetailsMaintenanceHistoryComponent extends Component {
7
+ @service maintenanceActions;
8
+ @service notifications;
9
+ @service store;
10
+ @tracked maintenanceHistory = [];
11
+
12
+ get resourceId() {
13
+ return this.args.resource.id ?? this.args.vehicle.id;
14
+ }
15
+
16
+ constructor() {
17
+ super(...arguments);
18
+ this.loadMaintenanceHistory.perform();
19
+ }
20
+
21
+ @task *loadMaintenanceHistory() {
22
+ try {
23
+ this.maintenanceHistory = yield this.store.query('maintenance', {
24
+ maintainable_uuid: this.resourceId,
25
+ maintainable_type: 'vehicle',
26
+ sort: '-created_at',
27
+ });
28
+ } catch (err) {
29
+ this.notifications.serverError(err);
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,40 @@
1
+ <div class="vehicle-details-schedules p-4">
2
+ {{#if this.schedules.isRunning}}
3
+ <div class="flex items-center justify-center py-10">
4
+ <Spinner />
5
+ </div>
6
+ {{else}}
7
+ {{#if this.schedules.length}}
8
+ <table class="min-w-full text-xs">
9
+ <thead>
10
+ <tr class="border-b border-gray-200 dark:border-gray-700">
11
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Name</th>
12
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Interval</th>
13
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Next Due</th>
14
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Status</th>
15
+ <th class="py-2"></th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ {{#each this.schedules as |schedule|}}
20
+ <tr class="border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-800">
21
+ <td class="py-2 pr-4 font-medium">{{schedule.name}}</td>
22
+ <td class="py-2 pr-4 text-gray-500">{{schedule.interval_value}} {{schedule.interval_unit}}</td>
23
+ <td class="py-2 pr-4 text-gray-500">{{n-a (format-date-fns schedule.next_due_date "dd MMM yyyy")}}</td>
24
+ <td class="py-2 pr-4"><StatusBadge @status={{schedule.status}} /></td>
25
+ <td class="py-2">
26
+ <Button @icon="eye" @size="xs" @onClick={{fn this.maintenanceScheduleActions.transition.view schedule}} />
27
+ </td>
28
+ </tr>
29
+ {{/each}}
30
+ </tbody>
31
+ </table>
32
+ {{else}}
33
+ <div class="flex flex-col items-center justify-center py-10 text-gray-400 dark:text-gray-600">
34
+ <FaIcon @icon="calendar-alt" @size="2x" class="mb-3" />
35
+ <p class="text-sm">No maintenance schedules for this vehicle.</p>
36
+ <Button @text="Add Schedule" @icon="plus" @size="xs" @type="primary" class="mt-3" @onClick={{fn this.maintenanceScheduleActions.modal.create (hash subject=@vehicle)}} />
37
+ </div>
38
+ {{/if}}
39
+ {{/if}}
40
+ </div>
@@ -0,0 +1,32 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { task } from 'ember-concurrency';
5
+
6
+ export default class VehicleDetailsSchedulesComponent extends Component {
7
+ @service maintenanceScheduleActions;
8
+ @service notifications;
9
+ @service store;
10
+ @tracked schedules = [];
11
+
12
+ get resourceId() {
13
+ return this.args.resource.id ?? this.args.vehicle.id;
14
+ }
15
+
16
+ constructor() {
17
+ super(...arguments);
18
+ this.loadSchedules.perform();
19
+ }
20
+
21
+ @task *loadSchedules() {
22
+ try {
23
+ this.schedules = yield this.store.query('maintenance-schedule', {
24
+ subject_uuid: this.resourceId,
25
+ subject_type: 'vehicle',
26
+ sort: '-created_at',
27
+ });
28
+ } catch (err) {
29
+ this.notifications.serverError(err);
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,42 @@
1
+ <div class="vehicle-details-work-orders p-4">
2
+ {{#if this.loadWorkOrders.isRunning}}
3
+ <div class="flex items-center justify-center py-10">
4
+ <Spinner />
5
+ </div>
6
+ {{else}}
7
+ {{#if this.workOrders.length}}
8
+ <table class="min-w-full text-xs">
9
+ <thead>
10
+ <tr class="border-b border-gray-200 dark:border-gray-700">
11
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Code</th>
12
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Subject</th>
13
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Priority</th>
14
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Status</th>
15
+ <th class="text-left py-2 pr-4 font-semibold text-gray-500 uppercase tracking-wide">Due</th>
16
+ <th class="py-2"></th>
17
+ </tr>
18
+ </thead>
19
+ <tbody>
20
+ {{#each this.workOrders as |workOrder|}}
21
+ <tr class="border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-800">
22
+ <td class="py-2 pr-4 font-mono uppercase">{{workOrder.code}}</td>
23
+ <td class="py-2 pr-4 font-medium">{{workOrder.subject}}</td>
24
+ <td class="py-2 pr-4 text-gray-500">{{humanize workOrder.priority}}</td>
25
+ <td class="py-2 pr-4"><StatusBadge @status={{workOrder.status}} /></td>
26
+ <td class="py-2 pr-4 text-gray-500">{{n-a (format-date-fns workOrder.due_at "dd MMM yyyy")}}</td>
27
+ <td class="py-2">
28
+ <Button @icon="eye" @size="xs" @onClick={{fn this.workOrderActions.transition.view workOrder}} />
29
+ </td>
30
+ </tr>
31
+ {{/each}}
32
+ </tbody>
33
+ </table>
34
+ {{else}}
35
+ <div class="flex flex-col items-center justify-center py-10 text-gray-400 dark:text-gray-600">
36
+ <FaIcon @icon="clipboard-list" @size="2x" class="mb-3" />
37
+ <p class="text-sm">No work orders for this vehicle.</p>
38
+ <Button @text="Create Work Order" @icon="plus" @size="xs" @type="primary" class="mt-3" @onClick={{fn this.workOrderActions.modal.create (hash target=@vehicle)}} />
39
+ </div>
40
+ {{/if}}
41
+ {{/if}}
42
+ </div>
@@ -0,0 +1,32 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { task } from 'ember-concurrency';
5
+
6
+ export default class VehicleDetailsWorkOrdersComponent extends Component {
7
+ @service workOrderActions;
8
+ @service notifications;
9
+ @service store;
10
+ @tracked workOrders = [];
11
+
12
+ get resourceId() {
13
+ return this.args.resource.id ?? this.args.vehicle.id;
14
+ }
15
+
16
+ constructor() {
17
+ super(...arguments);
18
+ this.loadWorkOrders.perform();
19
+ }
20
+
21
+ @task *loadWorkOrders() {
22
+ try {
23
+ this.workOrders = yield this.store.query('work-order', {
24
+ target_uuid: this.resourceId,
25
+ target_type: 'vehicle',
26
+ sort: '-created_at',
27
+ });
28
+ } catch (err) {
29
+ this.notifications.serverError(err);
30
+ }
31
+ }
32
+ }