diff --git a/src/digital-components/date-picker/date-picker.vue b/src/digital-components/date-picker/date-picker.vue index fefeb30ff..bc4d6318e 100644 --- a/src/digital-components/date-picker/date-picker.vue +++ b/src/digital-components/date-picker/date-picker.vue @@ -31,8 +31,8 @@
SaturdayS
initialViewEndDate) { // should part of 1st month be hidden? @@ -243,7 +288,7 @@ export default { } } - let myPromise = new Promise((resolve, reject) => { + const myPromise = new Promise((resolve, reject) => { const response = config.customSelectableDatesCallback( initialViewStartDate.toISOString().split("T")[0], initialViewEndDate.toISOString().split("T")[0], @@ -431,12 +476,6 @@ export default { "-" + forceTwoDigitString(i); - const thisDate = { - year: yearNum, - month: monthIndex, - date: i, - dateString: dateString, - }; if (offset === 0 && i === this.todayDateNum) { dayClasses += "current-day"; } @@ -457,11 +496,9 @@ export default { const dateObject = { dateNum: i, dayClasses: dayClasses, - inputValue: thisDate, + inputValue: dateString, isSelectable: - this.selectableDatesData.findIndex( - (date) => date.dateString === dateString - ) > -1 + this.selectableDatesData.findIndex((date) => date.date === dateString) > -1 ? true : false, }; @@ -510,8 +547,8 @@ export default { if (monthToShow) { // make new API call with this month's start and end dates await this.updateSelectableDates( - monthToShow.dates[monthStartDateNum].inputValue.dateString, - monthToShow.dates[monthToShow.dates.length - 1].inputValue.dateString + monthToShow.dates[monthStartDateNum].inputValue, + monthToShow.dates[monthToShow.dates.length - 1].inputValue ); this.isLoading = false; this.hideSomeDaysForInitialView = false; // if hid days on initial partial view, this will reveal those days @@ -531,13 +568,13 @@ export default { ); moreSelectableDates.days.forEach((selectableDate) => { const index = this.selectableDatesData.findIndex( - (obj) => obj.dateString === selectableDate.dateString + (dateObj) => dateObj.date === selectableDate.date ); - if (index === -1) this.selectableDatesData.push(selectableDate); + if (index === -1) this.selectableDatesData.push(selectableDate.date); this.months.forEach((month) => { - // TODO: avoid checking all calendar date; maybe only ones between monthStart and monthEnd as defined above? + // TODO: avoid checking all calendar dates; maybe only ones between monthStart and monthEnd as defined above? month.dates.forEach((date) => { - if (date.inputValue.dateString === selectableDate.dateString) { + if (date.inputValue === selectableDate.date) { date["isSelectable"] = true; } }); @@ -808,7 +845,6 @@ export default { .btn-link { font-weight: 500; text-underline-offset: 4px; - box-shadow: none !important; // TODO: FIX THIS position: absolute; top: 90%; } diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index db17d966f..cbfa07d33 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -73,7 +73,7 @@ import { getRouterLinkRouteFromCopy, getRouterLinkDisplayTextFromCopy, } from "@/helpers/cms-content-helper"; -import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "./constants/schedule-constants"; +import { AppointmentTypeStrings } from "./constants/schedule-constants"; import { errorMessages } from "@/constants/error-messages"; import { required } from "@/helpers/validation-rules"; import store from "@/store"; @@ -107,20 +107,7 @@ const getAvailableDates = async (startDate, endDate, appointmentType, providerNu ); } - const newShopTimeSlots = newTimeSlotsResponse.data; - return convertApiResponse(newShopTimeSlots); -}; -const convertApiResponse = (responseData) => { - // DATA CONVERSION - responseData?.days.forEach((date) => { - const dateString = date.date; - date.dateString = dateString; - const dateStringPieces = dateString.split("-"); - date.year = Number(dateStringPieces[0]); - date.month = Number(dateStringPieces[1]); - date.date = Number(dateStringPieces[2]); - }); - return responseData; + return newTimeSlotsResponse.data; }; export default { @@ -146,24 +133,24 @@ export default { customSelectableDatesCallback: getAvailableDates, }); - // Price EARLY BIRD pre-emptively to allow for asynchronous call to pricing - const pricingPromise = baseMixin.methods.dispatchStoreAction( - storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, - { - availableLineItems: [ - { - partNumber: PREMIUM_FEE_PART_TYPE, - partType: PREMIUM_FEE_PART_TYPE, - description: null, - }, - ], - }, - false - ); - const premiumFeePromise = baseMixin.methods.dispatchStoreAction( storeActions.GET_MOBILE_PREMIUM_FEE ); + + const premiumFeeWithPricePromise = premiumFeePromise.then((result) => { + if (result.data) { + return baseMixin.methods.dispatchStoreAction( + storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, + { + availableLineItems: [result.data], + }, + false + ); + } else { + return result.data; + } + }); + const alertReasonsPromise = locationAlerts.methods.loadInitialData( store.getters.order.serviceLocation.zipCodeCtu ); @@ -182,12 +169,8 @@ export default { promise: datePickerInitialDataPromise, }, { - resultKey: "premiumFee", - promise: premiumFeePromise, - }, - { - resultKey: "pricingResults", - promise: pricingPromise, + resultKey: "premiumFeeWithPrice", + promise: premiumFeeWithPricePromise, }, ]; @@ -199,9 +182,10 @@ export default { vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData); vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons); vm.selectableDatesData = resultMap.datePickerInitialData.initialShopTimeSlotsResponse; - if (resultMap.premiumFee) { - vm.mobilePremiumAppointmentFee = resultMap.pricingResults[0]; - } + vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice + ? resultMap.premiumFeeWithPrice[0] + : null; + vm.updateFooterButtonText(vm.selectedTimeSlotData); }); }, computed: { @@ -216,11 +200,11 @@ export default { return this.$store.getters.order.serviceLocation.appointmentType; }, timeSlotsForSelectedDate() { - if (this.selectedDate === null) { + if (!this.selectedDate) { return null; } return this.selectableDatesData.days?.find( - (selectableDate) => selectableDate.dateString === this.selectedDate.dateString + (selectableDate) => selectableDate.date === this.selectedDate ); }, appointmentDateAndTime() { @@ -230,10 +214,9 @@ export default { const timeSlotSelectedObject = this.getTimeSlotObjectFromTimeSlotId( this.selectedTimeSlotData.id ); - if (timeSlotSelectedObject) { return { - date: this.selectedDate.dateString, + date: this.selectedDate, startTime: timeSlotSelectedObject.startTime, endTime: timeSlotSelectedObject.endTime, routeCode: this.selectedTimeSlotData.id, @@ -275,7 +258,7 @@ export default { }, getTimeSlotObjectFromTimeSlotId(timeSlotId) { const timeSlots = this.selectableDatesData.days.find( - (selectableDate) => selectableDate.dateString === this.selectedDate.dateString + (selectableDate) => selectableDate.date === this.selectedDate ).timeSlots; return timeSlots.find((timeSlot) => timeSlot.id === timeSlotId); }, @@ -325,7 +308,7 @@ export default { }, convertSelectedDateToShortMonthAndDay(selectedDate) { // This conversion ensures we don't get get GMT induced date changes - const dateObject = new Date(`${selectedDate.dateString}T00:00:00`); + const dateObject = new Date(`${selectedDate}T00:00:00`); // Ex: April 25 return dateObject.toLocaleDateString("en-us", { month: "short", day: "numeric" }); }, @@ -365,7 +348,7 @@ export default { }; } }, - selectedTimeSlotData() { + selectedTimeSlotData(newValue) { this.updateFooterButtonText(this.selectedTimeSlotData); }, }, 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 62d052941..10640dfd9 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 @@ -78,13 +78,14 @@ export default { }, data() { return { - selectedTimeSlotId: null, + selectedTimeSlotId: this.modelValue.id, timeSlotModalListButton: timeSlotModalListButton, }; }, setup(props) { const { handleChange } = useField("time-slot-modal-question", props.validationRules); - + // Run validation on component load + handleChange(props.modelValue.id); return { handleChange, }; @@ -92,6 +93,11 @@ export default { watch: { modelValue() { // Run component validation that is used at parent level + if (this.modelValue.isPremiumAppointment) { + this.selectedTimeSlotId = this.addPremiumFlagToInput(this.modelValue.id); + } else { + this.selectedTimeSlotId = this.modelValue.id; + } this.handleChange(this.modelValue.id); }, availableTimeSlots(newValue) { @@ -162,7 +168,7 @@ export default { } // This conversion ensures we don't get get GMT induced date changes - const dateObject = new Date(`${this.dateAndTimeSlotData.dateString}T00:00:00`); + const dateObject = new Date(`${this.dateAndTimeSlotData.date}T00:00:00`); // Ex: Tuesday, April 22 return dateObject.toLocaleDateString("en-us", { weekday: "long", @@ -203,12 +209,6 @@ export default { }, // fires any time the modal is closed, AFTER "closeModal" fires if footer button is used onModalClosed() { - // Reset component state to parent's state - if (this.modelValue.isPremiumAppointment) { - this.selectedTimeSlotId = this.addPremiumFlagToInput(this.modelValue.id); - } else { - this.selectedTimeSlotId = this.modelValue.id; - } this.$emit("time-slot-modal-closed"); }, // Expected input: "HH:MM" diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 713cdb089..252eac529 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -142,7 +142,7 @@ export default { city: this.getServiceCityFromStore(), state: this.getServiceStateFromStore(), zipCode: this.getServiceZipCodeFromStore(), - isVehicleProtected: null, + isVehicleProtected: this.getIsVehicleProtectedFromStore(), isGlassServiceableInshop: null, isRecalibrationServiceableInshop: null, isGlassServiceableMobile: null, @@ -348,6 +348,9 @@ export default { getServiceZipCodeFromStore() { return store.getters.order.serviceLocation.zipCode; }, + getIsVehicleProtectedFromStore() { + return store.getters.order.serviceLocation.isVehicleProtected; + }, getSelectedAppointmentType() { return store.getters.order.serviceLocation.appointmentType; }, diff --git a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue index 6509c7d5c..f29ccf37b 100644 --- a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue +++ b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue @@ -192,7 +192,7 @@ export default { .button-auxillary-copy { box-sizing: border-box; justify-content: right; - line-height: 1.25rem !important; + line-height: 1.25rem; font-weight: 500; font-size: 0.75rem; align-items: center; @@ -205,7 +205,7 @@ export default { } .loader:after { - background-color: $gray-300 !important; + background-color: $gray-300; height: 1rem; width: 1rem; } @@ -221,7 +221,7 @@ export default { } &.gray { - color: $gray-600 !important; + color: $gray-600; background-color: $gray-100; padding-left: 0.125rem; padding-right: 0.125rem; diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index 2bc4cba7b..929c779af 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -280,7 +280,7 @@ export default { border-radius: 0.5rem; display: flex; flex-direction: row; - padding: 0.5rem 0.5rem 0.5rem 1.5rem !important; + padding: 0.5rem 0.5rem 0.5rem 1.5rem; gap: 0.25rem; .alert-heading { diff --git a/src/store/index.js b/src/store/index.js index 014ed71af..67917bf01 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -39,11 +39,13 @@ const getDefaultState = () => { }, serviceLocation: { address: null, + address2: null, city: null, state: null, zipCode: null, zipCodeCtu: null, appointmentType: null, + isVehicleProtected: null, provider: { providerNumber: null, address: { @@ -1190,7 +1192,6 @@ export const actions = { method: endpoints.GetShopTimeSlots.method, endpoint: endpoints.GetShopTimeSlots.url, payload: payload, - logApiCall: false, }); }, @@ -1242,7 +1243,6 @@ export const actions = { method: endpoints.GetMobileTimeSlots.method, endpoint: endpoints.GetMobileTimeSlots.url, payload: payload, - logApiCall: false, }); }, diff --git a/src/styles/common-styles.scss b/src/styles/common-styles.scss index 73845e5cc..f8e1c50f1 100644 --- a/src/styles/common-styles.scss +++ b/src/styles/common-styles.scss @@ -56,3 +56,9 @@ body { height: calc(100% - 72px); } } +//Disable scroll of main container when modal is open +.modal-open { + .page-container-grouped-styles { + overflow: hidden; + } +} diff --git a/src/styles/shared-input-button-styles.scss b/src/styles/shared-input-button-styles.scss index 9af066bb0..07329fc71 100644 --- a/src/styles/shared-input-button-styles.scss +++ b/src/styles/shared-input-button-styles.scss @@ -9,6 +9,7 @@ position: relative; z-index: 5; @include box-shadow-hover($blue-300); + border-radius: 0.5rem; } } } diff --git a/src/styles/ux-variables.scss b/src/styles/ux-variables.scss index 1e95a4052..976e8ed04 100644 --- a/src/styles/ux-variables.scss +++ b/src/styles/ux-variables.scss @@ -190,3 +190,6 @@ $alert-color-scale: 40%; // This affects all [Bootstrap] modals $modal-fade-transform: translate(0, 100%); $modal-backdrop-opacity: 0; + +//Disable default !important behavior +$enable-important-utilities: false; diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue index 7755249ab..ee8785022 100644 --- a/src/ux-components/list-card/list-card.vue +++ b/src/ux-components/list-card/list-card.vue @@ -94,7 +94,7 @@ export default { + .list-card-content { outline: none; - display: block; + display: flex; position: relative; p {