From 6c4ea262b1b27589f82592e3543c729a2621eefe Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 28 May 2026 16:07:41 -0400 Subject: [PATCH 1/6] Styling updates --- src/layouts/scheduling/date-picker/date-picker.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/layouts/scheduling/date-picker/date-picker.vue b/src/layouts/scheduling/date-picker/date-picker.vue index 6b3fb7638..b8288f993 100644 --- a/src/layouts/scheduling/date-picker/date-picker.vue +++ b/src/layouts/scheduling/date-picker/date-picker.vue @@ -226,7 +226,7 @@ export default { } &__track { - gap: 0.5rem; + gap: 0.25rem; } &__day-card { @@ -268,8 +268,8 @@ export default { } &__day-abbr { - font-family: $font-family-sans-serif-semibold; - font-size: $font-size-12; + font-family: $font-family-sans-serif-bold; + font-size: $font-size-14; color: $blue; text-transform: uppercase; line-height: 1.2; From 5c10137df1af92548fca4ec0d05cfbfb677f1e4d Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 28 May 2026 16:33:11 -0400 Subject: [PATCH 2/6] Disable date-picker advance after 180 days have been loaded Unit tests to confirm functonality --- .../date-picker/date-picker.spec.js | 70 +++++++++++++++++++ .../scheduling/date-picker/date-picker.vue | 5 +- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/layouts/scheduling/date-picker/date-picker.spec.js b/src/layouts/scheduling/date-picker/date-picker.spec.js index f64d27a12..73a05ac52 100644 --- a/src/layouts/scheduling/date-picker/date-picker.spec.js +++ b/src/layouts/scheduling/date-picker/date-picker.spec.js @@ -214,6 +214,76 @@ describe("date-picker.vue", () => { }); }); + describe("forward button disabled at 180-date limit", () => { + function generateDateRange(startStr, count) { + const dates = []; + const [y, m, d] = startStr.split("-").map(Number); + const cursor = new Date(y, m - 1, d); + for (let i = 0; i < count; i++) { + const yy = cursor.getFullYear(); + const mm = String(cursor.getMonth() + 1).padStart(2, "0"); + const dd = String(cursor.getDate()).padStart(2, "0"); + dates.push(`${yy}-${mm}-${dd}`); + cursor.setDate(cursor.getDate() + 1); + } + return dates; + } + + test("canGoForward is false when allDates.length >= 180 and the last date is in the current view", async () => { + const allDateValues = generateDateRange("2026-01-01", 180); + const wrapper = mountDesktop({ + availableDates: allDateValues, + startDate: allDateValues[0], + endDate: allDateValues[allDateValues.length - 1], + }); + // Desktop window size is 5; set windowStart to last window (index 175) + wrapper.vm.windowStart = 175; + await wrapper.vm.$nextTick(); + expect(wrapper.vm.canGoForward).toBe(false); + wrapper.unmount(); + }); + + test("forward nav button has disabled attribute when at the end of a 180-date range", async () => { + const allDateValues = generateDateRange("2026-01-01", 180); + const wrapper = mountDesktop({ + availableDates: allDateValues, + startDate: allDateValues[0], + endDate: allDateValues[allDateValues.length - 1], + }); + wrapper.vm.windowStart = 175; + await wrapper.vm.$nextTick(); + const forwardBtn = wrapper.findAll(".date-picker__nav-btn")[1]; + expect(forwardBtn.attributes("disabled")).toBeDefined(); + wrapper.unmount(); + }); + + test("canGoForward is true when allDates.length >= 180 but the last date is not yet in view", () => { + const allDateValues = generateDateRange("2026-01-01", 180); + const wrapper = mountDesktop({ + availableDates: allDateValues, + startDate: allDateValues[0], + endDate: allDateValues[allDateValues.length - 1], + }); + // windowStart = 0, first 5 of 180 dates are visible — last date is not in view + expect(wrapper.vm.canGoForward).toBe(true); + wrapper.unmount(); + }); + + test("canGoForward remains true at the last window when allDates.length < 180", async () => { + const allDateValues = generateDateRange("2026-01-01", 10); + const wrapper = mountDesktop({ + availableDates: allDateValues, + startDate: allDateValues[0], + endDate: allDateValues[allDateValues.length - 1], + }); + // windowStart = 5 puts the last 5 dates (indices 5–9) in view + wrapper.vm.windowStart = 5; + await wrapper.vm.$nextTick(); + expect(wrapper.vm.canGoForward).toBe(true); + wrapper.unmount(); + }); + }); + describe("initial window positioning", () => { test("scrolls to the window containing the pre-selected date on mount", () => { // Jan 25 is the 5th date (index 4); with window size 5 on desktop it's still in window 0 diff --git a/src/layouts/scheduling/date-picker/date-picker.vue b/src/layouts/scheduling/date-picker/date-picker.vue index b8288f993..fa0ebc276 100644 --- a/src/layouts/scheduling/date-picker/date-picker.vue +++ b/src/layouts/scheduling/date-picker/date-picker.vue @@ -151,7 +151,10 @@ export default { return this.windowStart > 0; }, canGoForward() { - return !this.isLoadingDates && this.allDates.length > 0; + if (this.isLoadingDates || !this.allDates.length) return false; + const lastDateIsVisible = this.windowStart + this.windowSize >= this.allDates.length; + if (this.allDates.length >= 180 && lastDateIsVisible) return false; + return true; }, }, mounted() { From 8a472aa3353f805b88a56ea0ae7cc17a808941a3 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Fri, 29 May 2026 10:34:45 -0400 Subject: [PATCH 3/6] CASH-2572 | Add in auto-select functionality --- .../date-picker/date-picker.spec.js | 226 +++++++++++++++++- .../scheduling/date-picker/date-picker.vue | 46 +++- 2 files changed, 269 insertions(+), 3 deletions(-) diff --git a/src/layouts/scheduling/date-picker/date-picker.spec.js b/src/layouts/scheduling/date-picker/date-picker.spec.js index 73a05ac52..d6ae3a6ae 100644 --- a/src/layouts/scheduling/date-picker/date-picker.spec.js +++ b/src/layouts/scheduling/date-picker/date-picker.spec.js @@ -133,9 +133,12 @@ describe("date-picker.vue", () => { test("does not emit when a disabled card is clicked", async () => { const wrapper = mountDesktop(); + const emissionCountBeforeClick = (wrapper.emitted("update:modelValue") ?? []).length; const disabledCard = wrapper.find(".date-picker__day-card--disabled"); await disabledCard.trigger("click"); - expect(wrapper.emitted("update:modelValue")).toBeFalsy(); + expect((wrapper.emitted("update:modelValue") ?? []).length).toBe( + emissionCountBeforeClick + ); wrapper.unmount(); }); @@ -292,4 +295,225 @@ describe("date-picker.vue", () => { wrapper.unmount(); }); }); + + describe("mounted initialization", () => { + test("emits first available date when mounted with no modelValue and dates present", () => { + const wrapper = mountDesktop(); + expect(wrapper.emitted("update:modelValue")).toBeTruthy(); + expect(wrapper.emitted("update:modelValue")[0][0]).toBe("2026-01-21"); + wrapper.unmount(); + }); + }); + + describe("goBack auto-selection", () => { + test("emits update:modelValue with first available date in the new window", async () => { + // modelValue set → mounted() uses scroll path, no emission on mount + const wrapper = mountDesktop({ + availableDates: ["2026-01-01", "2026-01-07"], + startDate: "2026-01-01", + endDate: "2026-01-10", + modelValue: "2026-01-07", + }); + // "2026-01-07" is index 6 → mounted sets windowStart = Math.floor(6/5)*5 = 5 + expect(wrapper.vm.windowStart).toBe(5); + expect(wrapper.emitted("update:modelValue")).toBeFalsy(); + await wrapper.vm.goBack(); + const emissions = wrapper.emitted("update:modelValue"); + expect(emissions).toBeTruthy(); + expect(emissions[emissions.length - 1][0]).toBe("2026-01-01"); + wrapper.unmount(); + }); + }); + + describe("goForward pending flow", () => { + test("emits requestMoreDates when at the last window", async () => { + // 5 dates, desktop window size 5 → already at end on mount + const wrapper = mountDesktop({ modelValue: "2026-01-21" }); + await wrapper.vm.goForward(); + expect(wrapper.emitted("requestMoreDates")).toBeTruthy(); + wrapper.unmount(); + }); + + test("sets pendingAutoSelect when at the last window", async () => { + const wrapper = mountDesktop({ modelValue: "2026-01-21" }); + await wrapper.vm.goForward(); + expect(wrapper.vm.pendingAutoSelect).toBe(true); + wrapper.unmount(); + }); + + test("emits update:modelValue with first available date in the new window when not at the end", async () => { + const wrapper = mountDesktop({ + availableDates: ["2026-01-01", "2026-01-07"], + startDate: "2026-01-01", + endDate: "2026-01-10", + modelValue: "2026-01-01", + }); + // windowStart = 0, not at end (0 + 5 < 10), no emission on mount + await wrapper.vm.goForward(); + const emissions = wrapper.emitted("update:modelValue"); + expect(emissions).toBeTruthy(); + expect(emissions[emissions.length - 1][0]).toBe("2026-01-07"); + wrapper.unmount(); + }); + }); + + describe("advanceWindowAndAutoSelect", () => { + test("advances windowStart by windowSize", () => { + const wrapper = mountDesktop({ + availableDates: ["2026-01-01", "2026-01-07"], + startDate: "2026-01-01", + endDate: "2026-01-10", + modelValue: "2026-01-01", + }); + expect(wrapper.vm.windowStart).toBe(0); + wrapper.vm.advanceWindowAndAutoSelect(); + expect(wrapper.vm.windowStart).toBe(5); + wrapper.unmount(); + }); + + test("caps windowStart at maxStart when already near the end", () => { + const wrapper = mountDesktop({ + availableDates: ["2026-01-01", "2026-01-07"], + startDate: "2026-01-01", + endDate: "2026-01-10", + modelValue: "2026-01-07", + }); + // mounted() sets windowStart = 5 (index 6, Math.floor(6/5)*5) + // maxStart = Math.max(0, 10 - 5) = 5 → min(5, 5+5) = 5 + wrapper.vm.advanceWindowAndAutoSelect(); + expect(wrapper.vm.windowStart).toBe(5); + wrapper.unmount(); + }); + + test("emits update:modelValue with first available date in the advanced window", () => { + const wrapper = mountDesktop({ + availableDates: ["2026-01-01", "2026-01-07"], + startDate: "2026-01-01", + endDate: "2026-01-10", + modelValue: "2026-01-01", + }); + wrapper.vm.advanceWindowAndAutoSelect(); + const emissions = wrapper.emitted("update:modelValue"); + expect(emissions).toBeTruthy(); + expect(emissions[emissions.length - 1][0]).toBe("2026-01-07"); + wrapper.unmount(); + }); + }); + + describe("autoSelectFirstAvailable", () => { + test("emits update:modelValue with the first available date in the visible window", () => { + const wrapper = mountDesktop({ modelValue: "2026-01-21" }); + wrapper.vm.autoSelectFirstAvailable(); + const emissions = wrapper.emitted("update:modelValue"); + expect(emissions[emissions.length - 1][0]).toBe("2026-01-21"); + wrapper.unmount(); + }); + + test("emits null when no available dates are visible", () => { + // availableDates outside the date range → all visible dates are unavailable + const wrapper = mountDesktop({ + availableDates: ["9999-12-31"], + startDate: "2026-01-21", + endDate: "2026-01-25", + modelValue: "2026-01-21", + }); + // modelValue set → mounted uses scroll path, no emission on mount + wrapper.vm.autoSelectFirstAvailable(); + const emissions = wrapper.emitted("update:modelValue"); + expect(emissions[emissions.length - 1][0]).toBeNull(); + wrapper.unmount(); + }); + }); + + describe("initializeWindow", () => { + test("sets the initialized flag to true", async () => { + const wrapper = mountDesktop({ availableDates: [] }); + expect(wrapper.vm.initialized).toBe(false); + await wrapper.setProps({ availableDates: AVAILABLE_DATES }); + expect(wrapper.vm.initialized).toBe(true); + wrapper.unmount(); + }); + + test("positions windowStart to the window containing the first available date", async () => { + const wrapper = mountDesktop({ + availableDates: [], + startDate: "2026-01-01", + endDate: "2026-01-10", + }); + // "2026-01-07" is index 6 → Math.floor(6/5)*5 = 5 + await wrapper.setProps({ availableDates: ["2026-01-07"] }); + expect(wrapper.vm.windowStart).toBe(5); + wrapper.unmount(); + }); + + test("emits update:modelValue with the first available date", async () => { + const wrapper = mountDesktop({ availableDates: [] }); + await wrapper.setProps({ availableDates: AVAILABLE_DATES }); + expect(wrapper.emitted("update:modelValue")[0][0]).toBe("2026-01-21"); + wrapper.unmount(); + }); + + test("positions windowStart to the last window and does not emit when no dates are available", async () => { + const wrapper = mountDesktop({ + availableDates: [], + startDate: "2026-01-01", + endDate: "2026-01-10", + }); + // Dates are present but none fall in the Jan 1–10 range + await wrapper.setProps({ availableDates: ["9999-12-31"] }); + // Math.max(0, 10 - 5) = 5 + expect(wrapper.vm.windowStart).toBe(5); + expect(wrapper.emitted("update:modelValue")).toBeFalsy(); + wrapper.unmount(); + }); + + test("does not re-run after initialized flag is set", async () => { + const wrapper = mountDesktop({ availableDates: [] }); + 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 + await wrapper.setProps({ availableDates: [...AVAILABLE_DATES, "2026-01-24"] }); + // initialized=true and pendingAutoSelect=false → watcher takes no action + expect(wrapper.emitted("update:modelValue").length).toBe(emissionCount); + wrapper.unmount(); + }); + }); + + 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 + expect(wrapper.vm.initialized).toBe(false); + await wrapper.setProps({ availableDates: AVAILABLE_DATES }); + expect(wrapper.vm.initialized).toBe(true); + expect(wrapper.emitted("update:modelValue")[0][0]).toBe("2026-01-21"); + wrapper.unmount(); + }); + + test("clears pendingAutoSelect and advances the window when pendingAutoSelect is true", async () => { + const wrapper = mountDesktop({ + availableDates: [], + startDate: "2026-01-01", + endDate: "2026-01-10", + }); + wrapper.vm.initialized = true; + wrapper.vm.pendingAutoSelect = true; + await wrapper.setProps({ availableDates: ["2026-01-01", "2026-01-07"] }); + expect(wrapper.vm.pendingAutoSelect).toBe(false); + expect(wrapper.vm.windowStart).toBe(5); + const emissions = wrapper.emitted("update:modelValue"); + expect(emissions[emissions.length - 1][0]).toBe("2026-01-07"); + wrapper.unmount(); + }); + + test("takes no action when allDates becomes empty", async () => { + const wrapper = mountDesktop({ availableDates: AVAILABLE_DATES }); + // mounted() calls initializeWindow() → emits; record count + const emissionCount = wrapper.emitted("update:modelValue").length; + await wrapper.setProps({ availableDates: [] }); + // 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 fa0ebc276..48c49c1ed 100644 --- a/src/layouts/scheduling/date-picker/date-picker.vue +++ b/src/layouts/scheduling/date-picker/date-picker.vue @@ -118,6 +118,8 @@ export default { window.innerWidth >= DESKTOP_BREAKPOINT_PX ? DESKTOP_WINDOW_SIZE : MOBILE_WINDOW_SIZE, + pendingAutoSelect: false, + initialized: false, }; }, computed: { @@ -157,6 +159,21 @@ export default { return true; }, }, + watch: { + allDates(newDates) { + if (!newDates.length) return; + + if (!this.initialized && !this.modelValue) { + this.initializeWindow(); + return; + } + + if (this.pendingAutoSelect) { + this.pendingAutoSelect = false; + this.advanceWindowAndAutoSelect(); + } + }, + }, mounted() { this.updateWindowSize(); window.addEventListener("resize", this.updateWindowSize); @@ -165,6 +182,8 @@ export default { if (index !== -1) { this.windowStart = Math.floor(index / this.windowSize) * this.windowSize; } + } else if (!this.modelValue && this.allDates.length) { + this.initializeWindow(); } }, beforeUnmount() { @@ -179,15 +198,38 @@ export default { }, goBack() { this.windowStart = Math.max(0, this.windowStart - this.windowSize); + this.autoSelectFirstAvailable(); }, goForward() { if (this.isLoadingDates) return; const isAtEnd = this.windowStart + this.windowSize >= this.allDates.length; if (isAtEnd) { this.$emit("requestMoreDates"); + this.pendingAutoSelect = true; } else { - const maxStart = Math.max(0, this.allDates.length - this.windowSize); - this.windowStart = Math.min(maxStart, this.windowStart + this.windowSize); + this.advanceWindowAndAutoSelect(); + } + }, + advanceWindowAndAutoSelect() { + const maxStart = Math.max(0, this.allDates.length - this.windowSize); + this.windowStart = Math.min(maxStart, this.windowStart + this.windowSize); + this.autoSelectFirstAvailable(); + }, + autoSelectFirstAvailable() { + const first = this.visibleDates.find((d) => d.isAvailable); + this.$emit("update:modelValue", first ? first.value : null); + }, + initializeWindow() { + this.initialized = true; + if (this.modelValue !== null) return; + + const firstAvailable = this.allDates.find((d) => d.isAvailable); + if (firstAvailable) { + const index = this.allDates.indexOf(firstAvailable); + this.windowStart = Math.floor(index / this.windowSize) * this.windowSize; + this.$emit("update:modelValue", firstAvailable.value); + } else { + this.windowStart = Math.max(0, this.allDates.length - this.windowSize); } }, selectDate(date) { From 7fd7362982866ba2d6bd725852d4b1295e821b5c Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Fri, 29 May 2026 11:23:10 -0400 Subject: [PATCH 4/6] Logic refactoring of date-picker --- .../scheduling/date-picker/date-picker.vue | 67 ++++++++----------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/src/layouts/scheduling/date-picker/date-picker.vue b/src/layouts/scheduling/date-picker/date-picker.vue index 48c49c1ed..cdbebb5d9 100644 --- a/src/layouts/scheduling/date-picker/date-picker.vue +++ b/src/layouts/scheduling/date-picker/date-picker.vue @@ -6,13 +6,7 @@ aria-label="Previous dates" @click="goBack"> - @@ -38,16 +32,7 @@ :disabled="!canGoForward" aria-label="Next dates" @click="goForward"> - - + @@ -73,6 +58,7 @@ const MONTH_ABBRS = [ const MOBILE_WINDOW_SIZE = 3; const DESKTOP_WINDOW_SIZE = 5; const DESKTOP_BREAKPOINT_PX = Breakpoints.MD; +const MAX_DATE_RANGE = 180; function toLocalDateString(date) { const y = date.getFullYear(); @@ -86,6 +72,10 @@ function parseLocalDate(str) { return new Date(year, month - 1, day); } +function getWindowSize() { + return window.innerWidth >= DESKTOP_BREAKPOINT_PX ? DESKTOP_WINDOW_SIZE : MOBILE_WINDOW_SIZE; +} + export default { name: "datePicker", props: { @@ -114,10 +104,7 @@ export default { data() { return { windowStart: 0, - windowSize: - window.innerWidth >= DESKTOP_BREAKPOINT_PX - ? DESKTOP_WINDOW_SIZE - : MOBILE_WINDOW_SIZE, + windowSize: getWindowSize(), pendingAutoSelect: false, initialized: false, }; @@ -154,9 +141,8 @@ export default { }, canGoForward() { if (this.isLoadingDates || !this.allDates.length) return false; - const lastDateIsVisible = this.windowStart + this.windowSize >= this.allDates.length; - if (this.allDates.length >= 180 && lastDateIsVisible) return false; - return true; + const atEnd = this.windowStart + this.windowSize >= this.allDates.length; + return !(atEnd && this.allDates.length >= MAX_DATE_RANGE); }, }, watch: { @@ -177,12 +163,11 @@ export default { mounted() { this.updateWindowSize(); window.addEventListener("resize", this.updateWindowSize); - if (this.modelValue && this.allDates.length) { + if (!this.allDates.length) return; + if (this.modelValue) { const index = this.allDates.findIndex((d) => d.value === this.modelValue); - if (index !== -1) { - this.windowStart = Math.floor(index / this.windowSize) * this.windowSize; - } - } else if (!this.modelValue && this.allDates.length) { + if (index !== -1) this.windowStart = this.getWindowStart(index); + } else { this.initializeWindow(); } }, @@ -191,10 +176,15 @@ export default { }, methods: { updateWindowSize() { - this.windowSize = - window.innerWidth >= DESKTOP_BREAKPOINT_PX - ? DESKTOP_WINDOW_SIZE - : MOBILE_WINDOW_SIZE; + this.windowSize = getWindowSize(); + }, + navIconSrc(enabled) { + return enabled + ? require("@/assets/img/icons/chevron-right-blue.svg") + : require("@/assets/img/icons/chevron-right-grey.svg"); + }, + getWindowStart(index) { + return Math.floor(index / this.windowSize) * this.windowSize; }, goBack() { this.windowStart = Math.max(0, this.windowStart - this.windowSize); @@ -226,7 +216,7 @@ export default { const firstAvailable = this.allDates.find((d) => d.isAvailable); if (firstAvailable) { const index = this.allDates.indexOf(firstAvailable); - this.windowStart = Math.floor(index / this.windowSize) * this.windowSize; + this.windowStart = this.getWindowStart(index); this.$emit("update:modelValue", firstAvailable.value); } else { this.windowStart = Math.max(0, this.allDates.length - this.windowSize); @@ -312,18 +302,19 @@ export default { } } - &__day-abbr { + &__day-abbr, + &__day-date { font-family: $font-family-sans-serif-bold; font-size: $font-size-14; color: $blue; + } + + &__day-abbr { text-transform: uppercase; line-height: 1.2; } &__day-date { - font-family: $font-family-sans-serif-bold; - font-size: $font-size-14; - color: $blue; line-height: 1.4; white-space: nowrap; } From 0bed421da3542566f2010bf5ed4a2c3a4e26b4be Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Fri, 29 May 2026 11:39:55 -0400 Subject: [PATCH 5/6] Increase readability --- src/layouts/scheduling/date-picker/date-picker.vue | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/layouts/scheduling/date-picker/date-picker.vue b/src/layouts/scheduling/date-picker/date-picker.vue index cdbebb5d9..c3b9afdc5 100644 --- a/src/layouts/scheduling/date-picker/date-picker.vue +++ b/src/layouts/scheduling/date-picker/date-picker.vue @@ -153,7 +153,7 @@ export default { this.initializeWindow(); return; } - + // Pending auto select is set when the user is at the end of the dates and the next page of dates is loaded. if (this.pendingAutoSelect) { this.pendingAutoSelect = false; this.advanceWindowAndAutoSelect(); @@ -164,9 +164,11 @@ export default { this.updateWindowSize(); window.addEventListener("resize", this.updateWindowSize); if (!this.allDates.length) return; + // If a model value is set, we need to set the window start to the index of the model value. + // Otherwise, we need to initialize the window. if (this.modelValue) { const index = this.allDates.findIndex((d) => d.value === this.modelValue); - if (index !== -1) this.windowStart = this.getWindowStart(index); + if (index !== -1) this.windowStart = this.getWindowStartFromIndex(index); } else { this.initializeWindow(); } @@ -183,7 +185,7 @@ export default { ? require("@/assets/img/icons/chevron-right-blue.svg") : require("@/assets/img/icons/chevron-right-grey.svg"); }, - getWindowStart(index) { + getWindowStartFromIndex(index) { return Math.floor(index / this.windowSize) * this.windowSize; }, goBack() { @@ -206,6 +208,7 @@ export default { this.autoSelectFirstAvailable(); }, autoSelectFirstAvailable() { + // Finds the first available date in the visible dates and emits the value. const first = this.visibleDates.find((d) => d.isAvailable); this.$emit("update:modelValue", first ? first.value : null); }, @@ -215,10 +218,12 @@ export default { const firstAvailable = this.allDates.find((d) => d.isAvailable); if (firstAvailable) { + // If an available date is found, set the window start ensures the first available date is visible. const index = this.allDates.indexOf(firstAvailable); - this.windowStart = this.getWindowStart(index); + this.windowStart = this.getWindowStartFromIndex(index); this.$emit("update:modelValue", firstAvailable.value); } else { + // If no available dates are found, set the window start to the last window. this.windowStart = Math.max(0, this.allDates.length - this.windowSize); } }, From b1cdb3be87fb4e3a9ad719314cdd2989ac29ce4e Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Fri, 29 May 2026 12:17:47 -0400 Subject: [PATCH 6/6] Fix initialization logic --- src/layouts/scheduling/date-picker/date-picker.vue | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/layouts/scheduling/date-picker/date-picker.vue b/src/layouts/scheduling/date-picker/date-picker.vue index c3b9afdc5..66dbe997a 100644 --- a/src/layouts/scheduling/date-picker/date-picker.vue +++ b/src/layouts/scheduling/date-picker/date-picker.vue @@ -150,7 +150,7 @@ export default { if (!newDates.length) return; if (!this.initialized && !this.modelValue) { - this.initializeWindow(); + this.initialize(); return; } // Pending auto select is set when the user is at the end of the dates and the next page of dates is loaded. @@ -170,8 +170,9 @@ export default { const index = this.allDates.findIndex((d) => d.value === this.modelValue); if (index !== -1) this.windowStart = this.getWindowStartFromIndex(index); } else { - this.initializeWindow(); + this.initialize(); } + this.initialized = true; }, beforeUnmount() { window.removeEventListener("resize", this.updateWindowSize); @@ -212,7 +213,7 @@ export default { const first = this.visibleDates.find((d) => d.isAvailable); this.$emit("update:modelValue", first ? first.value : null); }, - initializeWindow() { + initialize() { this.initialized = true; if (this.modelValue !== null) return;