diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 86a200dc3..156d3696d 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -24,13 +24,13 @@ { - if ( - value.date == null || - value.startTime == null || - value.routeCode == null || - value.estimatedServiceMinutesMaximum - ) { + if (value?.timeSlot?.routeCode == null) { return errorMessages.DATE_REQUIRED; } return true; @@ -190,7 +185,7 @@ export default { data() { return { selectedDate: this.getSelectedDate(), - selectedTimeSlot: this.getSelectedTimeSlot(), + selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(), selectableDatesData: [], mobilePremiumAppointmentFee: null, }; @@ -265,7 +260,7 @@ export default { vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice ? resultMap.premiumFeeWithPrice[0] : null; - vm.updateFooterButtonText(vm.selectedTimeSlot); + vm.updateFooterButtonText(vm.selectedTimeSlotInfo); }); }, computed: { @@ -334,47 +329,52 @@ export default { getSelectedDate() { return store.getters.order.schedule.date; }, - getSelectedTimeSlot() { + getSelectedTimeSlotInfo() { const supportingItems = this.getSupportingItems(); - const isPremiumAppointment = !!supportingItems.filter( - (lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE - ).length > 0; + const isPremiumAppointment = + !!supportingItems.filter((lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE) + .length > 0; - const selectedTimeSlot = store.getters.order.schedule; - selectedTimeSlot.isPremiumAppointment = isPremiumAppointment + const selectedTimeSlotInfo = { + timeSlot: store.getters.order.schedule, + isPremiumAppointment: isPremiumAppointment, + }; - return selectedTimeSlot; + return selectedTimeSlotInfo; }, getSupportingItems() { return store.getters.lineItems.supportingItems; }, timeSlotModalClosed() { // Clear the selectedDate if no timeSlot has been selected - if (this.selectedTimeSlot.routeCode == null) { + if (this.selectedTimeSlotInfo.timeSlot.routeCode == null) { this.selectedDate = null; } }, - updateFooterButtonText(timeSlot) { + updateFooterButtonText(timeSlotInfo) { let funnelFooterButtonText; - if (!timeSlot || !timeSlot.date) { + if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) { funnelFooterButtonText = "Continue"; } else { funnelFooterButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay( - timeSlot.date + timeSlotInfo.timeSlot.date )}`; if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) { funnelFooterButtonText += ` at ${this.getDisplayTextForMilitaryTime( - timeSlot.startTime + timeSlotInfo.timeSlot.startTime )}`; } else if ( this.appointmentType === AppointmentTypeStrings.MOBILE && - !timeSlot.isPremiumAppointment + !timeSlotInfo.isPremiumAppointment ) { funnelFooterButtonText += ` at ${this.getDisplayTextForMilitaryTime( - timeSlot.startTime, + timeSlotInfo.timeSlot.startTime, true - )} - ${this.getDisplayTextForMilitaryTime(timeSlot.endTime, true)}`; + )} - ${this.getDisplayTextForMilitaryTime( + timeSlotInfo.timeSlot.endTime, + true + )}`; } } this.$refs.funnelFooter.updateButtonText(funnelFooterButtonText); @@ -386,13 +386,15 @@ export default { return dateObject.toLocaleDateString("en-us", { month: "short", day: "numeric" }); }, getDisplayTextForMilitaryTime(militaryTimeInput, shouldTrimMinutesIfEmpty = false) { - // Expected input: "HH:MM" + // 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; } + if (shouldTrimMinutesIfEmpty && minutes === "00") { return `${hours} ${meridianNotation}`; } else { @@ -405,10 +407,11 @@ export default { forwardButtonAction() { this.updateSupportingItems(); - // Remove the isPremiumAppointment flag to ensure it never gets into the store - delete this.selectedTimeSlot.isPremiumAppointment; - - this.dispatchStoreAction(this.storeActions.SAVE_SCHEDULE, this.selectedTimeSlot, false); + this.dispatchStoreAction( + this.storeActions.SAVE_SCHEDULE, + this.selectedTimeSlotInfo.timeSlot, + false + ); this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route); }, @@ -418,7 +421,7 @@ export default { // if we have a premium fee(early bird), then save/update supporting items if ( this.appointmentType === AppointmentTypeStrings.MOBILE && - this.selectedTimeSlot?.isPremiumAppointment + this.selectedTimeSlotInfo?.isPremiumAppointment ) { const earlyBirdIndex = supportingItems.findIndex( (item) => item.partType == PREMIUM_FEE_PART_TYPE @@ -461,18 +464,20 @@ export default { selectedDate(newValue, oldValue) { // Clear time slot selection if date selected changes if (newValue !== oldValue) { - this.selectedTimeSlot = { - date: null, - routeCode: null, - startTime: null, - endTime: null, - jobMaxMinutes: null, - jobMinMinutes: null, + this.selectedTimeSlotInfo = { + timeSlot: { + date: null, + routeCode: null, + startTime: null, + endTime: null, + jobMaxMinutes: null, + jobMinMinutes: null, + }, isPremiumAppointment: null, }; } }, - selectedTimeSlot(newValue) { + selectedTimeSlotInfo(newValue) { this.updateFooterButtonText(newValue); }, }, 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 79238f539..007987ba8 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,12 +47,12 @@ import buttonQuestion from "@/digital-components/button-question/button-question import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button"; // Helpers +import { deepClone } from "@/helpers/object-helper"; import { convertDateStringToDate, militaryToTwelveHourTime, getDisplayTextForDurationLength, } from "@/layouts/schedule/helpers/schedule-helper"; -import { deepClone } from "@/helpers/object-helper"; // Validation - TODO: Move this somewhere more global? import { defineRule, useField } from "vee-validate"; @@ -84,7 +84,20 @@ export default { name: "time-slot-modal-question", emits: ["update:modelValue"], props: { - modelValue: Object, + modelValue: { + type: Object, + default: () => ({ + timeSlot: { + routeCode: null, + date: null, + startTime: null, + endTime: null, + jobMaxMinutes: null, + jobMinMinutes: null, + }, + isPremiumAppointment: null, + }), + }, cmsWidgetName: String, mobileCmsWidgetName: String, mobilePremiumCmsWidgetName: String, @@ -148,18 +161,18 @@ export default { if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) { return null; } else if (this.appointmentType === AppointmentTypeStrings.MOBILE) { - appointmentTypeCmsWidgetName = this.selectedTimeSlotId?.includes( + appointmentTypeCmsWidgetName = this.selectedRouteCode?.includes( PREMIUM_TIME_SLOT_ID_FLAG ) ? this.mobilePremiumCmsWidgetName : this.mobileCmsWidgetName; } else { - if (!this.selectedTimeSlotId) { + if (!this.selectedRouteCode) { return null; } else { appointmentTypeCmsWidgetName = this.getRelevantDropOffCmsWidgetNameForSelectedTimeSlot( - this.selectedTimeSlotId, + this.selectedRouteCode, true ); } @@ -216,13 +229,13 @@ export default { }, disclaimerTextBlockCopy() { if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { - if (this.selectedTimeSlotId?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { + if (this.selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { if (this.isSameDay) { return this.sameDayDropOffDisclaimerText; } else { return this.dropoffDisclaimerText; } - } else if (this.selectedTimeSlotId?.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + } else if (this.selectedRouteCode?.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { return this.overnightDropOffDisclaimerText; } else { return null; @@ -265,9 +278,9 @@ export default { } else if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) { return this.inshopDurationText; } else { - if (this.selectedTimeSlotId?.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + if (this.selectedRouteCode?.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { return this.overnightDropoffDurationText; - } else if (this.selectedTimeSlotId?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { + } else if (this.selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { if (this.isSameDay) { return this.sameDayDropoffDurationText; } else { @@ -307,7 +320,9 @@ export default { } if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { - return this.getAvailableTimeSlotsForDropOff(this.timeSlotsForSelectedDate.timeSlots); + return this.getAvailableTimeSlotsForDropOff( + this.timeSlotsForSelectedDate.timeSlots + ); } else if (this.appointmentType === AppointmentTypeStrings.MOBILE) { return this.getAvailableTimeSlotsForMobile(this.timeSlotsForSelectedDate.timeSlots); } else { @@ -329,16 +344,19 @@ export default { this.$emit("time-slot-modal-closed"); }, async setSelectedTimeSlot() { - this.$emit("update:modelValue", this.getSelectedTimeSlotObject(this.selectedRouteCode)); + this.$emit( + "update:modelValue", + this.getSelectedTimeSlotInfoObject(this.selectedRouteCode) + ); this.closeModal(); }, getRelevantDropOffCmsWidgetNameForSelectedTimeSlot( - selectedTimeSlotId, + selectedRouteCode, isSameDayRelevant = false ) { - if (selectedTimeSlotId.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + if (selectedRouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { return this.overnightDropOffCmsWidgetName; - } else if (selectedTimeSlotId.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { + } else if (selectedRouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { return this.isSameDay && isSameDayRelevant ? this.sameDayDropOffCmsWidgetName : this.dropoffCmsWidgetName; @@ -399,7 +417,7 @@ export default { "+$" + this.getTotalLineItemPrice(this.premiumAppointmentFee).toFixed(2); return { - // Unique value is required for each and the premium appoinment shares a timeSlot ID + // Unique value is required for each and the premium appoinment shares an id value: this.addPremiumFlagToInput(timeSlotData.id), buttonLabel: this.premiumAppointmentButtonText, buttonLabelSubCopy: formattedPrice, @@ -409,59 +427,65 @@ export default { }; }, getSelectedRouteCode() { - if (!this.modelValue?.routeCode) { - return null; + let selectedRouteCode; + if (!this.modelValue?.timeSlot) { + selectedRouteCode = null; } if (this.modelValue?.isPremiumAppointment) { - return this.addPremiumFlagToInput(this.modelValue?.routeCode); + selectedRouteCode = this.addPremiumFlagToInput(this.modelValue?.timeSlot?.routeCode); } else { - return this.modelValue?.routeCode; + selectedRouteCode = this.modelValue?.timeSlot?.routeCode; } + + return selectedRouteCode; }, - autoSelectTimeSlotIfOnlyOneIsAvailable(newAvailableTimeSlotsValue) { - const numberOfOptions = newAvailableTimeSlotsValue?.length; + autoSelectTimeSlotIfOnlyOneIsAvailable() { + const numberOfOptions = this.availableTimeSlots?.length; if (numberOfOptions === 1) { - this.selectedRouteCode = newAvailableTimeSlotsValue[0].value; + this.selectedRouteCode = this.availableTimeSlots[0].value; } }, - addPremiumFlagToInput(timeSlotId) { - return (timeSlotId += PREMIUM_TIME_SLOT_ID_FLAG); + addPremiumFlagToInput(routeCode) { + return (routeCode += PREMIUM_TIME_SLOT_ID_FLAG); }, - removePremiumFlagFromInput(timeSlotId) { - return timeSlotId.replace(PREMIUM_TIME_SLOT_ID_FLAG, ""); + removePremiumFlagFromInput(routeCode) { + return routeCode.replace(PREMIUM_TIME_SLOT_ID_FLAG, ""); }, - getSelectedTimeSlotObject(timeSlotId) { - console.log(timeSlotId) - const timeSlotIdIncludesPremium = timeSlotId?.includes(PREMIUM_TIME_SLOT_ID_FLAG); - if (timeSlotIdIncludesPremium) { - timeSlotId = this.removePremiumFlagFromInput(timeSlotId); + getSelectedTimeSlotInfoObject(routeCode) { + const routeCodeIncludesPremium = routeCode?.includes(PREMIUM_TIME_SLOT_ID_FLAG); + if (routeCodeIncludesPremium) { + routeCode = this.removePremiumFlagFromInput(routeCode); } const timeSlot = this.timeSlotsForSelectedDate?.timeSlots?.find( - (timeSlot) => timeSlot.id == timeSlotId + (timeSlot) => timeSlot.id == routeCode ); if (timeSlot) { return { - date: this.timeSlotsForSelectedDate.date, - routeCode: timeSlot.id, - startTime: timeSlot.startTime, - endTime: timeSlot.endTime, - jobMaxMinutes: this.estimatedServiceMinutesMaximum.toString(), - jobMinMinutes: this.estimatedServiceMinutesMinimum.toString(), - isPremiumAppointment: timeSlotIdIncludesPremium ? true : false + timeSlot: { + date: this.timeSlotsForSelectedDate.date, + routeCode: timeSlot.id, + startTime: timeSlot.startTime, + endTime: timeSlot.endTime, + jobMaxMinutes: this.estimatedServiceMinutesMaximum.toString(), + jobMinMinutes: this.estimatedServiceMinutesMinimum.toString(), + }, + isPremiumAppointment: routeCodeIncludesPremium ? true : false, }; } return { - date: null, - startTime: null, - endTime: null, - routeCode: null, - jobMaxMinutes: null, - jobMinMinutes: null, - isPremiumAppointment: null + timeSlot: { + date: null, + startTime: null, + endTime: null, + routeCode: null, + jobMaxMinutes: null, + jobMinMinutes: null, + }, + isPremiumAppointment: null, }; }, }, @@ -474,12 +498,10 @@ export default { }, selectedDate: { handler() { - this.selectedTimeSlotId = null; + this.selectedRouteCode = null; + this.autoSelectTimeSlotIfOnlyOneIsAvailable(); }, }, - availableTimeSlots(newValue) { - this.autoSelectTimeSlotIfOnlyOneIsAvailable(newValue); - }, }, components: { modal,