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
This commit is contained in:
Scott Kiener 2025-07-16 10:24:23 -04:00
parent 141ebc33f5
commit c1f7f7f734
6 changed files with 44 additions and 104 deletions

View file

@ -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,
};
},

View file

@ -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;

View file

@ -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,
};
},

View file

@ -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,

View file

@ -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,
};
});

View file

@ -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,
};
},