@fleetbase/fleetops-engine 0.6.49 → 0.6.51

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 (271) hide show
  1. package/README.md +185 -67
  2. package/addon/components/contact/panel-header.hbs +11 -48
  3. package/addon/components/customer/create-order-form.hbs +2 -2
  4. package/addon/components/customer/details.hbs +1 -2
  5. package/addon/components/customer/form.hbs +62 -50
  6. package/addon/components/customer/form.js +27 -1
  7. package/addon/components/customer/order-form.hbs +2 -2
  8. package/addon/components/customer/orders.hbs +50 -2
  9. package/addon/components/customer/orders.js +67 -5
  10. package/addon/components/display-place.hbs +2 -2
  11. package/addon/components/driver/form.hbs +1 -1
  12. package/addon/components/home/getting-started-guidance.hbs +113 -0
  13. package/addon/components/home/getting-started-guidance.js +107 -0
  14. package/addon/components/issue/details/comments.hbs +3 -0
  15. package/addon/components/issue/details/comments.js +3 -0
  16. package/addon/components/issue/details/correspondence.hbs +9 -0
  17. package/addon/components/issue/details/correspondence.js +83 -0
  18. package/addon/components/issue/details/documents.hbs +69 -0
  19. package/addon/components/issue/details/documents.js +85 -0
  20. package/addon/components/issue/details.hbs +220 -59
  21. package/addon/components/issue/details.js +245 -0
  22. package/addon/components/issue/form.hbs +19 -1
  23. package/addon/components/issue/panel-header.hbs +43 -0
  24. package/addon/components/issue/panel-header.js +22 -0
  25. package/addon/components/issue/timeline.hbs +40 -0
  26. package/addon/components/issue/timeline.js +45 -0
  27. package/addon/components/leaflet-tracking-marker.js +3 -0
  28. package/addon/components/map/drawer/position-listing.js +3 -0
  29. package/addon/components/map/google-live-map.js +6 -2
  30. package/addon/components/map/leaflet-live-map.hbs +48 -14
  31. package/addon/components/map/leaflet-live-map.js +201 -20
  32. package/addon/components/map/order-list-overlay.hbs +4 -4
  33. package/addon/components/modals/convert-customer-to-vendor.hbs +30 -0
  34. package/addon/components/modals/convert-customer-to-vendor.js +55 -0
  35. package/addon/components/modals/issue-assign.hbs +20 -0
  36. package/addon/components/modals/issue-assign.js +49 -0
  37. package/addon/components/modals/issue-close.hbs +30 -0
  38. package/addon/components/modals/issue-close.js +73 -0
  39. package/addon/components/modals/issue-status.hbs +20 -0
  40. package/addon/components/modals/issue-status.js +43 -0
  41. package/addon/components/modals/order-change-destination.hbs +46 -0
  42. package/addon/components/modals/order-change-destination.js +106 -0
  43. package/addon/components/modals/reset-customer-credentials.js +12 -6
  44. package/addon/components/modals/stop-activity.hbs +28 -0
  45. package/addon/components/modals/stop-activity.js +52 -0
  46. package/addon/components/modals/update-order-activity.hbs +78 -2
  47. package/addon/components/modals/update-order-activity.js +197 -5
  48. package/addon/components/orchestrator/resource-panel.hbs +0 -10
  49. package/addon/components/orchestrator/resource-panel.js +2 -4
  50. package/addon/components/order/activity-list.hbs +2 -2
  51. package/addon/components/order/activity-timeline.hbs +31 -29
  52. package/addon/components/order/details/activity.hbs +3 -3
  53. package/addon/components/order/details/activity.js +13 -2
  54. package/addon/components/order/details/documents.js +2 -0
  55. package/addon/components/order/details/proof.hbs +40 -38
  56. package/addon/components/order/details/proof.js +31 -4
  57. package/addon/components/order/details/purchase-rate.hbs +2 -2
  58. package/addon/components/order/details/route.hbs +11 -3
  59. package/addon/components/order/details/route.js +91 -14
  60. package/addon/components/order/details/tracking.hbs +101 -72
  61. package/addon/components/order/details/tracking.js +149 -2
  62. package/addon/components/order/details.hbs +5 -5
  63. package/addon/components/order/details.js +19 -1
  64. package/addon/components/order/form/details.hbs +3 -3
  65. package/addon/components/order/form/documents.js +11 -4
  66. package/addon/components/order/form/route.hbs +108 -104
  67. package/addon/components/order/form/route.js +37 -1
  68. package/addon/components/order/form/service-rate.hbs +2 -2
  69. package/addon/components/order/header.hbs +1 -1
  70. package/addon/components/order-config-manager/activity-flow.hbs +4 -1
  71. package/addon/components/order-config-manager/activity-flow.js +178 -12
  72. package/addon/components/place/address.js +1 -1
  73. package/addon/components/route-list.hbs +17 -29
  74. package/addon/components/route-list.js +42 -10
  75. package/addon/components/service-rate/details.hbs +42 -1
  76. package/addon/components/service-rate/form.hbs +119 -1
  77. package/addon/components/service-rate/form.js +59 -0
  78. package/addon/components/vehicle/form.js +1 -1
  79. package/addon/components/vehicle/pill.hbs +1 -1
  80. package/addon/components/vendor/personnel-manager.hbs +166 -0
  81. package/addon/components/vendor/personnel-manager.js +143 -0
  82. package/addon/components/widget/live-fleet.hbs +1 -0
  83. package/addon/components/widget/live-fleet.js +2 -7
  84. package/addon/components/widget/revenue-trend.hbs +1 -1
  85. package/addon/components/widget/revenue-trend.js +75 -2
  86. package/addon/controllers/management/contacts/customers/details.js +31 -13
  87. package/addon/controllers/management/contacts/customers.js +16 -5
  88. package/addon/controllers/management/contacts/index/details.js +31 -13
  89. package/addon/controllers/management/contacts/index.js +7 -0
  90. package/addon/controllers/management/issues/index/details.js +52 -6
  91. package/addon/controllers/management/vehicles/index/new.js +1 -1
  92. package/addon/controllers/management/vendors/index/details.js +4 -0
  93. package/addon/controllers/operations/orders/index/details.js +15 -7
  94. package/addon/controllers/operations/orders/index.js +15 -1
  95. package/addon/extension.js +19 -12
  96. package/addon/helpers/format-duration.js +1 -38
  97. package/addon/helpers/place-address-html.js +2 -2
  98. package/addon/initializers/load-leaflet-assets.js +5 -6
  99. package/addon/initializers/patch-ember-leaflet-tooltip-layer.js +51 -0
  100. package/addon/routes/management/issues/index/details.js +1 -1
  101. package/addon/routes/operations/service-rates/index.js +1 -1
  102. package/addon/routes.js +1 -0
  103. package/addon/services/contact-actions.js +231 -1
  104. package/addon/services/geofence.js +163 -19
  105. package/addon/services/getting-started.js +44 -0
  106. package/addon/services/issue-actions.js +71 -0
  107. package/addon/services/leaflet-contextmenu-manager.js +27 -0
  108. package/addon/services/leaflet-map-manager.js +2 -0
  109. package/addon/services/map-adapter/leaflet.js +19 -0
  110. package/addon/services/service-areas.js +3 -0
  111. package/addon/services/vehicle-actions.js +1 -1
  112. package/addon/styles/fleetops-engine.css +1127 -1
  113. package/addon/templates/management/contacts/customers/details.hbs +1 -1
  114. package/addon/templates/management/contacts/index/details.hbs +1 -1
  115. package/addon/templates/management/contacts.hbs +2 -2
  116. package/addon/templates/management/issues/index/details/index.hbs +3 -1
  117. package/addon/templates/management/issues/index/details.hbs +3 -2
  118. package/addon/templates/management/vendors/index/details/personnel.hbs +1 -2
  119. package/addon/templates/operations/orders/index/details/index.hbs +2 -2
  120. package/addon/templates/operations/orders/index.hbs +1 -1
  121. package/addon/templates/operations/service-rates/index/edit.hbs +1 -0
  122. package/addon/templates/operations/service-rates/index/new.hbs +1 -0
  123. package/addon/templates/settings/payments/onboard.hbs +8 -8
  124. package/addon/utils/fleet-ops-options.js +2 -1
  125. package/addon/utils/leaflet-draw-namespace-guard.js +22 -0
  126. package/addon/utils/leaflet-plugin-loader.js +219 -0
  127. package/addon/utils/normalize-order-config-flow.js +41 -0
  128. package/addon/utils/place-address-html.js +3 -2
  129. package/addon/utils/route-visualization.js +54 -7
  130. package/addon/utils/setup-customer-portal.js +4 -64
  131. package/app/components/home/getting-started-guidance.js +1 -0
  132. package/app/components/issue/details/comments.js +1 -0
  133. package/app/components/issue/details/correspondence.js +1 -0
  134. package/app/components/issue/details/documents.js +1 -0
  135. package/app/components/issue/panel-header.js +1 -0
  136. package/app/components/modals/convert-customer-to-vendor.js +1 -0
  137. package/app/components/modals/issue-assign.js +1 -0
  138. package/app/components/modals/issue-close.js +1 -0
  139. package/app/components/modals/issue-status.js +1 -0
  140. package/app/components/modals/order-change-destination.js +1 -0
  141. package/app/components/modals/stop-activity.js +1 -0
  142. package/app/components/vendor/personnel-manager.js +1 -0
  143. package/app/helpers/format-duration.js +1 -1
  144. package/app/services/getting-started.js +1 -0
  145. package/app/utils/leaflet-draw-namespace-guard.js +1 -0
  146. package/app/utils/leaflet-plugin-loader.js +1 -0
  147. package/composer.json +1 -1
  148. package/extension.json +1 -1
  149. package/package.json +5 -5
  150. package/server/migrations/2026_05_21_000001_add_geographic_rules_to_service_rate_fees_table.php +37 -0
  151. package/server/migrations/2026_05_25_000001_add_endpoint_tracking_refs_to_payloads_table.php +50 -0
  152. package/server/migrations/2026_05_27_000001_default_driver_vehicle_statuses_to_available.php +48 -0
  153. package/server/migrations/2026_05_31_000001_add_portal_fields_to_vendor_personnels_table.php +30 -0
  154. package/server/migrations/2026_06_03_000000_ensure_tags_column_on_issues_table.php +31 -0
  155. package/server/migrations/2026_06_03_000001_add_order_uuid_to_issues_table.php +25 -0
  156. package/server/migrations/2026_06_04_000001_backfill_order_transaction_subjects.php +39 -0
  157. package/server/migrations/2026_06_04_000002_backfill_order_transaction_directions.php +24 -0
  158. package/server/resources/views/labels/default.php +57 -49
  159. package/server/resources/views/labels/waypoint-label.php +27 -20
  160. package/server/resources/views/mail/customer-credentials.blade.php +16 -13
  161. package/server/seeders/Testing/ConnectivitySeeder.php +1 -0
  162. package/server/seeders/Testing/FleetSeeder.php +22 -22
  163. package/server/seeders/Testing/OrdersSeeder.php +6 -22
  164. package/server/seeders/Testing/VroomOrchestrationSeeder.php +21 -21
  165. package/server/src/Console/Commands/AuditCustomerUserConflicts.php +75 -0
  166. package/server/src/Exceptions/CustomerUserConflictException.php +13 -0
  167. package/server/src/Expansions/UserFilterExpansion.php +28 -0
  168. package/server/src/Http/Controllers/Api/v1/ContactController.php +17 -2
  169. package/server/src/Http/Controllers/Api/v1/CustomerController.php +876 -0
  170. package/server/src/Http/Controllers/Api/v1/DriverController.php +1 -1
  171. package/server/src/Http/Controllers/Api/v1/IssueController.php +2 -0
  172. package/server/src/Http/Controllers/Api/v1/OrderConfigController.php +54 -0
  173. package/server/src/Http/Controllers/Api/v1/OrderController.php +109 -80
  174. package/server/src/Http/Controllers/Api/v1/PlaceController.php +10 -58
  175. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -2
  176. package/server/src/Http/Controllers/Api/v1/VehicleController.php +20 -3
  177. package/server/src/Http/Controllers/Internal/v1/ContactController.php +154 -0
  178. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +116 -6
  179. package/server/src/Http/Controllers/Internal/v1/GettingStartedController.php +17 -0
  180. package/server/src/Http/Controllers/Internal/v1/IssueController.php +251 -0
  181. package/server/src/Http/Controllers/Internal/v1/LiveController.php +101 -66
  182. package/server/src/Http/Controllers/Internal/v1/OrderController.php +530 -52
  183. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +10 -68
  184. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +1 -1
  185. package/server/src/Http/Controllers/Internal/v1/SettingController.php +2 -2
  186. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +54 -1
  187. package/server/src/Http/Controllers/Internal/v1/VendorController.php +89 -0
  188. package/server/src/Http/Middleware/AuthenticateCustomerToken.php +34 -0
  189. package/server/src/Http/Requests/CreateCustomerOrderRequest.php +63 -0
  190. package/server/src/Http/Requests/CreateCustomerRequest.php +48 -0
  191. package/server/src/Http/Requests/CreateDriverRequest.php +1 -1
  192. package/server/src/Http/Requests/CreateIssueRequest.php +4 -0
  193. package/server/src/Http/Requests/CreateVehicleRequest.php +25 -1
  194. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -1
  195. package/server/src/Http/Requests/UpdateIssueRequest.php +4 -0
  196. package/server/src/Http/Requests/VerifyCreateCustomerRequest.php +29 -0
  197. package/server/src/Http/Resources/Internal/v1/OrderConfig.php +41 -0
  198. package/server/src/Http/Resources/v1/Customer.php +79 -0
  199. package/server/src/Http/Resources/v1/Index/Order.php +12 -9
  200. package/server/src/Http/Resources/v1/Issue.php +25 -0
  201. package/server/src/Http/Resources/v1/Order.php +20 -18
  202. package/server/src/Http/Resources/v1/OrderConfig.php +74 -0
  203. package/server/src/Http/Resources/v1/Payload.php +23 -20
  204. package/server/src/Http/Resources/v1/ServiceArea.php +33 -19
  205. package/server/src/Http/Resources/v1/ServiceRateFee.php +7 -0
  206. package/server/src/Listeners/HandleOrderDispatched.php +2 -2
  207. package/server/src/Mail/CustomerCredentialsMail.php +5 -6
  208. package/server/src/Models/Contact.php +122 -66
  209. package/server/src/Models/Customer.php +64 -0
  210. package/server/src/Models/Driver.php +12 -3
  211. package/server/src/Models/Entity.php +2 -2
  212. package/server/src/Models/Issue.php +47 -6
  213. package/server/src/Models/Order.php +62 -10
  214. package/server/src/Models/Payload.php +17 -1
  215. package/server/src/Models/ServiceArea.php +1 -1
  216. package/server/src/Models/ServiceRate.php +273 -1
  217. package/server/src/Models/ServiceRateFee.php +39 -9
  218. package/server/src/Models/TrackingNumber.php +8 -2
  219. package/server/src/Models/Vehicle.php +18 -2
  220. package/server/src/Models/VendorPersonnel.php +10 -1
  221. package/server/src/Models/Waypoint.php +2 -2
  222. package/server/src/Models/Zone.php +1 -1
  223. package/server/src/Notifications/LateDeparture.php +2 -2
  224. package/server/src/Notifications/ProlongedStoppage.php +2 -2
  225. package/server/src/Notifications/RouteDeviation.php +2 -2
  226. package/server/src/Observers/ContactObserver.php +2 -0
  227. package/server/src/Observers/PurchaseRateObserver.php +20 -0
  228. package/server/src/Observers/ServiceRateObserver.php +6 -6
  229. package/server/src/Observers/ZoneObserver.php +56 -0
  230. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +1 -1
  231. package/server/src/Providers/FleetOpsServiceProvider.php +2 -0
  232. package/server/src/Support/Analytics/AbstractAnalytics.php +6 -6
  233. package/server/src/Support/Analytics/FuelEfficiency.php +2 -2
  234. package/server/src/Support/Analytics/OrdersByStatus.php +1 -1
  235. package/server/src/Support/Analytics/RevenueTrend.php +0 -1
  236. package/server/src/Support/Analytics/TopDrivers.php +10 -2
  237. package/server/src/Support/CustomerAuth.php +98 -0
  238. package/server/src/Support/GettingStarted.php +144 -0
  239. package/server/src/Support/LabelPdf.php +52 -0
  240. package/server/src/Support/Metrics/AbstractMetric.php +4 -4
  241. package/server/src/Support/PlaceSearch.php +282 -0
  242. package/server/src/Support/ResolvesOrderServiceStops.php +522 -0
  243. package/server/src/Tracking/TrackingContextBuilder.php +41 -38
  244. package/server/src/Tracking/TrackingIntelligenceService.php +109 -9
  245. package/server/src/Tracking/TrackingStop.php +13 -11
  246. package/server/src/routes.php +76 -10
  247. package/server/tests/AnalyticsRoutesTest.php +8 -0
  248. package/server/tests/CapacityAllocationEngineTest.php +10 -10
  249. package/server/tests/CustomerContactIdentitySafetyTest.php +95 -0
  250. package/server/tests/CustomerEndpointTest.php +199 -0
  251. package/server/tests/DriverVehicleStatusDefaultTest.php +39 -0
  252. package/server/tests/GettingStartedStatusTest.php +21 -0
  253. package/server/tests/LabelPdfRenderingTest.php +23 -0
  254. package/server/tests/LiveControllerViewportTest.php +60 -0
  255. package/server/tests/MetricsRegistryTest.php +4 -8
  256. package/server/tests/OrchestrationPayloadBuilderTest.php +2 -2
  257. package/server/tests/OrderActivityFlowRegressionTest.php +116 -0
  258. package/server/tests/OrderConfigEndpointTest.php +86 -0
  259. package/server/tests/OrderFileAttachmentTest.php +20 -0
  260. package/server/tests/ServiceAreaZoneApiShapeTest.php +78 -0
  261. package/server/tests/VehicleDriverAssignmentTest.php +18 -0
  262. package/translations/ar-ae.yml +9 -0
  263. package/translations/bg-bg.yaml +9 -0
  264. package/translations/en-us.yaml +12 -0
  265. package/translations/es-pa.yaml +9 -0
  266. package/translations/fr-fr.yaml +9 -0
  267. package/translations/mn-mn.yaml +9 -0
  268. package/translations/pt-br.yaml +9 -0
  269. package/translations/ru-ru.yaml +9 -0
  270. package/translations/vi-vn.yaml +9 -0
  271. package/server/migrations/2026_05_13_000001_repair_customer_contact_user_types.php +0 -86
