Merge pull request #3036 from Safelite/rlsmerge/2026.01.29-to-2026.02.12

Rlsmerge/2026.01.29 to 2026.02.12
This commit is contained in:
CarlNation 2026-01-29 11:24:37 -05:00 committed by GitHub
commit 49cf7f7ddc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 63 additions and 72 deletions

View file

@ -281,7 +281,7 @@ export default {
if (event.screenX === 0 && event.screenY === 0) {
return;
}
this.$emit("date-clicked", date);
this.$emit("date-selected", date);
},
getWeekStartDate(dateString) {
const date = convertDateStringToDate(dateString);

View file

@ -496,7 +496,7 @@ export default {
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_STATE);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.navigationScenarios.CLICKED_PAY_LATER,
this.pageName
);
} catch (error) {

View file

@ -28,6 +28,7 @@
cmsWidgetName="ScheduleYourServiceWidget"
id="schedule-your-service" />
<appointmentTypeQuestion
v-if="hasSelectableDatesLoaded"
v-model="appointmentTypeFromAppointmentTypeQuestion"
v-show="isAppointmentTypeDisplayed"
:isServiceableMobile="isServiceableMobile"
@ -139,8 +140,6 @@
:isOvernightDropoff="isOvernightDropoff" />
</div>
<datePicker
:currentZip="zipCode"
:currentProviderNumber="selectedProvider?.providerNumber"
v-show="appointmentType"
customComponentId="dateQuestion"
selectableDatesSetting="custom"
@ -150,7 +149,7 @@
class="text-link-small"
:getMoreDatesCallback="getMoreScheduleData"
validationRules="date-required"
@date-clicked="handleDateClicked"
@date-selected="handleDateSelected"
:pricingByDayBasePrice="pricingByDayBasePrice"
:pricingByDayUpcharge="pricingByDayUpcharge"
:showPricingByDay="showPricingByDay"
@ -653,12 +652,12 @@ export default {
showTimeSlotQuestion() {
if (
this.selectedDate &&
this.selectedDate.includes("mobile") &&
!this.isMobileSelected
this.appointmentTypeFromAppointmentTypeQuestion &&
this.timeSlotsForSelectedDate
) {
this.setSelectedDateToFirstAvailable();
return true;
}
return this.selectedDate && this.appointmentTypeFromAppointmentTypeQuestion;
return false;
},
isMobileStaticRecalibrationApplicable() {
return (
@ -886,6 +885,13 @@ export default {
? this.$refs.mobileFirstModal?.getIsModalOpen()
: false;
},
hasSelectableDatesLoaded() {
if (this.isMobileSelected) {
return this.selectableDatesMobile?.days?.length > 0;
} else {
return this.selectableDatesInshop?.days?.length > 0;
}
},
},
methods: {
splitCopyOnCMSPlaceHolder,
@ -1200,8 +1206,6 @@ export default {
async initializeDatePicker() {
this.isShowMobileFirstAppt && this.showLoadingModal();
this.selectedDate = null;
const includeMobileTimeSlots = this.isServiceableMobile;
const includeInshopTimeSlots = this.isServiceableInshop || this.isServiceableDropoff;
const datePickerInitialData = await this.$refs.datePicker.loadInitialData({
@ -1613,28 +1617,39 @@ export default {
handleWaitListRequested(value) {
this.waitListRequested = value;
},
handleDateClicked(date) {
// do something to mark this as upcharge day or not...
if (date.isPricingByDayUpchargeDay) {
this.includePricingByDayUpcharge = true;
} else {
this.includePricingByDayUpcharge = false;
handleDateSelected(date) {
const previousDate = this.selectedDate;
// check if date actually changed
if (previousDate !== date.dateString) {
this.selectedTimeSlotInfo = this.getEmptyTimeSlot();
this.updateFooterButtonText(this.selectedTimeSlotInfo);
}
// TODO: REMOVE AS PART OF CASH-1634
// // do something to mark this as upcharge day or not...
// if (date.isPricingByDayUpchargeDay) {
// this.includePricingByDayUpcharge = true;
// } else {
// this.includePricingByDayUpcharge = false;
// }
},
getEmptyTimeSlot() {
return {
timeSlot: {
date: null,
routeCode: null,
startTime: null,
endTime: null,
jobMaxMinutes: null,
jobMinMinutes: null,
},
isPremiumAppointment: null,
};
},
updateTimeSlot(timeSlotObj) {
if (!timeSlotObj?.routeCode) {
this.appointmentType = AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF;
this.selectedTimeSlotInfo = {
timeSlot: {
date: null,
routeCode: null,
startTime: null,
endTime: null,
jobMaxMinutes: null,
jobMinMinutes: null,
},
isPremiumAppointment: null,
};
this.selectedTimeSlotInfo = this.getEmptyTimeSlot();
return;
}
const timeSlot = this.timeSlotsForSelectedDate?.timeSlots?.find(
@ -1752,6 +1767,9 @@ export default {
},
handleAppointmentTypeChange(newAppointmentType) {
this.updateFooterButtonText();
// if time appointment type changes, clear any selected time slot
this.selectedTimeSlotInfo = this.getEmptyTimeSlot();
if (newAppointmentType === AppointmentTypeStrings.MOBILE) {
// Remember last shop selected if previous selection was inshop/dropoff
if (
@ -1760,17 +1778,6 @@ export default {
AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF) &&
this.selectedProvider
) {
this.selectedTimeSlotInfo = {
timeSlot: {
date: null,
routeCode: null,
startTime: null,
endTime: null,
jobMaxMinutes: null,
jobMinMinutes: null,
},
isPremiumAppointment: null,
};
this.lastSelectedInshopOrDropoffProvider = this.selectedProvider;
}
this.appointmentType = AppointmentTypeStrings.MOBILE;
@ -1797,8 +1804,8 @@ export default {
} else {
this.appointmentType = null;
}
this.setSelectedDateToFirstAvailable();
this.setDisplayWaitList();
this.setSelectedDateToFirstAvailable(); // v-if on appointmentTypeQuestion ensures dates have been loaded by now
this.setDisplayWaitList(); // v-if on appointmentTypeQuestion ensures dates have been loaded by now
},
setSelectedDateToFirstAvailable() {
this.selectedDate = this.getFirstAvailableDate();
@ -2025,35 +2032,9 @@ export default {
watch: {
appointmentTypeFromAppointmentTypeQuestion: {
handler(newValue, oldValue) {
this.handleAppointmentTypeChange(newValue);
this.handleAppointmentTypeChange(newValue); // v-if on appointmentTypeQuestion ensures dates have been loaded by now
},
},
selectedDate(newValue, oldValue) {
// Clear time slot selection if date selected changes
const selectedDate = this.getSelectedDateFromStore();
if (oldValue && this.appointmentType === AppointmentTypeStrings.MOBILE) {
oldValue = `${oldValue}-mobile`;
}
const hasValueChanged = newValue !== oldValue;
const isDateDifferent = (newValue || oldValue) !== selectedDate;
if (hasValueChanged && isDateDifferent && !this.selectedMobileFirstAppointment) {
this.selectedTimeSlotInfo = {
timeSlot: {
date: null,
routeCode: null,
startTime: null,
endTime: null,
jobMaxMinutes: null,
jobMinMinutes: null,
},
isPremiumAppointment: null,
};
}
},
selectedTimeSlotInfo(newValue) {
this.updateFooterButtonText(newValue);
},
},
components: {
funnelHeader,

View file

@ -1,6 +1,7 @@
<template>
<div class="time-slots-question">
<buttonQuestion
ref="chooseDropOffOrInshop"
v-if="isDropOffAppointmentAvailable"
v-model="selectedAnswerForDropOffOrInshop"
@update:modelValue="dropOffSelectionChanged"
@ -23,8 +24,9 @@
</div>
</buttonQuestion>
<buttonQuestion
ref="buttonQuestion"
v-if="shouldDisplayTimeSlotQuestion"
ref="chooseTimeSlot"
v-if="displayTimeSlotQuestion"
v-model="selectedAnswerForTimeSlots"
@update:modelValue="timeSlotSelectionChanged"
buttonTypeString="timeSlotModalListButton"
:buttonTypeObject="timeSlotModalListButton"
@ -37,7 +39,6 @@
:lazyLoad="{ isLazyLoad: !isMobileAppointment, amountToLoad: 10 }"
groupName="chooseTimeSlot"
textPosition="text-center"
v-model="selectedAnswerForTimeSlots"
questionText="Available times:"
isRequired
validationRules="time-slot-required" />
@ -389,7 +390,7 @@ export default {
this.answersForDropOffQuestion[0].value !== PICK_A_TIME_BUTTON_VALUE
);
},
shouldDisplayTimeSlotQuestion() {
displayTimeSlotQuestion() {
return (
this.selectedAnswerForDropOffOrInshop == PICK_A_TIME_BUTTON_VALUE ||
!this.isDropOffAppointmentAvailable

View file

@ -80,6 +80,7 @@ export default {
},
set: function (newValue) {
this.$emit("update:modelValue", newValue);
this.$emit("handle-appointment-type-change", newValue);
},
},
isMobileOnly() {

View file

@ -569,6 +569,10 @@ const routingTable = function () {
piaError: "true",
},
},
{
scenario: navigationScenarios.CLICKED_PAY_LATER,
destinationPageData: routeData.CONFIRMATION,
},
],
},
{
@ -589,6 +593,10 @@ const routingTable = function () {
piaError: "true",
},
},
{
scenario: navigationScenarios.CLICKED_PAY_LATER,
destinationPageData: routeData.CONFIRMATION,
},
],
},
{