diff --git a/src/digital-components/date-picker/date-picker.vue b/src/digital-components/date-picker/date-picker.vue index 1a3080286..bfaeac476 100644 --- a/src/digital-components/date-picker/date-picker.vue +++ b/src/digital-components/date-picker/date-picker.vue @@ -2,16 +2,6 @@
-
- - -
-
Select a day and time
View more dates - + :selectedDate="selectedDate" // used in date-picker + :appointmentType="appointmentType" // used in date-picker for duration + :premiumAppointmentFee="premiumAppointmentFee" // Removed from date-picker + :displayWaitList="displayWaitList" // Removed from date-picker + :timeSlotsForSelectedDate="timeSlotsForSelectedDate" // Removed from date-picker (but it had a null check for is-same-day) + :estimatedServiceMinutesMinimum="estimatedServiceMinutesMinimum" // used in date-picker for duration + :estimatedServiceMinutesMaximum="estimatedServiceMinutesMaximum" // used in date-picker for duration + @waitListRequested="handleWaitListRequested" // removed, it's a pass-through /> -->
diff --git a/src/layouts/schedule/duration-text-block/duration-text-block.vue b/src/layouts/schedule/duration-text-block/duration-text-block.vue new file mode 100644 index 000000000..4fd170680 --- /dev/null +++ b/src/layouts/schedule/duration-text-block/duration-text-block.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index e8dd8250c..a97f0f125 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -113,6 +113,15 @@
+
+ + +
+ slot.id == timeSlotObj.routeCode + ); + + this.selectedTimeSlotInfo = { + timeSlot: { + date: this.timeSlotsForSelectedDate.date, + routeCode: timeSlotObj.routeCode, + startTime: timeSlot.startTime, + endTime: timeSlot.endTime, + jobMaxMinutes: this.estimatedServiceMinutesMaximum.toString(), + jobMinMinutes: this.estimatedServiceMinutesMinimum.toString(), + }, + isPremiumAppointment: timeSlotObj.isPremiumAppointment ? true : false, + }; + if ( this.appointmentType !== AppointmentTypeStrings.MOBILE && this.appointmentType !== null ) { // update apptType based on routeCode to determine if it should be dropoff or inshop debugLog(`Updating appointment type based on route code.`); - debugLog(`Route code =`, timeSlotObj.timeSlot.routeCode); - debugLog( - `Parsed type = `, - this.getInShopOrDropOffApptType(timeSlotObj.timeSlot.routeCode) - ); - this.appointmentType = this.getInShopOrDropOffApptType( - timeSlotObj.timeSlot.routeCode - ); + debugLog(`Route code =`, timeSlotObj.routeCode); + debugLog(`Parsed type = `, this.getInShopOrDropOffApptType(timeSlotObj.routeCode)); + this.appointmentType = this.getInShopOrDropOffApptType(timeSlotObj.routeCode); } }, getInShopOrDropOffApptType(routeCode) { @@ -1724,6 +1800,7 @@ export default { } }, selectedTimeSlotInfo(newValue) { + console.log("heard a change on selectedTimeslotInfo", newValue); this.updateFooterButtonText(newValue); }, }, @@ -1736,10 +1813,13 @@ export default { datePicker, locationAlerts, textBlock, + timeSlotQuestion, + alert, serviceZipModalQuestion, appointmentTypeQuestion, contentGroupModal, + durationTextBlock, shopLocation, mobileFeeWaiverAlert, }, diff --git a/src/layouts/schedule/time-slot-question/time-slot-question.vue b/src/layouts/schedule/time-slot-question/time-slot-question.vue index 900db972d..18f3b77d2 100644 --- a/src/layouts/schedule/time-slot-question/time-slot-question.vue +++ b/src/layouts/schedule/time-slot-question/time-slot-question.vue @@ -3,6 +3,7 @@
@@ -92,7 +94,6 @@ import { isDropOffRouteCode, militaryToTwelveHourTime, } from "@/layouts/schedule/helpers/schedule-helper"; -import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper"; // Validation import { defineRule, useField } from "vee-validate"; @@ -116,23 +117,8 @@ defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED)); export default { name: "time-slot-question", - emits: ["update:modelValue", "TimeSlotSelected", "click-event"], + emits: ["update:modelValue", "time-slot-selection-changed"], props: { - 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, dropoffCmsWidgetName: String, @@ -142,21 +128,23 @@ export default { appointmentType: String, timeSlotsForSelectedDate: Object, premiumAppointmentFee: Object, - estimatedServiceMinutesMinimum: Number, - estimatedServiceMinutesMaximum: Number, validationRules: String, customComponentId: String, - selectedDate: String, + isSameDay: Boolean, displayWaitList: Boolean, + selectedRouteCodeData: Object, }, data() { return { - selectedRouteCode: null, timeSlotModalListButton: timeSlotModalListButton, - selectedAnswerForDropOffOrInshop: null, selectedAnswerForTimeSlots: null, + selectedAnswerForDropOffOrInshop: null, }; }, + mounted() { + this.updateDropoffAndTimeSlotAnswersFromSelectedRouteCodeData(this.selectedRouteCodeData); + this.autoSelectTimeSlotIfOnlyOneIsAvailable(); + }, setup(props) { const uuid = uuidv4(); const componentId = !props.customComponentId @@ -186,20 +174,33 @@ export default { errors, }; }, + watch: { + waitListRequested(newVal) { + if (newVal) { + this.$nextTick(() => { + this.scrollToSuccessMessage(); + }); + } + }, + selectedRouteCodeData(newValue) { + this.updateDropoffAndTimeSlotAnswersFromSelectedRouteCodeData(newValue); + }, + timeSlotsForSelectedDate() { + this.selectedAnswerForDropOffOrInshop = null; + this.selectedAnswerForTimeSlots = null; + this.autoSelectTimeSlotIfOnlyOneIsAvailable(); + }, + }, computed: { supplementalInformationBlock() { let appointmentTypeCmsWidgetName; if ( - this.selectedDate == null || this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF || this.appointmentType === AppointmentTypeStrings.IN_SHOP || this.appointmentType === AppointmentTypeStrings.DROP_OFF || !this.availableTimeSlots ) { - if (!this.selectedAnswerForTimeSlots && !this.selectedAnswerForDropOffOrInshop) { - this.autoSelectTimeSlotIfOnlyOneIsAvailable(); - } return null; // This is planned to be used again for drop-off // Wrote this to be ready for that eventuality, is untested and no HTML work done yet @@ -214,11 +215,7 @@ export default { // ); // } } else { - if (!this.selectedAnswerForTimeSlots && this.selectedRouteCode) { - // Clearing selectedRouteCode if no time slot is selected - this.resetSelectedTimeSlot(); - } - appointmentTypeCmsWidgetName = this.selectedRouteCode?.includes( + appointmentTypeCmsWidgetName = this.selectedRouteCodeData?.routeCode?.includes( PREMIUM_TIME_SLOT_ID_FLAG ) ? this.mobilePremiumCmsWidgetName @@ -299,13 +296,6 @@ export default { // return null; // } // }, - isSameDay() { - if (!this.timeSlotsForSelectedDate) { - return false; - } - const todaysDate = new Date().toISOString().split("T")[0]; - return this.selectedDate === todaysDate; - }, availableTimeSlots() { if (!this.timeSlotsForSelectedDate) { return null; @@ -407,29 +397,60 @@ export default { }, }, methods: { - initializeComponent() { - this.setSelectedRouteCodeFromParent(); - }, - async setSelectedTimeSlot() { - this.selectedRouteCode = - this.selectedAnswerForTimeSlots || this.selectedAnswerForDropOffOrInshop; - this.$emit( - "update:modelValue", - this.getSelectedTimeSlotInfoObject(this.selectedRouteCode) - ); - }, - getRelevantDropOffCmsWidgetNameForSelectedTimeSlot( - selectedRouteCode, - isSameDayRelevant = false - ) { - if (selectedRouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { - return this.overnightDropOffCmsWidgetName; - } else if (selectedRouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { - return this.isSameDay && isSameDayRelevant - ? this.sameDayDropOffCmsWidgetName - : this.dropoffCmsWidgetName; + updateDropoffAndTimeSlotAnswersFromSelectedRouteCodeData(selectedRouteCodeData) { + if (selectedRouteCodeData?.routeCode) { + let routeCode = selectedRouteCodeData.routeCode; + if (isDropOffRouteCode(routeCode)) { + this.selectedAnswerForDropOffOrInshop = routeCode; + } else { + this.selectedAnswerForDropOffOrInshop = PICK_A_TIME_BUTTON_VALUE; + if (this.selectedRouteCodeData.isPremiumAppointment) { + routeCode = this.addPremiumFlagToInput(routeCode); + } + this.selectedAnswerForTimeSlots = routeCode; + } + } else { + this.selectedAnswerForDropOffOrInshop = null; + this.selectedAnswerForTimeSlots = null; } }, + dropOffSelectionChanged(newValue) { + let newSelectedRouteCodeData = null; + if (newValue && newValue != PICK_A_TIME_BUTTON_VALUE) { + newSelectedRouteCodeData = { + routeCode: newValue, + isPremiumAppointment: false, + }; + } + this.selectedAnswerForTimeSlots = null; + this.$emit("time-slot-selection-changed", newSelectedRouteCodeData); + }, + timeSlotSelectionChanged(newValue) { + if (newValue) { + let routeCode = newValue; + let isPremiumAppointment = routeCode.includes(PREMIUM_TIME_SLOT_ID_FLAG); + if (isPremiumAppointment) { + routeCode = this.removePremiumFlagFromInput(routeCode); + } + this.$emit("time-slot-selection-changed", { + routeCode: routeCode, + isPremiumAppointment: isPremiumAppointment, + }); + } + }, + // This is unused but planned to be used again + // getRelevantDropOffCmsWidgetNameForSelectedTimeSlot( + // selectedRouteCode, + // isSameDayRelevant = false + // ) { + // if (selectedRouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + // return this.overnightDropOffCmsWidgetName; + // } else if (selectedRouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { + // return this.isSameDay && isSameDayRelevant + // ? this.sameDayDropOffCmsWidgetName + // : this.dropoffCmsWidgetName; + // } + // }, getAvailableTimeSlotsForInshop(timeSlotsForSelectedDate) { return timeSlotsForSelectedDate .filter((timeSlot) => { @@ -463,8 +484,6 @@ export default { ); } - this.resetSelectedTimeSlotIfDateChange(timeSlotsForSelectedDate); - return availableTimeSlots; }, getPremiumAppointmentTimeSlot(timeSlotData) { @@ -480,35 +499,19 @@ export default { }, }; }, - setSelectedRouteCodeFromParent() { - if (!this.modelValue?.timeSlot?.routeCode) { - return; - } - const routeCodeFromParent = this.modelValue.timeSlot.routeCode; - if (this.modelValue?.isPremiumAppointment) { - // Mobile Only - this.selectedAnswerForTimeSlots = this.addPremiumFlagToInput(routeCodeFromParent); - } else { - if (isDropOffRouteCode(routeCodeFromParent)) { - this.selectedAnswerForDropOffOrInshop = routeCodeFromParent; - } else { - this.selectedAnswerForDropOffOrInshop = PICK_A_TIME_BUTTON_VALUE; - this.selectedAnswerForTimeSlots = routeCodeFromParent; - } - } - }, getWaitListRequestedFromStore() { return store.getters.order.customer?.waitListRequested; }, autoSelectTimeSlotIfOnlyOneIsAvailable() { const numberOfOptions = this.timeSlotsForSelectedDate?.timeSlots?.length; - if (this.appointmentType && numberOfOptions === 1) { + if (numberOfOptions === 1) { if (this.availableTimeSlots.length > 0) { + // this.availableTimeSlots only returns mobile/inshop slots so we know + // the only available slot is not dropOFf this.selectedAnswerForTimeSlots = this.availableTimeSlots[0].value; } else { this.selectedAnswerForDropOffOrInshop = this.answersForDropOffQuestion[0].value; } - this.setSelectedTimeSlot(); } }, addPremiumFlagToInput(routeCode) { @@ -517,41 +520,6 @@ export default { removePremiumFlagFromInput(routeCode) { return routeCode.replace(PREMIUM_TIME_SLOT_ID_FLAG, ""); }, - getSelectedTimeSlotInfoObject(routeCode) { - const routeCodeIncludesPremium = routeCode?.includes(PREMIUM_TIME_SLOT_ID_FLAG); - if (routeCodeIncludesPremium) { - routeCode = this.removePremiumFlagFromInput(routeCode); - } - const timeSlot = this.timeSlotsForSelectedDate?.timeSlots?.find( - (slot) => slot.id == routeCode - ); - - if (timeSlot) { - return { - timeSlot: { - date: this.timeSlotsForSelectedDate.date, - routeCode: timeSlot.id, - startTime: timeSlot.startTime, - endTime: timeSlot.endTime, - jobMaxMinutes: this.estimatedServiceMinutesMaximum?.toString() || null, - jobMinMinutes: this.estimatedServiceMinutesMinimum?.toString() || null, - }, - isPremiumAppointment: routeCodeIncludesPremium ? true : false, - }; - } - - return { - timeSlot: { - date: null, - routeCode: null, - startTime: null, - endTime: null, - jobMaxMinutes: null, - jobMinMinutes: null, - }, - isPremiumAppointment: null, - }; - }, waitListChecked(event) { this.$emit("waitListRequested", event.target.checked); }, @@ -561,65 +529,6 @@ export default { successMessageElement.scrollIntoView({ behavior: "smooth" }); } }, - resetSelectedTimeSlotIfDateChange(timeSlotsForSelectedDate) { - if (this.selectedRouteCode) { - const selectedRouteCodeString = this.selectedRouteCode.replace( - PREMIUM_TIME_SLOT_ID_FLAG, - "" - ); - const matchingTimeSlot = timeSlotsForSelectedDate.find((slot) => { - return slot.id === selectedRouteCodeString; - }); - if (!matchingTimeSlot) { - this.resetSelectedTimeSlot(); - } - } - }, - resetSelectedTimeSlot() { - this.selectedRouteCode = null; - }, - }, - watch: { - waitListRequested(newVal) { - if (newVal) { - this.$nextTick(() => { - this.scrollToSuccessMessage(); - }); - } - }, - modelValue: { - handler(newValue) { - this.handleChange(newValue); - }, - deep: true, - }, - selectedDate: { - handler() { - this.resetSelectedTimeSlot(); - this.selectedAnswerForDropOffOrInshop = null; - this.selectedAnswerForTimeSlots = null; - this.autoSelectTimeSlotIfOnlyOneIsAvailable(); - }, - }, - selectedRouteCode(newValue) { - if (newValue) { - this.setSelectedTimeSlot(); - } - }, - selectedAnswerForDropOffOrInshop(newValue) { - if (newValue == PICK_A_TIME_BUTTON_VALUE) { - this.selectedRouteCode = null; - this.setSelectedTimeSlot(); - } else { - this.selectedAnswerForTimeSlots = null; - this.selectedRouteCode = newValue; - } - }, - selectedAnswerForTimeSlots(newValue) { - if (newValue) { - this.selectedRouteCode = newValue; - } - }, }, components: { textBlock,