drop off updates for schedule page
Morning Drop off.
This commit is contained in:
parent
63e2f36c19
commit
ff6dca7650
4 changed files with 182 additions and 75 deletions
|
|
@ -99,9 +99,9 @@
|
|||
</div>
|
||||
<template
|
||||
v-for="timeSlot in selectableTimeSlotsData"
|
||||
:key="timeSlot.startTime">
|
||||
:key="`${timeSlot.startTime}-${timeSlot.isDropoff}`">
|
||||
<input
|
||||
:id="`timeslot${timeSlot.startTime}`"
|
||||
:id="`timeslot${timeSlot.startTime}-${timeSlot.isDropoff}`"
|
||||
v-model="selectedTime"
|
||||
type="radio"
|
||||
name="time-slot"
|
||||
|
|
@ -114,9 +114,14 @@
|
|||
class="time-slot-button"
|
||||
:class="[checkIsSelectedTimeSlot(timeSlot) ? 'selected-time-slot' : ''
|
||||
, {'has-date-error': showTimeSlotError}]"
|
||||
@click="selectTimeSlotForDay(timeSlot)">
|
||||
{{ displayTimeSlotTime(timeSlot) }}
|
||||
@click="selectTimeSlotForDay(timeSlot)"
|
||||
v-html="displayTimeSlotTime(timeSlot)">
|
||||
</label>
|
||||
<div
|
||||
v-if="timeSlot.isDropoff"
|
||||
class="time-slot-drop-off-information"
|
||||
v-html="displayDropOffInformation(timeSlot)">
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="row form-test-error">
|
||||
|
|
@ -256,6 +261,10 @@ export default {
|
|||
appointmentEstimate() {
|
||||
return getDisplayTextForDurationLength(this.appointmentDurationMinutesMinimum, this.appointmentDurationMinutesMaximum);
|
||||
},
|
||||
calendarViewDirection() {
|
||||
if (this.selectableDatesSetting === 'custom') return 'future';
|
||||
return 'past';
|
||||
},
|
||||
daysToAdd() {
|
||||
return this.isMobileView ? this.daysInViewMobile : this.daysInViewStandard;
|
||||
},
|
||||
|
|
@ -284,10 +293,6 @@ export default {
|
|||
this.todayOverrideDateString
|
||||
|| convertDateToDateString(new Date())
|
||||
);
|
||||
},
|
||||
calendarViewDirection() {
|
||||
if (this.selectableDatesSetting === 'custom') return 'future';
|
||||
return 'past';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -301,16 +306,16 @@ export default {
|
|||
this.findFirstAvailableDateInView();
|
||||
}
|
||||
},
|
||||
selectedDate(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
this.$emit('dateSelected', newValue);
|
||||
}
|
||||
},
|
||||
selectedTimeSlot(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
const testObj = this.getSelectedTimeSlotInfoObject(newValue);
|
||||
this.$emit('timeSlotSelected', testObj);
|
||||
}
|
||||
},
|
||||
selectedDate(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
this.$emit('dateSelected', newValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -340,50 +345,44 @@ export default {
|
|||
addPremiumFlagToInput(routeCode) {
|
||||
return (`${routeCode}${PREMIUM_TIME_SLOT_ID_FLAG}`);
|
||||
},
|
||||
removePremiumFlagFromInput(routeCode) {
|
||||
return routeCode.replace(PREMIUM_TIME_SLOT_ID_FLAG, '');
|
||||
checkIsSelectedDay(index, timeOfDayGrouping) {
|
||||
const dateToShowString = this.getDateToShowString(index);
|
||||
return this.selectedDate === dateToShowString && this.selectedTimeOfDayGrouping === timeOfDayGrouping;
|
||||
},
|
||||
getSelectedTimeSlotInfoObject(timeSlot) {
|
||||
const routeCode = timeSlot?.id;
|
||||
let routeCodeToUse = routeCode;
|
||||
const routeCodeIncludesPremium = routeCode?.includes(PREMIUM_TIME_SLOT_ID_FLAG);
|
||||
if (routeCodeIncludesPremium) {
|
||||
routeCodeToUse = this.removePremiumFlagFromInput(routeCode);
|
||||
checkIsSelectedTimeSlot(timeSlot) {
|
||||
if (!this.selectedTimeSlot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fullTimeSlot = this.selectableTimeSlotsData?.find((ts) => ts.id === routeCodeToUse);
|
||||
|
||||
if (fullTimeSlot) {
|
||||
return {
|
||||
timeSlot: {
|
||||
date: this.selectedDate,
|
||||
routeCode: fullTimeSlot.id,
|
||||
startTime: fullTimeSlot.startTime,
|
||||
endTime: fullTimeSlot.endTime,
|
||||
jobMaxMinutes: this.appointmentDurationMinutesMaximum.toString(),
|
||||
jobMinMinutes: this.appointmentDurationMinutesMinimum.toString()
|
||||
},
|
||||
isPremiumAppointment: !!routeCodeIncludesPremium
|
||||
};
|
||||
return (this.selectedTimeSlot.isDropoff === timeSlot.isDropoff
|
||||
&& this.selectedTimeSlot.startTime === timeSlot.startTime
|
||||
&& this.selectedTimeSlot.timeOfDay === timeSlot.timeOfDay);
|
||||
},
|
||||
displayDropOffInformation(timeSlot) {
|
||||
if (timeSlot.isDropoff) {
|
||||
if (timeSlot.timeOfDay === 'morning') {
|
||||
return this.getCmsContent(
|
||||
'DropOffTimeSlotModal',
|
||||
'BodyText'
|
||||
);
|
||||
}
|
||||
return this.getCmsContent(
|
||||
'OvernightDropOffTimeSlotModal',
|
||||
'BodyText'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
timeSlot: {
|
||||
date: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
routeCode: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null
|
||||
},
|
||||
isPremiumAppointment: null
|
||||
};
|
||||
return '';
|
||||
},
|
||||
displayTimeSlotTime(timeSlot) {
|
||||
const appointmentType = this.activeAppointmentType || AppointmentTypeStrings.IN_SHOP;
|
||||
if (appointmentType === AppointmentTypeStrings.MOBILE || appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||
return `${militaryToTwelveHourTime(timeSlot.startTime)} - ${militaryToTwelveHourTime(timeSlot.endTime)}`;
|
||||
}
|
||||
if (timeSlot.isDropoff) {
|
||||
if (timeSlot.timeOfDay === 'morning') {
|
||||
return '<span class="dropoff-label">Drop & Go<sup>™</sup></span>';
|
||||
}
|
||||
return '<span class="dropoff-label">Overnight drop off</span>';
|
||||
}
|
||||
return militaryToTwelveHourTime(timeSlot.startTime);
|
||||
},
|
||||
findFirstAvailableDateInView() {
|
||||
|
|
@ -436,8 +435,7 @@ export default {
|
|||
if (!initialTimeSlot || !initialTimeSlot.startTime) {
|
||||
return;
|
||||
}
|
||||
const initialStartTime = initialTimeSlot.startTime;
|
||||
const foundTimeSlot = timeSlots.find((ts) => ts.startTime === initialStartTime);
|
||||
const foundTimeSlot = timeSlots.find((ts) => ts.startTime === initialTimeSlot.startTime && ts.endTime === initialTimeSlot.endTime);
|
||||
if (foundTimeSlot) {
|
||||
this.selectTimeSlotForDay(foundTimeSlot);
|
||||
}
|
||||
|
|
@ -452,6 +450,44 @@ export default {
|
|||
const dateToShow = this.getDateToShow(index);
|
||||
return convertDateToDateString(dateToShow);
|
||||
},
|
||||
getSelectedTimeSlotInfoObject(timeSlot) {
|
||||
const routeCode = timeSlot?.id;
|
||||
let routeCodeToUse = routeCode;
|
||||
const routeCodeIncludesPremium = routeCode?.includes(PREMIUM_TIME_SLOT_ID_FLAG);
|
||||
if (routeCodeIncludesPremium) {
|
||||
routeCodeToUse = this.removePremiumFlagFromInput(routeCode);
|
||||
}
|
||||
|
||||
const fullTimeSlot = this.selectableTimeSlotsData?.find((ts) => ts.id === routeCodeToUse);
|
||||
|
||||
if (fullTimeSlot) {
|
||||
return {
|
||||
timeSlot: {
|
||||
date: this.selectedDate,
|
||||
routeCode: fullTimeSlot.id,
|
||||
startTime: fullTimeSlot.startTime,
|
||||
endTime: fullTimeSlot.endTime,
|
||||
isDropoff: fullTimeSlot.isDropoff,
|
||||
jobMaxMinutes: this.appointmentDurationMinutesMaximum.toString(),
|
||||
jobMinMinutes: this.appointmentDurationMinutesMinimum.toString()
|
||||
},
|
||||
isPremiumAppointment: !!routeCodeIncludesPremium
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
timeSlot: {
|
||||
date: null,
|
||||
routeCode: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
isDropoff: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null
|
||||
},
|
||||
isPremiumAppointment: null
|
||||
};
|
||||
},
|
||||
async gotoNextPage() {
|
||||
const maxPageIndex = Math.floor((this.daysLoaded - 1) / this.daysToAdd);
|
||||
if (this.activePageIndex >= maxPageIndex) {
|
||||
|
|
@ -479,15 +515,15 @@ export default {
|
|||
this.selectedTimeSlot = null;
|
||||
this.findFirstAvailableDateInView();
|
||||
},
|
||||
checkIsSelectedDay(index, timeOfDayGrouping) {
|
||||
const dateToShowString = this.getDateToShowString(index);
|
||||
return this.selectedDate === dateToShowString && this.selectedTimeOfDayGrouping === timeOfDayGrouping;
|
||||
mapTimeSlot(timeSlot, timeOfDay) {
|
||||
return {
|
||||
...timeSlot,
|
||||
isDropoff: timeSlot.id.endsWith('DROP OFF'),
|
||||
timeOfDay
|
||||
};
|
||||
},
|
||||
checkIsSelectedTimeSlot(timeSlot) {
|
||||
if (!this.selectedTimeSlot) {
|
||||
return false;
|
||||
}
|
||||
return this.selectedTimeSlot.startTime === timeSlot.startTime;
|
||||
removePremiumFlagFromInput(routeCode) {
|
||||
return routeCode.replace(PREMIUM_TIME_SLOT_ID_FLAG, '');
|
||||
},
|
||||
selectTimeSlotForDay(timeSlot) {
|
||||
if (timeSlot) {
|
||||
|
|
@ -567,13 +603,28 @@ export default {
|
|||
morningTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
|
||||
const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
|
||||
return timeHour < 12;
|
||||
}),
|
||||
}).map((timeSlot) => this.mapTimeSlot(timeSlot, 'morning')),
|
||||
afternoonTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
|
||||
const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
|
||||
return timeHour >= 12;
|
||||
}),
|
||||
}).map((timeSlot) => this.mapTimeSlot(timeSlot, 'afternoon')),
|
||||
isSelected: false
|
||||
};
|
||||
|
||||
if (dateObjectToPush.morningTimeSlots.length > 0) {
|
||||
const findIndex = dateObjectToPush.morningTimeSlots.findIndex((timeSlot) => timeSlot.id.endsWith('DROP OFF'));
|
||||
if (findIndex !== -1) {
|
||||
const dropOffSlot = dateObjectToPush.morningTimeSlots.splice(findIndex, 1)[0];
|
||||
dateObjectToPush.morningTimeSlots.unshift(dropOffSlot);
|
||||
}
|
||||
}
|
||||
if (dateObjectToPush.afternoonTimeSlots.length > 0) {
|
||||
const findIndex = dateObjectToPush.afternoonTimeSlots.findIndex((timeSlot) => timeSlot.id.endsWith('DROP OFF'));
|
||||
if (findIndex !== -1) {
|
||||
const dropOffSlot = dateObjectToPush.afternoonTimeSlots.splice(findIndex, 1)[0];
|
||||
dateObjectToPush.afternoonTimeSlots.push(dropOffSlot);
|
||||
}
|
||||
}
|
||||
this.selectableDatesData.push(dateObjectToPush);
|
||||
});
|
||||
|
||||
|
|
@ -635,14 +686,28 @@ export default {
|
|||
morningTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
|
||||
const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
|
||||
return timeHour < 12;
|
||||
}),
|
||||
}).map((timeSlot) => this.mapTimeSlot(timeSlot, 'morning')),
|
||||
afternoonTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
|
||||
const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
|
||||
return timeHour >= 12;
|
||||
}),
|
||||
}).map((timeSlot) => this.mapTimeSlot(timeSlot, 'afternoon')),
|
||||
isSelected: false
|
||||
};
|
||||
|
||||
if (dateObjectToPush.morningTimeSlots.length > 0) {
|
||||
const findIndex = dateObjectToPush.morningTimeSlots.findIndex((timeSlot) => timeSlot.id.endsWith('DROP OFF'));
|
||||
if (findIndex !== -1) {
|
||||
const dropOffSlot = dateObjectToPush.morningTimeSlots.splice(findIndex, 1)[0];
|
||||
dateObjectToPush.morningTimeSlots.unshift(dropOffSlot);
|
||||
}
|
||||
}
|
||||
if (dateObjectToPush.afternoonTimeSlots.length > 0) {
|
||||
const findIndex = dateObjectToPush.afternoonTimeSlots.findIndex((timeSlot) => timeSlot.id.endsWith('DROP OFF'));
|
||||
if (findIndex !== -1) {
|
||||
const dropOffSlot = dateObjectToPush.afternoonTimeSlots.splice(findIndex, 1)[0];
|
||||
dateObjectToPush.afternoonTimeSlots.push(dropOffSlot);
|
||||
}
|
||||
}
|
||||
this.selectableDatesData.push(dateObjectToPush);
|
||||
}
|
||||
});
|
||||
|
|
@ -832,16 +897,55 @@ export default {
|
|||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
:deep(.dropoff-label) {
|
||||
sup {
|
||||
top: -0.375rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
& + .time-slot-drop-off-information {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.75s ease-in-out;
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
color: $darker-gray;
|
||||
|
||||
:deep(ul) {
|
||||
margin: 0;
|
||||
margin-bottom: 0.375rem;
|
||||
|
||||
> li {
|
||||
padding-left: 0.625rem;
|
||||
margin-top: 0.625rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected-time-slot {
|
||||
background-color: $background-color-selected;
|
||||
border: solid 1px #0070d1;
|
||||
color:#000;
|
||||
font-weight: 500;
|
||||
|
||||
:deep(.dropoff-label) {
|
||||
sup {
|
||||
top: .25rem;
|
||||
font-size: 1.625rem;
|
||||
}
|
||||
}
|
||||
|
||||
& + .time-slot-drop-off-information {
|
||||
max-height: 12rem;
|
||||
transition: max-height 0.75s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-date-error {
|
||||
border: 1px solid #d93025;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<div class="fade-on-route-transition">
|
||||
<div class="justify-content-center">
|
||||
<siteHeader
|
||||
class="header"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
<div class="iss-heritage-container-width">
|
||||
|
|
@ -176,9 +175,7 @@ const getAvailableDates = async (
|
|||
storeAction.payload.endDate,
|
||||
storeAction.payload.shopAppointmentType,
|
||||
storeAction.payload.providerNumber
|
||||
).catch(() => {
|
||||
console.warn('Error fetching shop time slots...');
|
||||
});
|
||||
);
|
||||
} else if (storeAction.payload?.zipCodeOverride) {
|
||||
timeSlotsResponse = await useMainStore().getMobileTimeSlots(
|
||||
storeAction.payload.startDate,
|
||||
|
|
@ -343,7 +340,7 @@ export default {
|
|||
&& (((this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)
|
||||
&& serviceLocationToUse.mobileProviderNumber)
|
||||
|| (this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP
|
||||
|| ((this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP || this.selectedAppointmentType === AppointmentTypeStrings.DROP_OFF)
|
||||
&& (this.selectedProvider?.providerNumber || serviceLocationToUse.provider?.providerNumber)));
|
||||
|
||||
const damageInfo = useMainStore().order.damage.isRepair
|
||||
|
|
@ -652,8 +649,13 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
// Save service location then schedule and navigate forward
|
||||
await this.$refs.serviceLocation.forwardButtonAction();
|
||||
let appointmentTypeToUse = this.selectedAppointmentType;
|
||||
if (appointmentTypeToUse === AppointmentTypeStrings.IN_SHOP && this.selectedTimeSlotInfo.timeSlot?.isDropoff === true) {
|
||||
appointmentTypeToUse = AppointmentTypeStrings.DROP_OFF;
|
||||
}
|
||||
|
||||
// Save service location then save schedule then navigate forward
|
||||
await this.$refs.serviceLocation.forwardButtonAction(appointmentTypeToUse);
|
||||
this.mainStore.saveSchedule(this.selectedTimeSlotInfo.timeSlot);
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ export default {
|
|||
}
|
||||
},
|
||||
selectedAppointmentType(newValue, oldValue) {
|
||||
if (this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP && this.selectedProvider && this.availabilityRating === null) {
|
||||
if (this.isInshop && this.selectedProvider && this.availabilityRating === null) {
|
||||
this.refreshAvailabilityRating();
|
||||
|
||||
const appointmenTypeServiceLocationObj = {
|
||||
|
|
@ -336,7 +336,7 @@ export default {
|
|||
},
|
||||
selectedProvider(newProvider, oldProvider) {
|
||||
if (newProvider?.providerNumber !== oldProvider?.providerNumber || this.availabilityRating === null) {
|
||||
const appointmentIsInshop = this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP;
|
||||
const appointmentIsInshop = this.isInshop;
|
||||
const returnedProvider = {
|
||||
provider: newProvider,
|
||||
refreshDatePicker: appointmentIsInshop && oldProvider?.providerNumber !== null
|
||||
|
|
@ -358,7 +358,7 @@ export default {
|
|||
await this.setData(initialData);
|
||||
this.initializingData = false;
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
async forwardButtonAction(appointmentType) {
|
||||
let provider = this.selectedProvider;
|
||||
this.mainStore.updateMobileFee(null);
|
||||
if (this.isMobile) {
|
||||
|
|
@ -382,7 +382,7 @@ export default {
|
|||
state: this.state,
|
||||
zipCode: this.zipCode,
|
||||
zipCodeCtu: this.zipCodeCtu,
|
||||
appointmentType: this.selectedAppointmentType,
|
||||
appointmentType: appointmentType || this.selectedAppointmentType,
|
||||
provider
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -965,7 +965,8 @@ export const useMainStore = defineStore({
|
|||
providerNumber,
|
||||
startDate,
|
||||
endDate,
|
||||
shopAppointmentType,
|
||||
shopAppointmentType: (shopAppointmentType === AppointmentTypeStrings.IN_SHOP
|
||||
|| shopAppointmentType === AppointmentTypeStrings.DROP_OFF) ? 'InShopOrDropoff' : shopAppointmentType,
|
||||
applicationName: applicationConfig.APPLICATION_NAME,
|
||||
billToAccountNumber: this.billToAccountNumber,
|
||||
parentAccountNumber: this.order.parentAccountNumber, // this.payment.parentAccountNumber,
|
||||
|
|
@ -1605,7 +1606,7 @@ export const useMainStore = defineStore({
|
|||
order.customer.firstName = data?.customer?.firstName;
|
||||
order.customer.lastName = data?.customer?.lastName;
|
||||
order.customer.emailAddress = data?.customer?.emailAddress;
|
||||
|
||||
|
||||
order.contactInfo.extension = data?.customer?.homePhone?.slice(10);
|
||||
order.contactInfo.homePhone = data?.customer?.homePhone?.slice(0, 10);
|
||||
order.contactInfo.servicePhone = data?.customer?.servicePhone;
|
||||
|
|
|
|||
Loading…
Reference in a new issue