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:
parent
9dbcf1c93d
commit
bf38d11bca
1 changed files with 26 additions and 18 deletions
|
|
@ -50,12 +50,19 @@ import {
|
||||||
} from "@/helpers/page-prerequisites-helper.js";
|
} from "@/helpers/page-prerequisites-helper.js";
|
||||||
import { debugLog } from "@/helpers/debug-log-helper";
|
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()) {
|
function toDateString(offsetDays, base = new Date()) {
|
||||||
const d = new Date(base);
|
const d = new Date(base);
|
||||||
d.setDate(d.getDate() + offsetDays);
|
d.setDate(d.getDate() + offsetDays);
|
||||||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SCHEDULE_FETCH_DAYS = 15;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "scheduling",
|
name: "scheduling",
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
@ -65,29 +72,31 @@ export default {
|
||||||
payload: { serviceZipCode },
|
payload: { serviceZipCode },
|
||||||
pageNameToLog: to.name,
|
pageNameToLog: to.name,
|
||||||
});
|
});
|
||||||
|
// Get the first 3 providers from the shopProviderData
|
||||||
const providers = shopProviderData?.data?.shopProviders?.slice(0, 3) ?? [];
|
const providers = shopProviderData?.data?.shopProviders?.slice(0, 3) ?? [];
|
||||||
const mobileProviderNumber = shopProviderData?.data?.mobileProviderNumber ?? null;
|
const mobileProviderNumber = shopProviderData?.data?.mobileProviderNumber ?? null;
|
||||||
|
|
||||||
const startDate = toDateString(0);
|
const startDate = toDateString(0);
|
||||||
const endDate = toDateString(14);
|
const endDate = toDateString(SCHEDULE_FETCH_DAYS - 1);
|
||||||
|
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
resultKey: "cmsContent",
|
resultKey: "cmsContent",
|
||||||
promise: fetchCmsContentForPage(to.name),
|
promise: fetchCmsContentForPage(to.name),
|
||||||
},
|
},
|
||||||
...providers.map((p, i) => ({
|
...providers.map((provider, i) => ({
|
||||||
resultKey: `inshopTimeSlots_${i}`,
|
resultKey: `inshopTimeSlots_${i}`,
|
||||||
promise: store.dispatch("getShopTimeSlots", {
|
promise: store.dispatch("getShopTimeSlots", {
|
||||||
payload: {
|
payload: {
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
shopAppointmentType: "InshopOrDropoff",
|
shopAppointmentType: "InshopOrDropoff",
|
||||||
providerNumber: p.providerNumber,
|
providerNumber: provider.providerNumber,
|
||||||
},
|
},
|
||||||
pageNameToLog: to.name,
|
pageNameToLog: to.name,
|
||||||
}),
|
}),
|
||||||
})),
|
})),
|
||||||
|
// Get the mobile time slots if a mobile provider number is available
|
||||||
...(mobileProviderNumber
|
...(mobileProviderNumber
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
|
|
@ -103,11 +112,13 @@ export default {
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
vm.inShopProviders = providers;
|
vm.inShopProvidersAndTimeslots = providers.map((provider, i) => ({
|
||||||
vm.inshopTimeSlots = providers.map((_, i) => resultMap[`inshopTimeSlots_${i}`] ?? null);
|
provider,
|
||||||
vm.mobileTimeSlots = resultMap.mobileTimeSlots ?? null;
|
timeSlots: resultMap[`inshopTimeSlots_${i}`] ?? null,
|
||||||
vm.inShopProviderNumber = providers[0]?.providerNumber ?? null;
|
}));
|
||||||
vm.mobileProviderNumber = mobileProviderNumber;
|
vm.mobileProviderAndTimeSlot = mobileProviderNumber
|
||||||
|
? { providerNumber: mobileProviderNumber, timeSlots: resultMap.mobileTimeSlots ?? null }
|
||||||
|
: null;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -115,10 +126,10 @@ export default {
|
||||||
return this.getCmsContent("ServiceLocationText", "Text");
|
return this.getCmsContent("ServiceLocationText", "Text");
|
||||||
},
|
},
|
||||||
availableDates() {
|
availableDates() {
|
||||||
const inshopDates = this.inshopTimeSlots.flatMap((ts) =>
|
const inshopDates = this.inShopProvidersAndTimeslots.flatMap(({ timeSlots }) =>
|
||||||
(ts?.days ?? []).map((d) => d.date)
|
(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();
|
return [...new Set([...inshopDates, ...mobileDates])].sort();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -127,12 +138,9 @@ export default {
|
||||||
selectedDate: null,
|
selectedDate: null,
|
||||||
isLoadingDates: false,
|
isLoadingDates: false,
|
||||||
datePickerStartDate: toDateString(0),
|
datePickerStartDate: toDateString(0),
|
||||||
datePickerEndDate: toDateString(14),
|
datePickerEndDate: toDateString(SCHEDULE_FETCH_DAYS - 1),
|
||||||
inShopProviders: [],
|
inShopProvidersAndTimeslots: [],
|
||||||
inshopTimeSlots: [],
|
mobileProviderAndTimeSlot: null,
|
||||||
mobileTimeSlots: null,
|
|
||||||
inShopProviderNumber: null,
|
|
||||||
mobileProviderNumber: null,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -194,7 +202,7 @@ export default {
|
||||||
this.$refs.loadingModal.hideModal();
|
this.$refs.loadingModal.hideModal();
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
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) {
|
if (appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||||
this.$router.navigateWithSaving(
|
this.$router.navigateWithSaving(
|
||||||
this.navigationScenarios.CLICKED_FORWARD_WITH_MOBILE_SERVICE,
|
this.navigationScenarios.CLICKED_FORWARD_WITH_MOBILE_SERVICE,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue