From 1d11d3d392090c0d8fad464c6e7334dbd1867bee Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 11 Jun 2026 10:30:32 -0400 Subject: [PATCH 1/2] Add gitignore for cursor files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b01672f1a..3018f2938 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,9 @@ ortoni-report/ *.sln *.sw? +# Cursor +.cursor/ + # Misc coverage/* junit.xml \ No newline at end of file From f9c45941e88631d6f2a3e4bbce788f8bae5c8117 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Mon, 15 Jun 2026 15:54:44 -0400 Subject: [PATCH 2/2] CASH-2752 | Add ability to get more timeslots on next date click --- src/layouts/scheduling/scheduling.vue | 105 ++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 13 deletions(-) diff --git a/src/layouts/scheduling/scheduling.vue b/src/layouts/scheduling/scheduling.vue index 1c2a1fd49..4a45907ee 100644 --- a/src/layouts/scheduling/scheduling.vue +++ b/src/layouts/scheduling/scheduling.vue @@ -66,13 +66,41 @@ import { debugLog } from "@/helpers/debug-log-helper"; * @param {Date} base - The starting date (defaults to today). */ function toDateString(offsetDays, base = new Date()) { - const d = new Date(base); + // Adding T00:00:00 ensures the date is treated as a local date in the browser's timezone. + const d = typeof base === "string" ? new Date(base + "T00:00:00") : 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; +/** + * Returns a promise for inshop time slots for a single provider. + * @param {{ startDate: string, endDate: string, providerNumber: string, pageNameToLog: string }} params + */ +function fetchInshopTimeSlots({ startDate, endDate, providerNumber, pageNameToLog }) { + return store.dispatch("getShopTimeSlots", { + payload: { + startDate, + endDate, + shopAppointmentType: "InshopOrDropoff", + providerNumber, + }, + pageNameToLog, + }); +} + +/** + * Returns a promise for mobile time slots. + * @param {{ startDate: string, endDate: string, zipCode: string, pageNameToLog: string }} params + */ +function fetchMobileTimeSlots({ startDate, endDate, zipCode, pageNameToLog }) { + return store.dispatch("getMobileTimeSlots", { + payload: { startDate, endDate, zipCode }, + pageNameToLog, + }); +} + export default { name: "scheduling", async beforeRouteEnter(to, from, next) { @@ -102,13 +130,10 @@ export default { }, ...providers.map((provider, i) => ({ resultKey: `inshopTimeSlots_${i}`, - promise: store.dispatch("getShopTimeSlots", { - payload: { - startDate, - endDate, - shopAppointmentType: "InshopOrDropoff", - providerNumber: provider.providerNumber, - }, + promise: fetchInshopTimeSlots({ + startDate, + endDate, + providerNumber: provider.providerNumber, pageNameToLog: to.name, }), })), @@ -117,8 +142,10 @@ export default { ? [ { resultKey: "mobileTimeSlots", - promise: store.dispatch("getMobileTimeSlots", { - payload: { startDate, endDate, zipCode: serviceZipCode }, + promise: fetchMobileTimeSlots({ + startDate, + endDate, + zipCode: serviceZipCode, pageNameToLog: to.name, }), }, @@ -238,10 +265,62 @@ export default { this.isLoadingDates = true; this.$refs.loadingModal.showModal(); - // TODO: call getShopTimeSlots with the next date range and append results - // to this.availableDates and advance this.datePickerEndDate - console.log("handleRequestMoreDates"); + const newStartDate = toDateString(1, this.datePickerEndDate); + const newEndDate = toDateString(SCHEDULE_FETCH_DAYS, this.datePickerEndDate); + const promiseResultMap = [ + ...this.inShopProvidersAndTimeslots.map(({ provider }, i) => ({ + resultKey: `inshopTimeSlots_${i}`, + promise: fetchInshopTimeSlots({ + startDate: newStartDate, + endDate: newEndDate, + providerNumber: provider.providerNumber, + pageNameToLog: this.pageName, + }), + })), + ...(this.mobileProviderAndTimeSlot + ? [ + { + resultKey: "mobileTimeSlots", + promise: fetchMobileTimeSlots({ + startDate: newStartDate, + endDate: newEndDate, + zipCode: this.serviceZipCode, + pageNameToLog: this.pageName, + }), + }, + ] + : []), + ]; + + const resultMap = await settleAllPromises(promiseResultMap); + + this.inShopProvidersAndTimeslots.forEach((entry, index) => { + const newSlots = resultMap[`inshopTimeSlots_${index}`]; + if (!newSlots) return; + if (!entry.timeSlots) { + entry.timeSlots = newSlots; + } else { + entry.timeSlots.days = [ + ...(entry.timeSlots.days ?? []), + ...(newSlots.days ?? []), + ]; + } + }); + + if (this.mobileProviderAndTimeSlot && resultMap.mobileTimeSlots) { + const newSlots = resultMap.mobileTimeSlots; + if (!this.mobileProviderAndTimeSlot.timeSlots) { + this.mobileProviderAndTimeSlot.timeSlots = newSlots; + } else { + this.mobileProviderAndTimeSlot.timeSlots.days = [ + ...(this.mobileProviderAndTimeSlot.timeSlots.days ?? []), + ...(newSlots.days ?? []), + ]; + } + } + + this.datePickerEndDate = newEndDate; this.isLoadingDates = false; this.$refs.loadingModal.hideModal(); },