-
-
diff --git a/addon/components/order/form/details.js b/addon/components/order/form/details.js
index 86a99a450..84ffdcda2 100644
--- a/addon/components/order/form/details.js
+++ b/addon/components/order/form/details.js
@@ -20,9 +20,14 @@ export default class OrderFormDetailsComponent extends Component {
this.orderConfigActions.loadAll.perform();
}
+ get integratedVendorServiceType() {
+ return this.args.resource?.type;
+ }
+
@action selectFacilitator(model) {
this.args.resource.set('facilitator', model);
this.args.resource.set('driver', null);
+ this.requestServiceQuoteRefresh('details.facilitator.changed');
}
@action selectCustomer(model) {
@@ -39,6 +44,7 @@ export default class OrderFormDetailsComponent extends Component {
type: orderConfig.key,
});
this.args.resource.payload.set('type', orderConfig.key);
+ this.requestServiceQuoteRefresh('details.order_config.changed');
try {
const customFieldsManager = yield this.customFieldsRegistry.loadSubjectCustomFields.perform(orderConfig);
@@ -70,61 +76,16 @@ export default class OrderFormDetailsComponent extends Component {
this.leafletLayerVisibilityManager.showModelLayer(this.args.resource.driver_assigned);
}
- /**
- * Resolves the reference date to use when pre-populating the date portion
- * of a time window field. Prefers scheduled_at, falls back to created_at,
- * and finally falls back to now so there is always a valid date.
- *
- * @returns {Date}
- */
- get _timeWindowReferenceDate() {
- const raw = this.args.resource.scheduled_at ?? this.args.resource.created_at ?? new Date();
- return raw instanceof Date ? raw : new Date(raw);
+ @action setScheduledAt(value) {
+ this.args.resource.scheduled_at = value;
+ this.requestServiceQuoteRefresh('details.scheduled_at.changed');
}
- /**
- * Called by DateTimeInput @onUpdate for time_window_start and time_window_end.
- *
- * When the user picks a time, we preserve their chosen time but replace the
- * date portion with the order's scheduled_at date (or created_at if
- * scheduled_at is not set). This means the user only ever needs to set the
- * time — the date is always contextually correct.
- *
- * If the incoming value already carries a different date (e.g. the user
- * explicitly changed it via the date part of the picker) we respect that
- * and do not override it.
- *
- * @param {'time_window_start'|'time_window_end'} field
- * @param {Date|string|null} value Value emitted by DateTimeInput
- */
- @action setTimeWindow(field, value) {
- if (!value) {
- this.args.resource[field] = null;
- return;
- }
-
- const picked = value instanceof Date ? value : new Date(value);
- if (isNaN(picked.getTime())) {
- this.args.resource[field] = value;
- return;
- }
-
- const ref = this._timeWindowReferenceDate;
-
- // Only inject the reference date when the picked value has no meaningful
- // date of its own — i.e. when the date portion is the Unix epoch
- // (1970-01-01), which is what DateTimeInput emits when the user has only
- // touched the time picker and not the date picker.
- const isEpochDate = picked.getUTCFullYear() === 1970 && picked.getUTCMonth() === 0 && picked.getUTCDate() === 1;
-
- if (isEpochDate) {
- const merged = new Date(ref);
- merged.setHours(picked.getHours(), picked.getMinutes(), picked.getSeconds(), 0);
- this.args.resource[field] = merged;
- } else {
- // User explicitly set a date — honour it as-is.
- this.args.resource[field] = picked;
- }
+ @action selectIntegratedServiceType(serviceType) {
+ const type = serviceType?.key ?? serviceType?.value ?? serviceType;
+ this.args.resource.type = type;
+ this.args.resource.payload.set('type', type);
+ this.requestServiceQuoteRefresh('details.integrated_service_type.changed');
}
@action toggleAdhoc(toggled) {
@@ -136,4 +97,8 @@ export default class OrderFormDetailsComponent extends Component {
this.args.resource.pod_required = toggled;
this.args.resource.pod_method = toggled ? 'scan' : null;
}
+
+ requestServiceQuoteRefresh(reason) {
+ this.orderCreation.requestServiceQuoteRefresh(reason, this.args.resource);
+ }
}
diff --git a/addon/components/order/form/orchestrator-constraints.hbs b/addon/components/order/form/orchestrator-constraints.hbs
new file mode 100644
index 000000000..74c87fb7e
--- /dev/null
+++ b/addon/components/order/form/orchestrator-constraints.hbs
@@ -0,0 +1,40 @@
+
+
+
+ Delivery Window
+
+
+
+
+
+
+
+
+ Requirements & Priority
+
+
+
+
+ {{option.label}}
+
+
+
+
+
+
+
+
diff --git a/addon/components/order/form/orchestrator-constraints.js b/addon/components/order/form/orchestrator-constraints.js
new file mode 100644
index 000000000..730b00a96
--- /dev/null
+++ b/addon/components/order/form/orchestrator-constraints.js
@@ -0,0 +1,61 @@
+import Component from '@glimmer/component';
+import { action } from '@ember/object';
+
+export default class OrderFormOrchestratorConstraintsComponent extends Component {
+ /**
+ * Resolves the reference date to use when pre-populating the date portion
+ * of a time window field. Prefers scheduled_at, falls back to created_at,
+ * and finally falls back to now so there is always a valid date.
+ *
+ * @returns {Date}
+ */
+ get _timeWindowReferenceDate() {
+ const raw = this.args.resource.scheduled_at ?? this.args.resource.created_at ?? new Date();
+ return raw instanceof Date ? raw : new Date(raw);
+ }
+
+ /**
+ * Called by DateTimeInput @onUpdate for time_window_start and time_window_end.
+ *
+ * When the user picks a time, we preserve their chosen time but replace the
+ * date portion with the order's scheduled_at date (or created_at if
+ * scheduled_at is not set). This means the user only ever needs to set the
+ * time, the date is always contextually correct.
+ *
+ * If the incoming value already carries a different date (e.g. the user
+ * explicitly changed it via the date part of the picker) we respect that
+ * and do not override it.
+ *
+ * @param {'time_window_start'|'time_window_end'} field
+ * @param {Date|string|null} value Value emitted by DateTimeInput
+ */
+ @action setTimeWindow(field, value) {
+ if (!value) {
+ this.args.resource[field] = null;
+ return;
+ }
+
+ const picked = value instanceof Date ? value : new Date(value);
+ if (isNaN(picked.getTime())) {
+ this.args.resource[field] = value;
+ return;
+ }
+
+ const ref = this._timeWindowReferenceDate;
+
+ // Only inject the reference date when the picked value has no meaningful
+ // date of its own, i.e. when the date portion is the Unix epoch
+ // (1970-01-01), which is what DateTimeInput emits when the user has only
+ // touched the time picker and not the date picker.
+ const isEpochDate = picked.getUTCFullYear() === 1970 && picked.getUTCMonth() === 0 && picked.getUTCDate() === 1;
+
+ if (isEpochDate) {
+ const merged = new Date(ref);
+ merged.setHours(picked.getHours(), picked.getMinutes(), picked.getSeconds(), 0);
+ this.args.resource[field] = merged;
+ } else {
+ // User explicitly set a date, honour it as-is.
+ this.args.resource[field] = picked;
+ }
+ }
+}
diff --git a/addon/components/order/form/payload.js b/addon/components/order/form/payload.js
index 2b3e401e9..a87738c20 100644
--- a/addon/components/order/form/payload.js
+++ b/addon/components/order/form/payload.js
@@ -7,6 +7,7 @@ export default class OrderFormPayloadComponent extends Component {
@service store;
@service fetch;
@service entityActions;
+ @service orderCreation;
get entitiesByImportId() {
const groups = [];
@@ -32,6 +33,7 @@ export default class OrderFormPayloadComponent extends Component {
const { value } = target;
this.args.resource.payload.entities[index].destination_uuid = value;
+ this.requestServiceQuoteRefresh('entity.destination.changed');
}
@action addFromCustomEntity(customEntity) {
@@ -41,11 +43,15 @@ export default class OrderFormPayloadComponent extends Component {
});
this.args.resource.payload.entities.pushObject(entity);
+ this.requestServiceQuoteRefresh('entity.added');
}
@action addEntities(entities = []) {
if (isArray(entities)) {
this.args.resource.payload.entities.pushObjects(entities);
+ if (entities.length) {
+ this.requestServiceQuoteRefresh('entity.batch_added');
+ }
}
}
@@ -56,21 +62,61 @@ export default class OrderFormPayloadComponent extends Component {
});
this.args.resource.payload.entities.pushObject(entity);
+ this.requestServiceQuoteRefresh('entity.added');
}
@action removeEntity(entity) {
if (this.args.resource.payload.entities.length === 1) return;
if (!entity.isNew) {
- return entity.destroyRecord();
+ return entity.destroyRecord().then(() => {
+ this.requestServiceQuoteRefresh('entity.removed');
+ });
}
this.args.resource.payload.entities.removeObject(entity);
+ this.requestServiceQuoteRefresh('entity.removed');
}
@action editEntity(entity) {
this.entityActions.modal.edit(entity, {
- confirm: (modal) => modal.done(),
+ confirm: (modal) => {
+ modal.done();
+ this.requestServiceQuoteRefresh('entity.edited');
+ },
});
}
+
+ @action setEntityQuoteField(entity, field, value) {
+ this.setEntityValue(entity, field, value);
+ this.requestServiceQuoteRefresh(`entity.${field}.changed`);
+ }
+
+ @action setEntityCurrency(entity, value) {
+ this.setEntityValue(entity, 'currency', value);
+ this.requestServiceQuoteRefresh('entity.currency.changed');
+ }
+
+ @action setEntityDimensionsUnit(entity, value) {
+ this.setEntityValue(entity, 'dimensions_unit', value);
+ this.requestServiceQuoteRefresh('entity.dimensions_unit.changed');
+ }
+
+ @action setEntityWeightUnit(entity, value) {
+ this.setEntityValue(entity, 'weight_unit', value);
+ this.requestServiceQuoteRefresh('entity.weight_unit.changed');
+ }
+
+ setEntityValue(entity, field, value) {
+ if (typeof entity?.set === 'function') {
+ entity.set(field, value);
+ return;
+ }
+
+ entity[field] = value;
+ }
+
+ requestServiceQuoteRefresh(reason) {
+ this.orderCreation.requestServiceQuoteRefresh(reason, this.args.resource);
+ }
}
diff --git a/addon/components/order/form/route.js b/addon/components/order/form/route.js
index 1961843b6..0185ccde6 100644
--- a/addon/components/order/form/route.js
+++ b/addon/components/order/form/route.js
@@ -20,6 +20,7 @@ export default class OrderFormRouteComponent extends Component {
@service currentUser;
@service notifications;
@service placeActions;
+ @service orderCreation;
@tracked multipleWaypoints = false;
@tracked routingControl;
@tracked route;
@@ -119,6 +120,8 @@ export default class OrderFormRouteComponent extends Component {
this.clearWaypoints();
}
+
+ this.requestServiceQuoteRefresh('route.waypoints.toggled');
}
@action sortWaypoints({ sourceList, sourceIndex, targetList, targetIndex }) {
@@ -132,6 +135,7 @@ export default class OrderFormRouteComponent extends Component {
targetList.insertAt(targetIndex, item);
this.previewRoute();
+ this.requestServiceQuoteRefresh('route.waypoints.reordered');
}
@action addWaypoint(properties = {}) {
@@ -143,6 +147,7 @@ export default class OrderFormRouteComponent extends Component {
this.args.resource.payload.waypoints.pushObject(waypoint);
this.previewRoute();
+ this.requestServiceQuoteRefresh('route.waypoint.added');
}
@action setWaypointPlace(index, place) {
@@ -159,6 +164,7 @@ export default class OrderFormRouteComponent extends Component {
location: place.location,
});
this.previewRoute();
+ this.requestServiceQuoteRefresh('route.waypoint.place.changed');
}
@action setWaypointCustomer(waypoint, model) {
@@ -170,16 +176,19 @@ export default class OrderFormRouteComponent extends Component {
if (this.multipleWaypoints && this.args.resource.payload.waypoints.length === 1) return;
this.args.resource.payload.waypoints.removeObject(waypoint);
this.previewRoute();
+ this.requestServiceQuoteRefresh('route.waypoint.removed');
}
@action clearWaypoints() {
this.args.resource.payload.waypoints.clear();
this.previewRoute();
+ this.requestServiceQuoteRefresh('route.waypoints.cleared');
}
@action setPayloadPlace(prop, place) {
this.args.resource.payload[prop] = place;
this.previewRoute();
+ this.requestServiceQuoteRefresh(`route.${prop}.changed`);
}
@action editPlace(place) {
@@ -291,6 +300,7 @@ export default class OrderFormRouteComponent extends Component {
}
this.previewRoute();
this.args.resource.set('optimized', true);
+ this.requestServiceQuoteRefresh('route.optimized');
}
@action setOptimizedRoute(route, trip, waypoints, engine = 'osrm') {
@@ -314,5 +324,10 @@ export default class OrderFormRouteComponent extends Component {
const routeModel = this.store.createRecord('route', payload);
this.args.resource.route = routeModel;
this.route = payload;
+ this.requestServiceQuoteRefresh('route.changed');
+ }
+
+ requestServiceQuoteRefresh(reason) {
+ this.orderCreation.requestServiceQuoteRefresh(reason, this.args.resource);
}
}
diff --git a/addon/components/order/form/service-rate.hbs b/addon/components/order/form/service-rate.hbs
index d023e05fe..06111ebd6 100644
--- a/addon/components/order/form/service-rate.hbs
+++ b/addon/components/order/form/service-rate.hbs
@@ -1,14 +1,55 @@