diff --git a/src/layouts/review/review-block/review-block.vue b/src/layouts/review/review-block/review-block.vue
index 67e639da9..497aa3634 100644
--- a/src/layouts/review/review-block/review-block.vue
+++ b/src/layouts/review/review-block/review-block.vue
@@ -3,6 +3,7 @@
+
+
+
+
diff --git a/src/layouts/review/review-sections/service-location-review/service-location-review.vue b/src/layouts/review/review-sections/service-location-review/service-location-review.vue
index db4f8188a..0da8361c3 100644
--- a/src/layouts/review/review-sections/service-location-review/service-location-review.vue
+++ b/src/layouts/review/review-sections/service-location-review/service-location-review.vue
@@ -10,7 +10,7 @@ import reviewBlock from "@/layouts/review/review-block/review-block";
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
export default {
- name: "service-package-review",
+ name: "service-location-review",
props: {
cmsWidgetName: String,
serviceLocation: Object,
diff --git a/src/layouts/review/review.vue b/src/layouts/review/review.vue
index 59320bce9..78f24c35f 100644
--- a/src/layouts/review/review.vue
+++ b/src/layouts/review/review.vue
@@ -69,6 +69,13 @@
cmsWidgetName="ServiceLocationTitleWidget"
:serviceLocation="serviceLocationInfo"
@edit-clicked="editServiceLocation" />
+
+
+
+
@@ -94,22 +101,16 @@ import vehicleReview from "@/layouts/review/review-sections/vehicle-review/vehic
import damageReview from "@/layouts/review/review-sections/damage-review/damage-review";
import servicePackageReview from "@/layouts/review/review-sections/service-package-review/service-package-review";
import serviceLocationReview from "@/layouts/review/review-sections/service-location-review/service-location-review";
+import scheduleReview from "@/layouts/review/review-sections/schedule-review/schedule-review";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
-import baseMixin from "@/mixins/base-mixin.js";
-import { storeActions } from "@/constants/store-actions";
export default {
name: "review",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
- // Get rain defense and wiper availability for package review section.
- const wipersPromise = baseMixin.methods.dispatchStoreAction(storeActions.GET_WIPERS);
- const rainDefensePromise = baseMixin.methods.dispatchStoreAction(
- storeActions.GET_RAIN_DEFENSE
- );
const servicePackageInitialDataPromise = servicePackageReview.methods.loadInitialData();
@@ -168,6 +169,12 @@ export default {
this.$route
);
},
+ editSchedule() {
+ this.$router.navigateWithoutSaving(
+ this.navigationScenarios.CLICKED_SCHEDULE_EDIT,
+ this.$route
+ );
+ },
},
computed: {
subHeaderTitle() {
@@ -191,6 +198,12 @@ export default {
serviceLocationInfo() {
return this.$store.getters.order.serviceLocation;
},
+ appointmentType() {
+ return this.$store.getters.order.serviceLocation.appointmentType;
+ },
+ exposeCms() {
+ return this.$root.cmsContentByWidget;
+ },
},
components: {
funnelHeader,
@@ -202,6 +215,7 @@ export default {
damageReview,
servicePackageReview,
serviceLocationReview,
+ scheduleReview,
},
};
diff --git a/src/layouts/schedule/helpers/schedule-helper.js b/src/layouts/schedule/helpers/schedule-helper.js
index 82c756b5b..0f595b435 100644
--- a/src/layouts/schedule/helpers/schedule-helper.js
+++ b/src/layouts/schedule/helpers/schedule-helper.js
@@ -45,3 +45,33 @@ export function sumDateString(dateString, daysToAdd) {
date.setDate(date.getDate() + daysToAdd);
return convertDateToDateString(date);
}
+
+export function militaryToTwelveHourTime(timeString) {
+ // Expected input: "HH:MM"
+ if (typeof timeString !== "string") return;
+ let hours = parseInt(timeString.split(":")[0]);
+ const minutes = timeString.split(":")[1];
+ const meridianNotation = hours > 11 ? "PM" : "AM";
+
+ if (hours > 12) {
+ hours -= 12;
+ }
+
+ return `${hours}:${minutes} ${meridianNotation}`;
+}
+
+export function getDisplayTextForDurationLength(durationMinimum, durationMaximum) {
+ const isLongAppointment = durationMaximum >= 120;
+ const isDurationRange = durationMinimum !== durationMaximum;
+
+ const adjustedMinimum = isLongAppointment ? durationMinimum / 60 : durationMinimum;
+ const adjustedMaximum = isLongAppointment ? durationMaximum / 60 : durationMaximum;
+
+ const durationText = isDurationRange
+ ? `${adjustedMinimum} - ${adjustedMaximum}`
+ : adjustedMinimum;
+
+ const unitText = isLongAppointment ? "hours" : "minutes";
+
+ return `${durationText} ${unitText}`;
+}
diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue
index 5bebe26fb..6a42b7a92 100644
--- a/src/layouts/schedule/schedule.vue
+++ b/src/layouts/schedule/schedule.vue
@@ -459,6 +459,7 @@ export default {
startTime: null,
endTime: null,
jobMaxMinutes: null,
+ jobMinMinutes: null,
};
}
},
diff --git a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue
index 724facf6c..cce2c0503 100644
--- a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue
+++ b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue
@@ -47,7 +47,11 @@ import buttonQuestion from "@/digital-components/button-question/button-question
import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button";
// Helpers
-import { convertDateStringToDate } from "@/layouts/schedule/helpers/schedule-helper";
+import {
+ convertDateStringToDate,
+ militaryToTwelveHourTime,
+ getDisplayTextForDurationLength,
+} from "@/layouts/schedule/helpers/schedule-helper";
import { deepClone } from "@/helpers/object-helper";
// Validation - TODO: Move this somewhere more global?
@@ -88,6 +92,7 @@ export default {
startTime: null,
endTime: null,
jobMaxMinutes: null,
+ jobMinMinutes: null,
}),
},
cmsWidgetName: String,
@@ -263,7 +268,7 @@ export default {
cmsWidgetFieldMappings.DURATION
);
- const inshopDurationTime = this.getDisplayTextForDurationLength(
+ const inshopDurationTime = getDisplayTextForDurationLength(
this.estimatedServiceMinutesMinimum,
this.estimatedServiceMinutesMaximum
);
@@ -346,33 +351,6 @@ export default {
this.$emit("update:modelValue", this.selectedValue);
this.closeModal();
},
- getDisplayTextForMilitaryTime(militaryTimeInput) {
- // Expected input: "HH:MM"
- let hours = parseInt(militaryTimeInput.split(":")[0]);
- const minutes = militaryTimeInput.split(":")[1];
- const meridianNotation = hours > 11 ? "PM" : "AM";
-
- if (hours > 12) {
- hours -= 12;
- }
-
- return `${hours}:${minutes} ${meridianNotation}`;
- },
- getDisplayTextForDurationLength(durationMinimum, durationMaximum) {
- const isLongAppointment = durationMaximum >= 120;
- const isDurationRange = durationMinimum !== durationMaximum;
-
- const adjustedMinimum = isLongAppointment ? durationMinimum / 60 : durationMinimum;
- const adjustedMaximum = isLongAppointment ? durationMaximum / 60 : durationMaximum;
-
- const durationText = isDurationRange
- ? `${adjustedMinimum} - ${adjustedMaximum}`
- : adjustedMinimum;
-
- const unitText = isLongAppointment ? "hours" : "minutes";
-
- return `${durationText} ${unitText}`;
- },
getRelevantDropOffCmsWidgetNameForSelectedTimeSlot(
selectedTimeSlotId,
isSameDayRelevant = false
@@ -387,7 +365,7 @@ export default {
},
getAvailableTimeSlotsForInshop(timeSlotsForSelectedDate) {
return timeSlotsForSelectedDate.map((timeSlot) => {
- const readableTime = this.getDisplayTextForMilitaryTime(timeSlot.startTime);
+ const readableTime = militaryToTwelveHourTime(timeSlot.startTime);
return {
value: timeSlot.id,
buttonLabel: readableTime,
@@ -415,9 +393,9 @@ export default {
},
getAvailableTimeSlotsForMobile(timeSlotsForSelectedDate) {
const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => {
- const readableTime = `${this.getDisplayTextForMilitaryTime(
+ const readableTime = `${militaryToTwelveHourTime(
timeSlot.startTime
- )} - ${this.getDisplayTextForMilitaryTime(timeSlot.endTime)}`;
+ )} - ${militaryToTwelveHourTime(timeSlot.endTime)}`;
return {
value: timeSlot.id,
buttonLabel: readableTime,
@@ -472,6 +450,7 @@ export default {
startTime: timeSlot.startTime,
endTime: timeSlot.endTime,
jobMaxMinutes: this.estimatedServiceMinutesMaximum.toString(),
+ jobMinMinutes: this.estimatedServiceMinutesMinimum.toString(),
};
}
@@ -481,6 +460,7 @@ export default {
endTime: null,
routeCode: null,
jobMaxMinutes: null,
+ jobMinMinutes: null,
};
},
},
diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js
index ae1c880ae..ce2f32134 100644
--- a/src/router/router-constants/navigation-scenarios.js
+++ b/src/router/router-constants/navigation-scenarios.js
@@ -51,6 +51,7 @@ const navigationScenarios = {
CLICKED_DAMAGE_EDIT: "CLICKED_DAMAGE_EDIT",
CLICKED_SERVICE_PACKAGE_EDIT: "CLICKED_SERVICE_PACKAGE_EDIT",
CLICKED_SERVICE_LOCATION_EDIT: "CLICKED_SERVICE_LOCATION_EDIT",
+ CLICKED_SCHEDULE_EDIT: "CLICKED_SCHEDULE_EDIT",
};
export { navigationScenarios };
diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js
index 017e1372a..f1f83b445 100644
--- a/src/router/router-constants/routing-table.js
+++ b/src/router/router-constants/routing-table.js
@@ -484,6 +484,10 @@ const routingTable = function (store) {
scenario: navigationScenarios.CLICKED_SERVICE_LOCATION_EDIT,
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
},
+ {
+ scenario: navigationScenarios.CLICKED_SCHEDULE_EDIT,
+ destinationFmgPageValue: fmgPageValues.SCHEDULE,
+ },
],
},
];
diff --git a/src/store/index.js b/src/store/index.js
index 7d1caf59a..635d685b4 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -14,6 +14,11 @@ import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper
import { deepEqual } from "@/helpers/object-helper";
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
import { partTypeStrings } from "@/constants/part-type-strings";
+import {
+ convertDateStringToDate,
+ militaryToTwelveHourTime,
+ getDisplayTextForDurationLength,
+} from "@/layouts/schedule/helpers/schedule-helper";
// Export State
const getDefaultState = () => {
@@ -96,6 +101,7 @@ const getDefaultState = () => {
endTime: null,
routeCode: null,
jobMaxMinutes: null,
+ jobMinMinutes: null,
},
referralNumber: null,
referralDate: null,
@@ -283,6 +289,7 @@ export const mutations = {
state.order.schedule.endTime = scheduleInfo.endTime;
state.order.schedule.routeCode = scheduleInfo.routeCode;
state.order.schedule.jobMaxMinutes = scheduleInfo.jobMaxMinutes;
+ state.order.schedule.jobMinMinutes = scheduleInfo.jobMinMinutes;
}
},
updateCustomerDetails(state, customerDetails) {
@@ -368,6 +375,7 @@ export const mutations = {
state.order.schedule.endTime = null;
state.order.schedule.routeCode = null;
state.order.schedule.jobMaxMinutes = null;
+ state.order.schedule.jobMinMinutes = null;
//premium appointment fee used on schedule page also needs reset when schedule is reset
const supportingItems = state.order.lineItems.supportingItems;
@@ -506,6 +514,7 @@ export const mutations = {
state.order.schedule.endTime = sessionInformation.order.schedule?.endTime;
state.order.schedule.routeCode = sessionInformation.order.schedule?.routeCode;
state.order.schedule.jobMaxMinutes = sessionInformation.order.schedule?.jobMaxMinutes;
+ state.order.schedule.jobMinMinutes = sessionInformation.order.schedule?.jobMinMinutes;
},
updateExperiments(state, experiments) {
state.applicationUser.experiments = experiments;
@@ -540,6 +549,9 @@ export const getters = {
isMobileAppointment: (state) => {
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
},
+ isDropOffAppointment: (state) => {
+ return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF;
+ },
isRecalibrationOnOrder: (state) => {
return getHasRecalibrationPart(state);
},
@@ -548,6 +560,30 @@ export const getters = {
(vap) => vap.partType.toUpperCase() === partTypeStrings.REAR_WIPER.toUpperCase()
);
},
+ scheduleDisplayText: (state) => {
+ const dateModel = convertDateStringToDate(state.order.schedule.date);
+ const readableDate = dateModel?.toLocaleDateString("en-us", {
+ weekday: "long",
+ month: "long",
+ day: "numeric",
+ year: "numeric",
+ });
+
+ const readableStartTime = militaryToTwelveHourTime(state.order.schedule.startTime);
+ const readableEndTime = militaryToTwelveHourTime(state.order.schedule.endTime);
+
+ const readableDuration = getDisplayTextForDurationLength(
+ state.order.schedule.jobMinMinutes,
+ state.order.schedule.jobMaxMinutes
+ );
+
+ return {
+ date: readableDate,
+ startTime: readableStartTime,
+ endTime: readableEndTime,
+ duration: readableDuration,
+ };
+ },
lineItems: (state) => state.order.lineItems,
pageData: (state) => (page) => {
return state.applicationUser.pageData[page];
@@ -1458,6 +1494,7 @@ export const actions = {
endTime: order.schedule?.endTime,
routeCode: order.schedule?.routeCode,
jobMaxMinutes: order.schedule?.jobMaxMinutes,
+ jobMinMinutes: order.schedule?.jobMinMinutes,
},
existingPromoCode: null,
referralCorrelationId: order.referralCorrelationId,