Final review of Scheduling Page

Refactor scheduling.vue state to colocate providers with their time slots

Replace parallel inShopProviders/inshopTimeSlots arrays with a single
inShopProvidersAndTimeslots array of { provider, timeSlots } objects, and
combine mobileTimeSlots/mobileProviderNumber into a single
mobileProviderAndTimeSlot object. Also extract SCHEDULE_FETCH_DAYS constant
to replace the magic number 14
add JSDoc to toDateString, and remove the
unused inShopProviderNumber state.
This commit is contained in:
scottkiener-at-safelite 2026-05-06 12:45:48 -04:00
parent 9dbcf1c93d
commit bf38d11bca

View file

@ -50,12 +50,19 @@ import {
} from "@/helpers/page-prerequisites-helper.js";
import { debugLog } from "@/helpers/debug-log-helper";
/**
* Returns a YYYY-MM-DD date string offset by the given number of days from a base date.
* @param {number} offsetDays - Number of days to offset (positive or negative).
* @param {Date} base - The starting date (defaults to today).
*/
function toDateString(offsetDays, base = new Date()) {
const d = new Date(base);
d.setDate(d.getDate() + offsetDays);
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}
const SCHEDULE_FETCH_DAYS = 15;
export default {
name: "scheduling",
async beforeRouteEnter(to, from, next) {
@ -65,29 +72,31 @@ export default {
payload: { serviceZipCode },
pageNameToLog: to.name,
});
// Get the first 3 providers from the shopProviderData
const providers = shopProviderData?.data?.shopProviders?.slice(0, 3) ?? [];
const mobileProviderNumber = shopProviderData?.data?.mobileProviderNumber ?? null;
const startDate = toDateString(0);
const endDate = toDateString(14);
const endDate = toDateString(SCHEDULE_FETCH_DAYS - 1);
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: fetchCmsContentForPage(to.name),
},
...providers.map((p, i) => ({
...providers.map((provider, i) => ({
resultKey: `inshopTimeSlots_${i}`,
promise: store.dispatch("getShopTimeSlots", {
payload: {
startDate,
endDate,
shopAppointmentType: "InshopOrDropoff",
providerNumber: p.providerNumber,
providerNumber: provider.providerNumber,
},
pageNameToLog: to.name,
}),
})),
// Get the mobile time slots if a mobile provider number is available
...(mobileProviderNumber
? [
{
@ -103,11 +112,13 @@ export default {
const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.inShopProviders = providers;
vm.inshopTimeSlots = providers.map((_, i) => resultMap[`inshopTimeSlots_${i}`] ?? null);
vm.mobileTimeSlots = resultMap.mobileTimeSlots ?? null;
vm.inShopProviderNumber = providers[0]?.providerNumber ?? null;
vm.mobileProviderNumber = mobileProviderNumber;
vm.inShopProvidersAndTimeslots = providers.map((provider, i) => ({
provider,
timeSlots: resultMap[`inshopTimeSlots_${i}`] ?? null,
}));
vm.mobileProviderAndTimeSlot = mobileProviderNumber
? { providerNumber: mobileProviderNumber, timeSlots: resultMap.mobileTimeSlots ?? null }
: null;
});
},
computed: {
@ -115,10 +126,10 @@ export default {
return this.getCmsContent("ServiceLocationText", "Text");
},
availableDates() {
const inshopDates = this.inshopTimeSlots.flatMap((ts) =>
(ts?.days ?? []).map((d) => d.date)
const inshopDates = this.inShopProvidersAndTimeslots.flatMap(({ timeSlots }) =>
(timeSlots?.days ?? []).map((d) => d.date)
);
const mobileDates = (this.mobileTimeSlots?.days ?? []).map((d) => d.date);
const mobileDates = (this.mobileProviderAndTimeSlot?.timeSlots?.days ?? []).map((d) => d.date);
return [...new Set([...inshopDates, ...mobileDates])].sort();
},
},
@ -127,12 +138,9 @@ export default {
selectedDate: null,
isLoadingDates: false,
datePickerStartDate: toDateString(0),
datePickerEndDate: toDateString(14),
inShopProviders: [],
inshopTimeSlots: [],
mobileTimeSlots: null,
inShopProviderNumber: null,
mobileProviderNumber: null,
datePickerEndDate: toDateString(SCHEDULE_FETCH_DAYS - 1),
inShopProvidersAndTimeslots: [],
mobileProviderAndTimeSlot: null,
};
},
methods: {
@ -194,7 +202,7 @@ export default {
this.$refs.loadingModal.hideModal();
},
forwardButtonAction() {
const appointmentType = store.getters.order.serviceLocation.appointmentType;
const appointmentType = store.getters.order.serviceLocation.appointmentType; // TODO: remove this once we have a proper appointment type
if (appointmentType === AppointmentTypeStrings.MOBILE) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_MOBILE_SERVICE,