@@ -27,6 +27,7 @@
27
27
  @onClick={{fn this.addWaypoint (hash)}}
28
28
  @helpText={{t "order.fields.add-waypoint-help-text"}}
29
29
  @permission={{cannot-write @resource}}
30
+ data-test-waypoint-add
30
31
  />
31
32
  {{/if}}
32
33
  </div>
@@ -34,118 +35,123 @@
34
35
 
35
36
  {{#if this.multipleWaypoints}}
36
37
  <DragSortList class="multi-drop-select-container overflow-visible" @items={{@resource.payload.waypoints}} @dragEndAction={{this.sortWaypoints}} as |waypoint index|>
37
- <div id={{concat "waypoint_" (add index 1)}} class="border rounded-md px-3 py-2 shadow-sm border-gray-300 dark:border-gray-900 mb-3">
38
- <div class="flex items-start justify-between">
39
- <div class="flex items-center justify-between grip-cursor">
40
- <FaIcon @icon="grip-lines" @prefix="fas" class="mr-3 text-gray-100" />
41
- <label class="waypoint-label dark:text-gray-100 text-sm">
42
- {{waypoint-label (add index 1)}}
43
- </label>
44
- </div>
45
-
46
- <div class="flex-1 flex-col px-3">
47
- <div class="mb-2">
48
- <ModelSelect
49
- @modelName="place"
50
- @selectedModel={{waypoint.place}}
51
- @placeholder={{concat (t "order.fields.select-waypoint") " " (add index 1)}}
52
- @triggerClass="form-select form-input truncate max-w-300px"
53
- @infiniteScroll={{false}}
54
- @customSearchEndpoint="places/search"
55
- @query={{hash geo=true latitude=this.location.latitude longitude=this.location.longitude}}
56
- @renderInPlace={{true}}
57
- @onChange={{fn this.setWaypointPlace index}}
58
- @permission={{cannot-write @resource}}
59
- as |place|
60
- >
61
- <Place::Address @place={{place}} />
62
- </ModelSelect>
63
- {{#if (and @resource.facilitator.isIntegratedVendor (is-not-facilitator-supported-place @resource.facilitator waypoint.place))}}
64
- <InfoBlock
65
- class="my-2 px-4 py-1.5 danger"
66
- @blockClass="flex flex-row items-center"
67
- @text={{concat @resource.facilitator.name (t "order.fields.infoblock-text")}}
68
- />
69
- {{/if}}
70
- {{#if waypoint.place.hasInvalidCoordinates}}
71
- <div class="leading-5 text-sm text-red-400 mt-2">
72
- <FaIcon @icon="exclamation-triangle" class="mr-1" />
73
- {{t "order.fields.invalid-coordinates"}}
74
- </div>
75
- {{/if}}
38
+ {{#let (get this.waypointRouteStops index) as |stop|}}
39
+ <div
40
+ id={{concat "waypoint_" (add index 1)}}
41
+ class="fleetops-order-form-waypoint {{if stop.required 'fleetops-order-form-waypoint--required'}} border rounded-md px-3 py-2 shadow-sm border-gray-300 dark:border-gray-900 mb-3"
42
+ data-test-waypoint-row={{add index 1}}
43
+ >
44
+ {{#if stop.required}}
45
+ <div class="fleetops-order-form-waypoint__required-tab" data-test-required-waypoint-tab>Required</div>
46
+ {{/if}}
47
+ <div class="flex items-start justify-between">
48
+ <div class="fleetops-order-form-waypoint__marker grip-cursor">
49
+ <FaIcon @icon="grip-lines" @prefix="fas" class="text-gray-400" />
50
+ <span class="index-count fleetops-route-stop-badge fleetops-order-form-waypoint__badge" style={{stop.badgeStyle}}>{{stop.label}}</span>
76
51
  </div>
77
- <div>
78
- <ModelSelect
79
- @modelName="customer"
80
- @selectedModel={{waypoint.customer}}
81
- @placeholder={{t "order.fields.customer-placeholder"}}
82
- @triggerClass="form-select form-input truncate max-w-300px"
83
- @infiniteScroll={{false}}
84
- @renderInPlace={{true}}
85
- @allowClear={{true}}
86
- @onChange={{fn this.setWaypointCustomer waypoint}}
87
- @permission={{cannot-write @resource}}
88
- as |model|
89
- >
90
- <div class="flex items-center">
91
- <div class="w-7">
92
- <FaIcon @icon={{if model.isVendor "warehouse" "user"}} />
52
+
53
+ <div class="flex-1 flex-col px-3">
54
+ <div class="mb-2">
55
+ <ModelSelect
56
+ @modelName="place"
57
+ @selectedModel={{waypoint.place}}
58
+ @placeholder={{concat (t "order.fields.select-waypoint") " " (add index 1)}}
59
+ @triggerClass="form-select form-input truncate max-w-300px"
60
+ @infiniteScroll={{false}}
61
+ @customSearchEndpoint="places/search"
62
+ @query={{hash geo=true latitude=this.location.latitude longitude=this.location.longitude}}
63
+ @renderInPlace={{true}}
64
+ @onChange={{fn this.setWaypointPlace index}}
65
+ @permission={{cannot-write @resource}}
66
+ as |place|
67
+ >
68
+ <Place::Address @place={{place}} />
69
+ </ModelSelect>
70
+ {{#if (and @resource.facilitator.isIntegratedVendor (is-not-facilitator-supported-place @resource.facilitator waypoint.place))}}
71
+ <InfoBlock
72
+ class="my-2 px-4 py-1.5 danger"
73
+ @blockClass="flex flex-row items-center"
74
+ @text={{concat @resource.facilitator.name (t "order.fields.infoblock-text")}}
75
+ />
76
+ {{/if}}
77
+ {{#if waypoint.place.hasInvalidCoordinates}}
78
+ <div class="leading-5 text-sm text-red-400 mt-2">
79
+ <FaIcon @icon="exclamation-triangle" class="mr-1" />
80
+ {{t "order.fields.invalid-coordinates"}}
93
81
  </div>
94
- <span class="uppercase">
95
- {{model.name}}
96
- </span>
97
- </div>
98
- </ModelSelect>
99
- </div>
100
- <div>
101
- <div class="flex flex-row items-center space-x-4 text-sm mt-2">
102
- <div class={{if (eq waypoint.type "dropoff") "is-checked"}}>
103
- <div class="flex flex-row items-center">
104
- <RadioButton
105
- @radioClass="focus:ring-blue-500 h-4 w-4 text-blue-500"
106
- @radioId={{concat "waypoint_" index "_dropoff"}}
107
- @value="dropoff"
108
- @groupValue={{waypoint.type}}
109
- @name={{concat "waypoint_" index "_dropoff"}}
110
- @changed={{fn (mut waypoint.type)}}
111
- />
112
- <label for={{concat "waypoint_" index "_dropoff"}} class="ml-2">Dropoff</label>
82
+ {{/if}}
83
+ </div>
84
+ <div>
85
+ <ModelSelect
86
+ @modelName="customer"
87
+ @selectedModel={{waypoint.customer}}
88
+ @placeholder={{t "order.fields.customer-placeholder"}}
89
+ @triggerClass="form-select form-input truncate max-w-300px"
90
+ @infiniteScroll={{false}}
91
+ @renderInPlace={{true}}
92
+ @allowClear={{true}}
93
+ @onChange={{fn this.setWaypointCustomer waypoint}}
94
+ @permission={{cannot-write @resource}}
95
+ as |model|
96
+ >
97
+ <div class="flex items-center">
98
+ <div class="w-7">
99
+ <FaIcon @icon={{if model.isVendor "warehouse" "user"}} />
100
+ </div>
101
+ <span class="uppercase">
102
+ {{model.name}}
103
+ </span>
113
104
  </div>
114
- </div>
115
- <div class={{if (eq waypoint.type "pickup") "is-checked"}}>
116
- <div class="flex flex-row items-center">
117
- <RadioButton
118
- @radioClass="focus:ring-blue-500 h-4 w-4 text-blue-500"
119
- @radioId={{concat "waypoint_" index "_pickup"}}
120
- @value="pickup"
121
- @groupValue={{waypoint.type}}
122
- @name={{concat "waypoint_" index "_pickup"}}
123
- @changed={{fn (mut waypoint.type)}}
124
- />
125
- <label for={{concat "waypoint_" index "_pickup"}} class="ml-2">Pickup</label>
105
+ </ModelSelect>
106
+ </div>
107
+ <div>
108
+ <div class="flex flex-row items-center space-x-4 text-sm mt-2">
109
+ <div class={{if (eq waypoint.type "dropoff") "is-checked"}}>
110
+ <div class="flex flex-row items-center">
111
+ <RadioButton
112
+ @radioClass="focus:ring-blue-500 h-4 w-4 text-blue-500"
113
+ @radioId={{concat "waypoint_" index "_dropoff"}}
114
+ @value="dropoff"
115
+ @groupValue={{waypoint.type}}
116
+ @name={{concat "waypoint_" index "_dropoff"}}
117
+ @changed={{fn (mut waypoint.type)}}
118
+ />
119
+ <label for={{concat "waypoint_" index "_dropoff"}} class="ml-2">Dropoff</label>
120
+ </div>
121
+ </div>
122
+ <div class={{if (eq waypoint.type "pickup") "is-checked"}}>
123
+ <div class="flex flex-row items-center">
124
+ <RadioButton
125
+ @radioClass="focus:ring-blue-500 h-4 w-4 text-blue-500"
126
+ @radioId={{concat "waypoint_" index "_pickup"}}
127
+ @value="pickup"
128
+ @groupValue={{waypoint.type}}
129
+ @name={{concat "waypoint_" index "_pickup"}}
130
+ @changed={{fn (mut waypoint.type)}}
131
+ />
132
+ <label for={{concat "waypoint_" index "_pickup"}} class="ml-2">Pickup</label>
133
+ </div>
126
134
  </div>
127
135
  </div>
128
136
  </div>
129
137
  </div>
130
- </div>
131
138
 
132
- <div class="flex items-center space-x-2">
133
- {{#if waypoint.place}}
134
- <Button @icon="edit" @size="sm" @onClick={{fn this.editPlace waypoint.place}} @disabled={{cannot-write waypoint.place}} />
135
- {{/if}}
136
- {{#unless (eq index 0)}}
137
- <Button @type="danger" @icon="trash" @size="sm" @onClick={{fn this.removeWaypoint waypoint}} />
138
- {{/unless}}
139
+ <div class="flex items-center space-x-2">
140
+ {{#if waypoint.place}}
141
+ <Button @icon="edit" @size="sm" @onClick={{fn this.editPlace waypoint.place}} @disabled={{cannot-write waypoint.place}} />
142
+ {{/if}}
143
+ {{#unless (eq index 0)}}
144
+ <Button @type="danger" @icon="trash" @size="sm" @onClick={{fn this.removeWaypoint waypoint}} />
145
+ {{/unless}}
146
+ </div>
139
147
  </div>
140
148
  </div>
141
- </div>
149
+ {{/let}}
142
150
  </DragSortList>
143
151
  {{else}}
144
152
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-2 text-xs dark:text-gray-100">
145
- <InputGroup>
146
- <div class="flex items-center justify-between">
147
- <label>{{t "order.fields.pickup"}}</label>
148
-
153
+ <InputGroup @name={{t "order.fields.pickup"}} @required={{true}}>
154
+ <div class="flex items-center justify-end">
149
155
  <div class="flex-row space-x-1 pr-0.5">
150
156
  {{#if @resource.payload.pickup}}
151
157
  <a href="javascript:;" {{on "click" (fn this.editPlace @resource.payload.pickup)}}>
@@ -186,10 +192,8 @@
186
192
  {{/if}}
187
193
  </InputGroup>
188
194
 
189
- <InputGroup>
190
- <div class="flex items-center justify-between">
191
- <label>{{t "order.fields.dropoff"}}</label>
192
-
195
+ <InputGroup @name={{t "order.fields.dropoff"}} @required={{true}}>
196
+ <div class="flex items-center justify-end">
193
197
  <div class="flex-row space-x-2 pr-0.5">
194
198
  {{#if @resource.payload.dropoff}}
195
199
  <a href="javascript:;" {{on "click" (fn this.editPlace @resource.payload.dropoff)}} disaled={{cannot "fleet-ops update place"}}>
@@ -268,4 +272,4 @@
268
272
  </InputGroup>
269
273
  </div>
270
274
  {{/if}}
271
- </ContentPanel>
275
+ </ContentPanel>
@@ -4,7 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { action, get } from '@ember/object';
5
5
  import { task } from 'ember-concurrency';
6
6
  import { colorForId, routeColorForStatus, routeStyleForStatus } from '../../../utils/route-colors';
7
- import { buildRoutePointMarkerPresentation, buildRoutePointsFromPayload } from '../../../utils/route-visualization';
7
+ import { buildRoutePointMarkerPresentation, buildRoutePointsFromPayload, describeRoutePoint } from '../../../utils/route-visualization';
8
8
 
9
9
  const ORDER_ROUTE_PREVIEW_PADDING_BOTTOM_RIGHT = [420, 0];
10
10
  const ORDER_ROUTE_PREVIEW_MAX_ZOOM_TWO_POINTS = 13;
@@ -45,6 +45,42 @@ export default class OrderFormRouteComponent extends Component {
45
45
  return buildRoutePointsFromPayload(this.args.resource.payload);
46
46
  }
47
47
 
48
+ get routeColor() {
49
+ const order = this.args.resource;
50
+
51
+ return colorForId(order?.public_id ?? order?.id ?? 'new-order');
52
+ }
53
+
54
+ get waypointRouteStops() {
55
+ const waypoints = this.args.resource.payload?.waypoints ?? [];
56
+
57
+ return waypoints.map((_waypoint, index) => {
58
+ const routePoint = {
59
+ role: 'waypoint',
60
+ stopNumber: index + 1,
61
+ };
62
+
63
+ return {
64
+ ...describeRoutePoint(routePoint, this.routeColor),
65
+ badgeStyle: this.badgeStyleForWaypoint(index),
66
+ required: this.isRequiredWaypoint(index),
67
+ };
68
+ });
69
+ }
70
+
71
+ badgeStyleForWaypoint(index) {
72
+ const { markerColor } = describeRoutePoint({ role: 'waypoint', stopNumber: index + 1 }, this.routeColor);
73
+ const normalizedColor = markerColor?.toLowerCase?.();
74
+ const isYellow = normalizedColor === '#facc15' || normalizedColor === '#ca8a04';
75
+ const textColor = isYellow ? '#111827' : '#ffffff';
76
+
77
+ return `background-color: ${markerColor}; color: ${textColor};`;
78
+ }
79
+
80
+ isRequiredWaypoint(index) {
81
+ return index < 2;
82
+ }
83
+
48
84
  willDestroy() {
49
85
  super.willDestroy(...arguments);
50
86
  if (this.routingControl) {
@@ -75,7 +75,7 @@
75
75
  {{#each serviceQuote.items as |item|}}
76
76
  <tr>
77
77
  <td>
78
- <span class="font-semibold">{{smart-humanize item.details}}</span>
78
+ <span class="font-semibold">{{item.details}}</span>
79
79
  </td>
80
80
  <td>
81
81
  <span>{{format-currency item.amount serviceQuote.currency}}</span>
@@ -106,4 +106,4 @@
106
106
  </div>
107
107
  {{/if}}
108
108
  </div>
109
- </ContentPanel>
109
+ </ContentPanel>
@@ -10,7 +10,7 @@
10
10
  <Badge @status={{@order.status}} @helpText={{if (eq @order.status (t "order.header.dispatched")) (concat (t "order.header.dispatched-at") @order.dispatchedAt)}} />
11
11
  {{#if @order.shouldDisplayDispatchLabel}}
12
12
  <Badge @status="info" class="ml-2" @helpText={{t "order.header.dispatched" htmlSafe=true order=@order.dispatchedAt}}>{{t
13
- "fleet-ops.component.order.header.dispatched"
13
+ "order-status.dispatched"
14
14
  }}</Badge>
15
15
  {{/if}}
16
16
  </div>
@@ -10,10 +10,13 @@
10
10
  />
11
11
  <Button @type="default" @icon="rotate" @text="Reset" @onClick={{this.resetConfig}} @disabled={{or this.config.core_service (cannot "fleet-ops update order-config")}} />
12
12
  </div>
13
- <div class="activity-flow-graph-container">
13
+ <div class="activity-flow-graph-container" {{did-insert this.setupGraphScrollContainer}}>
14
14
  <div class="activity-flow-zoom-controls">
15
15
  <Button @icon="plus" @onClick={{this.zoomIn}} />
16
16
  <Button @icon="minus" @onClick={{this.zoomOut}} />
17
17
  </div>
18
18
  <JointGraph @onSetup={{this.initializeGraph}} />
19
+ </div>
20
+ <div class="activity-flow-horizontal-scrollbar {{unless this.hasHorizontalOverflow 'is-hidden'}}" {{did-insert this.setupHorizontalScrollbar}}>
21
+ <div class="activity-flow-horizontal-scrollbar-content"></div>
19
22
  </div>