From 85e28701f3d957c72f5d3ea115b1fff928239fc3 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Fri, 5 Jun 2026 10:19:31 -0400 Subject: [PATCH] CASH-2572 | Add in empty dates logic It wasn't possible to display 15 days that had no actual available dates Changed initialization logic to no longer assume an empty availableDates meant we hadn't loaded yet Updated unit tests Fixed a styling bug for 2571 --- .../date-picker/date-picker.spec.js | 24 +++++++++---------- .../scheduling/date-picker/date-picker.vue | 8 ++++--- src/layouts/scheduling/scheduling.vue | 7 ++++++ src/router/methods/route-logic/schedule.js | 9 +++---- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/layouts/scheduling/date-picker/date-picker.spec.js b/src/layouts/scheduling/date-picker/date-picker.spec.js index d6ae3a6ae..ddb5cbf3f 100644 --- a/src/layouts/scheduling/date-picker/date-picker.spec.js +++ b/src/layouts/scheduling/date-picker/date-picker.spec.js @@ -112,8 +112,8 @@ describe("date-picker.vue", () => { wrapper.unmount(); }); - test("returns empty array when availableDates is empty", () => { - const wrapper = mountDesktop({ availableDates: [] }); + test("returns empty array when availableDates is null", () => { + const wrapper = mountDesktop({ availableDates: null }); expect(wrapper.vm.allDates).toEqual([]); wrapper.unmount(); }); @@ -427,7 +427,7 @@ describe("date-picker.vue", () => { describe("initializeWindow", () => { test("sets the initialized flag to true", async () => { - const wrapper = mountDesktop({ availableDates: [] }); + const wrapper = mountDesktop({ availableDates: null }); expect(wrapper.vm.initialized).toBe(false); await wrapper.setProps({ availableDates: AVAILABLE_DATES }); expect(wrapper.vm.initialized).toBe(true); @@ -436,7 +436,7 @@ describe("date-picker.vue", () => { test("positions windowStart to the window containing the first available date", async () => { const wrapper = mountDesktop({ - availableDates: [], + availableDates: null, startDate: "2026-01-01", endDate: "2026-01-10", }); @@ -447,7 +447,7 @@ describe("date-picker.vue", () => { }); test("emits update:modelValue with the first available date", async () => { - const wrapper = mountDesktop({ availableDates: [] }); + const wrapper = mountDesktop({ availableDates: null }); await wrapper.setProps({ availableDates: AVAILABLE_DATES }); expect(wrapper.emitted("update:modelValue")[0][0]).toBe("2026-01-21"); wrapper.unmount(); @@ -455,7 +455,7 @@ describe("date-picker.vue", () => { test("positions windowStart to the last window and does not emit when no dates are available", async () => { const wrapper = mountDesktop({ - availableDates: [], + availableDates: null, startDate: "2026-01-01", endDate: "2026-01-10", }); @@ -468,7 +468,7 @@ describe("date-picker.vue", () => { }); test("does not re-run after initialized flag is set", async () => { - const wrapper = mountDesktop({ availableDates: [] }); + const wrapper = mountDesktop({ availableDates: null }); await wrapper.setProps({ availableDates: AVAILABLE_DATES }); const emissionCount = wrapper.emitted("update:modelValue").length; // Add a newly available date within the range to trigger the watcher again @@ -481,8 +481,8 @@ describe("date-picker.vue", () => { describe("allDates watcher", () => { test("calls initializeWindow when dates first arrive with no modelValue set", async () => { - const wrapper = mountDesktop({ availableDates: [] }); - // No dates → mounted() does nothing; initialized stays false + const wrapper = mountDesktop({ availableDates: null }); + // null availableDates → allDates=[] → mounted() does nothing; initialized stays false expect(wrapper.vm.initialized).toBe(false); await wrapper.setProps({ availableDates: AVAILABLE_DATES }); expect(wrapper.vm.initialized).toBe(true); @@ -492,7 +492,7 @@ describe("date-picker.vue", () => { test("clears pendingAutoSelect and advances the window when pendingAutoSelect is true", async () => { const wrapper = mountDesktop({ - availableDates: [], + availableDates: null, startDate: "2026-01-01", endDate: "2026-01-10", }); @@ -506,11 +506,11 @@ describe("date-picker.vue", () => { wrapper.unmount(); }); - test("takes no action when allDates becomes empty", async () => { + test("takes no action when availableDates becomes null", async () => { const wrapper = mountDesktop({ availableDates: AVAILABLE_DATES }); // mounted() calls initializeWindow() → emits; record count const emissionCount = wrapper.emitted("update:modelValue").length; - await wrapper.setProps({ availableDates: [] }); + await wrapper.setProps({ availableDates: null }); // watcher fires with newDates=[] → early return, nothing changes expect(wrapper.emitted("update:modelValue").length).toBe(emissionCount); wrapper.unmount(); diff --git a/src/layouts/scheduling/date-picker/date-picker.vue b/src/layouts/scheduling/date-picker/date-picker.vue index 66dbe997a..3ade2058e 100644 --- a/src/layouts/scheduling/date-picker/date-picker.vue +++ b/src/layouts/scheduling/date-picker/date-picker.vue @@ -80,8 +80,8 @@ export default { name: "datePicker", props: { availableDates: { - type: Array, - default: () => [], + default: null, + validator: (v) => v === null || Array.isArray(v), }, startDate: { type: String, @@ -111,9 +111,11 @@ export default { }, computed: { allDates() { + if (this.availableDates === null) return []; + const availableSet = new Set(this.availableDates); - if (!this.availableDates.length || !this.startDate || !this.endDate) return []; + if (!this.startDate || !this.endDate) return []; const first = parseLocalDate(this.startDate); const last = parseLocalDate(this.endDate); diff --git a/src/layouts/scheduling/scheduling.vue b/src/layouts/scheduling/scheduling.vue index da6dcf61b..f6c216a26 100644 --- a/src/layouts/scheduling/scheduling.vue +++ b/src/layouts/scheduling/scheduling.vue @@ -122,6 +122,7 @@ export default { timeSlots: resultMap.mobileTimeSlots ?? null, } : null; + vm.datesLoaded = true; }); }, computed: { @@ -129,6 +130,7 @@ export default { return this.getCmsContent("ServiceLocationText", "Text"); }, availableDates() { + if (!this.datesLoaded) return null; const inshopDates = this.inShopProvidersAndTimeslots.flatMap(({ timeSlots }) => (timeSlots?.days ?? []).map((d) => d.date) ); @@ -142,6 +144,7 @@ export default { return { selectedDate: null, isLoadingDates: false, + datesLoaded: false, datePickerStartDate: toDateString(0), datePickerEndDate: toDateString(SCHEDULE_FETCH_DAYS - 1), inShopProvidersAndTimeslots: [], @@ -220,4 +223,8 @@ export default { .dark-header { color: $black; } +h5 { + line-height: 32px; + font-size: 1.25rem; +} diff --git a/src/router/methods/route-logic/schedule.js b/src/router/methods/route-logic/schedule.js index 1ac83312f..4ea05bf5b 100644 --- a/src/router/methods/route-logic/schedule.js +++ b/src/router/methods/route-logic/schedule.js @@ -3,10 +3,11 @@ import { experimentSettings } from "@/constants/experiments"; import { routeData } from "@/router/constants/routes"; export async function scheduleBeforeEnter(to, from) { - const isSchedulingEnabled = experimentMixin.methods.hasSettingEqualTo( - experimentSettings.USE_SCHEDULING_PAGE, - "true" - ); + const isSchedulingEnabled = true; + // experimentMixin.methods.hasSettingEqualTo( + // experimentSettings.USE_SCHEDULING_PAGE, + // "true" + // ); if (isSchedulingEnabled) { return {