From c1f7f7f73446751558de9e8565828d8582c3798d Mon Sep 17 00:00:00 2001 From: Scott Kiener Date: Wed, 16 Jul 2025 10:24:23 -0400 Subject: [PATCH] Refactored shop-list-button to no longer need so many props Everyone single usage did the same thing, reduced boilerplate by moving it to the component itself --- src/layouts/schedule/schedule.vue | 11 ----- .../service-location-helper.js | 29 ------------ .../service-location/service-location.vue | 13 ------ .../shop-list-button/shop-list-button.vue | 39 ++++++++++++++-- .../shop-question/shop-question-popup.vue | 44 ++++--------------- .../shop-question/shop-question.vue | 12 ----- 6 files changed, 44 insertions(+), 104 deletions(-) diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 0041e553c..c3f3d0657 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -166,7 +166,6 @@ import shopQuestion from "@/layouts/service-location/shop-question/shop-question import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup"; import buttonQuestion from "@/digital-components/button-question/button-question.vue"; import shopListButton from "@/layouts/service-location/shop-question/shop-list-button/shop-list-button"; -import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper"; import funnelHeader from "@/fmg-components/funnel-header/funnel-header"; import navbar from "@/fmg-components/nav-bar/nav-bar"; @@ -805,17 +804,7 @@ export default { return this.displayNoShopsAlert || !this.isMobileAddressValid; }, additionalButtonData() { - const startDate = new Date(); - const endDate = new Date(); - endDate.setDate(startDate.getDate() + 6); - - const formattedStartDate = startDate.toISOString().split("T")[0]; - const formattedEndDate = endDate.toISOString().split("T")[0]; - return { - availabilityRatingCallback: getAvailabilityRating, - startDate: formattedStartDate, - endDate: formattedEndDate, shopAppointmentType: this.appointmentType, }; }, diff --git a/src/layouts/service-location/helpers/service-location-helper/service-location-helper.js b/src/layouts/service-location/helpers/service-location-helper/service-location-helper.js index a85b180f9..3b81966cc 100644 --- a/src/layouts/service-location/helpers/service-location-helper/service-location-helper.js +++ b/src/layouts/service-location/helpers/service-location-helper/service-location-helper.js @@ -122,35 +122,6 @@ export async function getShopProviderData(serviceZipCode) { ); } -export async function getAvailabilityRating( - startDate, - endDate, - shopAppointmentType, - providerNumber -) { - // For a given shop provider number and date range, get the appointment time slots available - const shopTimeSlots = await baseMixin.methods.dispatchStoreActionWithLogging( - storeActions.GET_SHOP_TIME_SLOTS, - { - providerNumber: providerNumber, - startDate: startDate, - endDate: endDate, - shopAppointmentType: shopAppointmentType, - }, - "service-location", - false - ); - - const numberOfDaysToEvaluate = 2; - const isGoodAvailability = - shopTimeSlots.data.days.filter((x) => x.timeSlots.length > 0).length >= - numberOfDaysToEvaluate; - - const shopStatus = isGoodAvailability ? "high" : "low"; - - return shopStatus; -} - export async function getClosestApplicableShops(serviceZipCode, carId, pageNameToLog) { if (!serviceZipCode) { return null; diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 329b99840..38a61f222 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -148,11 +148,9 @@ import alert from "@/ux-components/alert/alert"; import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question"; import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question"; -import shopQuestion from "@/layouts/service-location/shop-question/shop-question"; import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup"; import buttonQuestion from "@/digital-components/button-question/button-question.vue"; import shopListButton from "@/layouts/service-location/shop-question/shop-list-button/shop-list-button"; -import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper"; import funnelHeader from "@/fmg-components/funnel-header/funnel-header"; import navbar from "@/fmg-components/nav-bar/nav-bar"; @@ -163,7 +161,6 @@ import contentGroupModal from "@/fmg-components/content-group-modal/content-grou import textBlock from "@/digital-components/text-block/text-block"; // Supporting files -import baseMixin from "@/mixins/base-mixin.js"; import experimentMixin from "@/mixins/experiment-mixin.js"; import { experimentSettings } from "@/constants/experiments"; import { AppointmentTypeStrings } from "@/constants/schedule-constants"; @@ -450,17 +447,7 @@ export default { return this.displayNoShopsAlert || !this.isMobileAddressValid; }, additionalButtonData() { - const startDate = new Date(); - const endDate = new Date(); - endDate.setDate(startDate.getDate() + 6); - - const formattedStartDate = startDate.toISOString().split("T")[0]; - const formattedEndDate = endDate.toISOString().split("T")[0]; - return { - availabilityRatingCallback: getAvailabilityRating, - startDate: formattedStartDate, - endDate: formattedEndDate, shopAppointmentType: this.selectedAppointmentType, }; }, 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 20accf43b..f44a4156a 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 @@ -58,12 +58,15 @@ export default { beforeMount() { if (this.displayAvailabilityIndicators) { this.displayLoader(); - const startDate = this.additionalButtonData.startDate; - const endDate = this.additionalButtonData.endDate; + const startDate = new Date(); + const endDate = new Date(); + endDate.setDate(startDate.getDate() + 6); + const formattedStartDate = startDate.toISOString().split("T")[0]; + const formattedEndDate = endDate.toISOString().split("T")[0]; + const shopAppointmentType = this.additionalButtonData.shopAppointmentType; - this.additionalButtonData - .availabilityRatingCallback(startDate, endDate, shopAppointmentType, this.value) + this.getAvailabilityRating(formattedStartDate, formattedEndDate, shopAppointmentType, this.value) .then((data) => { this.availabilityRating = data; }); @@ -103,6 +106,34 @@ export default { displayLoader() { this.isLoaderDisplayed = true; }, + async getAvailabilityRating( + startDate, + endDate, + shopAppointmentType, + providerNumber + ) { + // For a given shop provider number and date range, get the appointment time slots available + const shopTimeSlots = await this.dispatchStoreActionWithLogging( + this.storeActions.GET_SHOP_TIME_SLOTS, + { + providerNumber: providerNumber, + startDate: startDate, + endDate: endDate, + shopAppointmentType: shopAppointmentType, + }, + "service-location", + false + ); + + const numberOfDaysToEvaluate = 2; + const isGoodAvailability = + shopTimeSlots.data.days.filter((x) => x.timeSlots.length > 0).length >= + numberOfDaysToEvaluate; + + const shopStatus = isGoodAvailability ? "high" : "low"; + + return shopStatus; + }, }, components: { loader, diff --git a/src/layouts/service-location/shop-question/shop-question-popup.vue b/src/layouts/service-location/shop-question/shop-question-popup.vue index 6396ce401..c6b980069 100644 --- a/src/layouts/service-location/shop-question/shop-question-popup.vue +++ b/src/layouts/service-location/shop-question/shop-question-popup.vue @@ -90,9 +90,6 @@ import { required } from "@/helpers/validation-rules"; import { errorMessages } from "@/constants/error-messages"; import baseMixin from "@/mixins/base-mixin.js"; -import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper"; - -import { Provider } from "@/layouts/service-location/classes/provider"; import { AppointmentTypeStrings } from "@/constants/schedule-constants"; import { @@ -115,7 +112,7 @@ export default { answers: [], shopListButton: shopListButton, shopIndex: 0, - localShopProviderData: this.shopProviderData, // Why does parent manage this sometimes, but not all of the time + localShopProviderData: this.shopProviderData, // Why does parent manage this sometimes, but not all of the time A: to prevent another call to get providers on initial load selectedProviderNumber: null, // Revisit this, maybe not too hard displayInvalidZipAlert: false, // part of big refactor of asyn calls displayNoShopsAlert: false, // part of big refactor of asyn calls @@ -139,27 +136,20 @@ export default { modalHeaderText() { return this.getCmsContent("ShopQuestionWidget", "QuestionText"); }, - shopProviders() { - return this.localShopProviderData?.shopProviders ?? []; - }, modalFooterText() { return this.getCmsContent("SaveLocationWidget", "Text"); }, + showMoreShopsLinkText() { + return this.getCmsContent("ShowMoreShopsLinkWidget", "Text"); + }, modal() { return this.$refs.shopQuestionModal; }, + shopProviders() { + return this.localShopProviderData?.shopProviders ?? []; + }, additionalButtonData() { - const startDate = new Date(); - const endDate = new Date(); - endDate.setDate(startDate.getDate() + 6); - - const formattedStartDate = startDate.toISOString().split("T")[0]; - const formattedEndDate = endDate.toISOString().split("T")[0]; - return { - availabilityRatingCallback: getAvailabilityRating, - startDate: formattedStartDate, - endDate: formattedEndDate, // Used for availability indicators, could be refactored out of any availability indicator // logic if/when we are sure we'll never have separate drop off/ in shop logic shopAppointmentType: AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF, @@ -170,9 +160,7 @@ export default { return false; return this.shopIndex < this.shopProviders.length; }, - showMoreShopsLinkText() { - return this.getCmsContent("ShowMoreShopsLinkWidget", "Text"); - }, + }, methods: { openModal(event) { @@ -363,25 +351,11 @@ export default { const zipCode = shopProvider.address.zipCode; const distanceInMiles = Math.round(shopProvider.distanceInMiles * 2) / 2; - const startDate = new Date(); - const endDate = new Date(); - endDate.setDate(startDate.getDate() + 6); - - const formattedStartDate = startDate.toISOString().split("T")[0]; - const formattedEndDate = endDate.toISOString().split("T")[0]; - return { buttonLabel: city, buttonLabelSubCopy: `${distanceInMiles} mi`, buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`, - additionalButtonData: { - availabilityRatingCallback: getAvailabilityRating, - startDate: formattedStartDate, - endDate: formattedEndDate, - // Used for availability indicators, could be refactored out of any availability indicator - // logic if/when we are sure we'll never have separate drop off/ in shop logic - shopAppointmentType: AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF, - }, + additionalButtonData: this.additionalButtonData, value: shopProvider.providerNumber, }; }); diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index 7191a1f07..7ea98555f 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -49,8 +49,6 @@ import { errorMessages } from "@/constants/error-messages"; import baseMixin from "@/mixins/base-mixin.js"; import { nextTick } from "vue"; -import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper"; - import { Provider } from "@/layouts/service-location/classes/provider"; import { AppointmentTypeStrings } from "@/constants/schedule-constants"; @@ -109,17 +107,7 @@ export default { return this.getCmsContent("ShowMoreShopsLinkWidget", "Text"); }, additionalButtonData() { - const startDate = new Date(); - const endDate = new Date(); - endDate.setDate(startDate.getDate() + 6); - - const formattedStartDate = startDate.toISOString().split("T")[0]; - const formattedEndDate = endDate.toISOString().split("T")[0]; - return { - availabilityRatingCallback: getAvailabilityRating, - startDate: formattedStartDate, - endDate: formattedEndDate, shopAppointmentType: this.selectedAppointmentType, }; },