Merge branch 'develop' into dependabot/npm_and_yarn/eslint-9.26.0
This commit is contained in:
commit
e74f83cc66
38 changed files with 1839 additions and 2815 deletions
1688
package-lock.json
generated
1688
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -66,7 +66,7 @@ const bailoutMessage = Object.freeze({
|
||||||
message: 'User selected to continue a referral where a TPA shop was previously selected.'
|
message: 'User selected to continue a referral where a TPA shop was previously selected.'
|
||||||
}),
|
}),
|
||||||
vehicleYMMSLookupError: (year, make, model, style, error) => {
|
vehicleYMMSLookupError: (year, make, model, style, error) => {
|
||||||
const baseMessage = "An error occurred looking up vehicle";
|
const baseMessage = 'An error occurred looking up vehicle';
|
||||||
const errorMessage = `Error: ${getItemData(error)}`;
|
const errorMessage = `Error: ${getItemData(error)}`;
|
||||||
|
|
||||||
const getMessage = (year, make, model, style) => {
|
const getMessage = (year, make, model, style) => {
|
||||||
|
|
@ -81,7 +81,7 @@ const bailoutMessage = Object.freeze({
|
||||||
code: bailoutCode.VehicleYMMSLookupError,
|
code: bailoutCode.VehicleYMMSLookupError,
|
||||||
message: getMessage(year, make, model, style)
|
message: getMessage(year, make, model, style)
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default bailoutMessage;
|
export default bailoutMessage;
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,6 @@ export const pageProgressMapper = {
|
||||||
'provider-preference': {
|
'provider-preference': {
|
||||||
percent: 60
|
percent: 60
|
||||||
},
|
},
|
||||||
'service-location': {
|
|
||||||
percent: 65
|
|
||||||
},
|
|
||||||
'schedule-page': {
|
'schedule-page': {
|
||||||
percent: 70
|
percent: 70
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,10 @@ import { selectableDaysOptions } from './mixins/helpers';
|
||||||
export default {
|
export default {
|
||||||
name: 'date-picker',
|
name: 'date-picker',
|
||||||
props: {
|
props: {
|
||||||
|
activeAppointmentType: {
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
customComponentId: String,
|
customComponentId: String,
|
||||||
selectableDatesSetting: {
|
selectableDatesSetting: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
@ -161,6 +165,10 @@ export default {
|
||||||
},
|
},
|
||||||
default: selectableDaysOptions.PAST
|
default: selectableDaysOptions.PAST
|
||||||
},
|
},
|
||||||
|
isMobileView: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object
|
type: Object
|
||||||
},
|
},
|
||||||
|
|
@ -241,8 +249,7 @@ export default {
|
||||||
daysLoaded: 0,
|
daysLoaded: 0,
|
||||||
appointmentDurationMinutesMinimum: 90,
|
appointmentDurationMinutesMinimum: 90,
|
||||||
appointmentDurationMinutesMaximum: 120,
|
appointmentDurationMinutesMaximum: 120,
|
||||||
initialDaysToLoad: 15,
|
initialDaysToLoad: 15
|
||||||
isMobileView: false
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -284,6 +291,16 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
isMobileView(newValue, oldValue) {
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
this.activePageIndex = 0;
|
||||||
|
this.selectedDate = null;
|
||||||
|
this.selectedTimeOfDayGrouping = null;
|
||||||
|
this.selectedTime = null;
|
||||||
|
this.selectedTimeSlot = null;
|
||||||
|
this.findFirstAvailableDateInView();
|
||||||
|
}
|
||||||
|
},
|
||||||
selectedTimeSlot(newValue, oldValue) {
|
selectedTimeSlot(newValue, oldValue) {
|
||||||
if (newValue !== oldValue) {
|
if (newValue !== oldValue) {
|
||||||
const testObj = this.getSelectedTimeSlotInfoObject(newValue);
|
const testObj = this.getSelectedTimeSlotInfoObject(newValue);
|
||||||
|
|
@ -296,20 +313,30 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
this.mql = window.matchMedia('(min-width: 1200px)');
|
|
||||||
this.isMobileView = !this.mql.matches;
|
|
||||||
this.mql.addEventListener('change', this.handleMqlChange);
|
|
||||||
},
|
|
||||||
unmounted() {
|
|
||||||
if (this.mql) {
|
|
||||||
this.mql.removeEventListener('change', this.handleMqlChange);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
initializeComponent(initialData) {
|
initializeComponent(initialData) {
|
||||||
|
this.resetComponent();
|
||||||
this.setCalendarData(initialData);
|
this.setCalendarData(initialData);
|
||||||
},
|
},
|
||||||
|
resetComponent() {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.selectableDatesData = []; // NOTE: uses monthNum (1-based), NOT monthIndex (0-based)
|
||||||
|
this.selectableTimeSlotsData = [];
|
||||||
|
this.selectedTimeOfDayGrouping = null;
|
||||||
|
this.selectedDate = null;
|
||||||
|
this.selectedTime = null;
|
||||||
|
this.selectedTimeSlot = null;
|
||||||
|
this.activeDate = new Date();
|
||||||
|
this.activePageIndex = 0;
|
||||||
|
this.todaysDate = new Date();
|
||||||
|
this.mql = null;
|
||||||
|
this.daysInViewMobile = 3;
|
||||||
|
this.daysInViewStandard = 5;
|
||||||
|
this.daysLoaded = 0;
|
||||||
|
this.appointmentDurationMinutesMinimum = 90;
|
||||||
|
this.appointmentDurationMinutesMaximum = 120;
|
||||||
|
this.initialDaysToLoad = 15;
|
||||||
|
},
|
||||||
addPremiumFlagToInput(routeCode) {
|
addPremiumFlagToInput(routeCode) {
|
||||||
return (`${routeCode}${PREMIUM_TIME_SLOT_ID_FLAG}`);
|
return (`${routeCode}${PREMIUM_TIME_SLOT_ID_FLAG}`);
|
||||||
},
|
},
|
||||||
|
|
@ -352,17 +379,8 @@ export default {
|
||||||
isPremiumAppointment: null
|
isPremiumAppointment: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
handleMqlChange(e) {
|
|
||||||
this.isMobileView = !e.matches;
|
|
||||||
this.activePageIndex = 0;
|
|
||||||
this.selectedDate = null;
|
|
||||||
this.selectedTimeOfDayGrouping = null;
|
|
||||||
this.selectedTime = null;
|
|
||||||
this.selectedTimeSlot = null;
|
|
||||||
this.findFirstAvailableDateInView();
|
|
||||||
},
|
|
||||||
displayTimeSlotTime(timeSlot) {
|
displayTimeSlotTime(timeSlot) {
|
||||||
const { appointmentType } = this.mainStore.order.serviceLocation;
|
const appointmentType = this.activeAppointmentType || AppointmentTypeStrings.IN_SHOP;
|
||||||
if (appointmentType === AppointmentTypeStrings.MOBILE || appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
if (appointmentType === AppointmentTypeStrings.MOBILE || appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||||
return `${militaryToTwelveHourTime(timeSlot.startTime)} - ${militaryToTwelveHourTime(timeSlot.endTime)}`;
|
return `${militaryToTwelveHourTime(timeSlot.startTime)} - ${militaryToTwelveHourTime(timeSlot.endTime)}`;
|
||||||
}
|
}
|
||||||
|
|
@ -434,38 +452,6 @@ export default {
|
||||||
const dateToShow = this.getDateToShow(index);
|
const dateToShow = this.getDateToShow(index);
|
||||||
return convertDateToDateString(dateToShow);
|
return convertDateToDateString(dateToShow);
|
||||||
},
|
},
|
||||||
getEndDateForExistingDate(startDate, selectedDateString, daysInView) {
|
|
||||||
const endDate = new Date(startDate);
|
|
||||||
endDate.setDate(endDate.getDate() + (daysInView - 1));
|
|
||||||
|
|
||||||
if (selectedDateString) {
|
|
||||||
const selectedDate = new Date(`${selectedDateString}T00:00:00`);
|
|
||||||
const daysDifferenceComparedToStartDate = Math.ceil((selectedDate - startDate) / (1000 * 60 * 60 * 24));
|
|
||||||
if (selectedDate > endDate) {
|
|
||||||
const daysDifferenceComparedToStartDateAsPages = Math.ceil(daysDifferenceComparedToStartDate / daysInView);
|
|
||||||
const newEndDate = new Date(startDate);
|
|
||||||
newEndDate.setDate(newEndDate.getDate() + (daysDifferenceComparedToStartDateAsPages * daysInView) - 1);
|
|
||||||
|
|
||||||
return {
|
|
||||||
endDateString: convertDateToDateString(newEndDate),
|
|
||||||
newDaysLoaded: (daysDifferenceComparedToStartDateAsPages * daysInView),
|
|
||||||
daysFromStart: daysDifferenceComparedToStartDate
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
endDateString: convertDateToDateString(endDate),
|
|
||||||
newDaysLoaded: null,
|
|
||||||
daysFromStart: daysDifferenceComparedToStartDate
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
endDateString: convertDateToDateString(endDate),
|
|
||||||
newDaysLoaded: null,
|
|
||||||
daysFromStart: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
async gotoNextPage() {
|
async gotoNextPage() {
|
||||||
const maxPageIndex = Math.floor((this.daysLoaded - 1) / this.daysToAdd);
|
const maxPageIndex = Math.floor((this.daysLoaded - 1) / this.daysToAdd);
|
||||||
if (this.activePageIndex >= maxPageIndex) {
|
if (this.activePageIndex >= maxPageIndex) {
|
||||||
|
|
@ -572,66 +558,7 @@ export default {
|
||||||
timeSlotInputChanged(timeSlot) {
|
timeSlotInputChanged(timeSlot) {
|
||||||
this.selectTimeSlotForDay(timeSlot);
|
this.selectTimeSlotForDay(timeSlot);
|
||||||
},
|
},
|
||||||
async loadInitialData(config) {
|
|
||||||
/*
|
|
||||||
** NOTE: this _could_ be called by a parent before fully loaded, so data or computeds might not be available
|
|
||||||
*/
|
|
||||||
let todayDateString;
|
|
||||||
const todayDateObject = new Date();
|
|
||||||
const calendarViewDirection = 'future';
|
|
||||||
const initialDays = 15;
|
|
||||||
|
|
||||||
if (this.todayString) {
|
|
||||||
todayDateString = this.todayString;
|
|
||||||
} else if (config.todayOverrideDateString) {
|
|
||||||
todayDateString = config.todayOverrideDateString;
|
|
||||||
} else {
|
|
||||||
todayDateString = convertDateToDateString(todayDateObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialViewStartDate = todayDateString;
|
|
||||||
const initialEndDate = new Date();
|
|
||||||
initialEndDate.setDate(initialEndDate.getDate() + (initialDays - 1));
|
|
||||||
let initialViewEndDate = convertDateToDateString(initialEndDate);
|
|
||||||
|
|
||||||
const endDateObject = this.getEndDateForExistingDate(
|
|
||||||
todayDateObject,
|
|
||||||
config.preSelectedDate,
|
|
||||||
initialDays
|
|
||||||
);
|
|
||||||
|
|
||||||
if (endDateObject.endDateString !== initialViewEndDate) {
|
|
||||||
initialViewEndDate = endDateObject.endDateString;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadInitialDataPromise = new Promise((resolve) => {
|
|
||||||
const response = config.customSelectableDatesCallback(
|
|
||||||
initialViewStartDate,
|
|
||||||
initialViewEndDate,
|
|
||||||
useMainStore().order.serviceLocation.appointmentType,
|
|
||||||
useMainStore().order.serviceLocation.provider.providerNumber
|
|
||||||
);
|
|
||||||
resolve(response);
|
|
||||||
});
|
|
||||||
|
|
||||||
return loadInitialDataPromise.then((response) => {
|
|
||||||
const initialData = {
|
|
||||||
todayDate: todayDateString,
|
|
||||||
initialViewStartDate,
|
|
||||||
initialViewEndDate,
|
|
||||||
calendarViewDirection,
|
|
||||||
initialShopTimeSlotsResponse: response,
|
|
||||||
preSelectedDate: config.preSelectedDate,
|
|
||||||
initialDaysLoaded: endDateObject.newDaysLoaded || initialDays,
|
|
||||||
daysFromStart: endDateObject.daysFromStart || null
|
|
||||||
};
|
|
||||||
|
|
||||||
return initialData;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
async setCalendarData(config = {}) {
|
async setCalendarData(config = {}) {
|
||||||
const initialMql = window.matchMedia('(min-width: 1200px)');
|
|
||||||
this.isMobileView = !initialMql.matches;
|
|
||||||
config.initialShopTimeSlotsResponse.days.forEach((selectableDate) => {
|
config.initialShopTimeSlotsResponse.days.forEach((selectableDate) => {
|
||||||
const dateObjectToPush = {
|
const dateObjectToPush = {
|
||||||
date: selectableDate.date,
|
date: selectableDate.date,
|
||||||
|
|
@ -663,8 +590,11 @@ export default {
|
||||||
this.findInitialDate(config.preSelectedDate, pageIndexObj.initialDayIndex);
|
this.findInitialDate(config.preSelectedDate, pageIndexObj.initialDayIndex);
|
||||||
} else {
|
} else {
|
||||||
this.findFirstAvailableDateInView();
|
this.findFirstAvailableDateInView();
|
||||||
while (!this.selectedDate) {
|
let attempts = 0;
|
||||||
this.gotoNextPage();
|
while (!this.selectedDate && attempts < 5) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await this.gotoNextPage();
|
||||||
|
attempts += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,9 +623,7 @@ export default {
|
||||||
const moreSelectableDates =
|
const moreSelectableDates =
|
||||||
await this.customSelectableDatesCallback(
|
await this.customSelectableDatesCallback(
|
||||||
dateStart,
|
dateStart,
|
||||||
dateEnd,
|
dateEnd
|
||||||
this.mainStore.order.serviceLocation.appointmentType,
|
|
||||||
this.mainStore.order.serviceLocation.provider.providerNumber
|
|
||||||
);
|
);
|
||||||
|
|
||||||
moreSelectableDates.days.forEach((selectableDate) => {
|
moreSelectableDates.days.forEach((selectableDate) => {
|
||||||
|
|
@ -899,7 +827,7 @@ export default {
|
||||||
border-radius: $border-radius-list-button;
|
border-radius: $border-radius-list-button;
|
||||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, .2);
|
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, .2);
|
||||||
color: #525656;
|
color: #525656;
|
||||||
padding: 0.5rem 0;
|
padding: 0.625rem 0;
|
||||||
margin-top: 0.625rem;
|
margin-top: 0.625rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ export function getMobileFeeLineItem(order) {
|
||||||
* @returns {number|undefined|null} current deductible
|
* @returns {number|undefined|null} current deductible
|
||||||
*/
|
*/
|
||||||
export function getDeductible(order) {
|
export function getDeductible(order) {
|
||||||
return order.currentDeductible;
|
return order.damage.isRepair ? order.currentDeductible.repair : order.currentDeductible.replace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -239,8 +239,13 @@ describe('cart-helper', () => {
|
||||||
describe('getDeductible', () => {
|
describe('getDeductible', () => {
|
||||||
test('Returns deductible on the order', () => {
|
test('Returns deductible on the order', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const deductible = 100;
|
const deductible = {
|
||||||
|
replace: 100
|
||||||
|
};
|
||||||
const order = {
|
const order = {
|
||||||
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
currentDeductible: deductible
|
currentDeductible: deductible
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -249,7 +254,7 @@ describe('cart-helper', () => {
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(result).not.toBeNull();
|
expect(result).not.toBeNull();
|
||||||
expect(result).toBe(deductible);
|
expect(result).toBe(deductible.replace);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -349,7 +354,12 @@ describe('cart-helper', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: type
|
coverageType: type
|
||||||
},
|
},
|
||||||
currentDeductible: 100,
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100
|
||||||
|
},
|
||||||
lineItems: nullLineItems
|
lineItems: nullLineItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -373,7 +383,12 @@ describe('cart-helper', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: type
|
coverageType: type
|
||||||
},
|
},
|
||||||
currentDeductible: 100,
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100
|
||||||
|
},
|
||||||
lineItems: emptyLineItems
|
lineItems: emptyLineItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -397,7 +412,12 @@ describe('cart-helper', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: type
|
coverageType: type
|
||||||
},
|
},
|
||||||
currentDeductible: 100,
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100
|
||||||
|
},
|
||||||
lineItems: defaultLineItems
|
lineItems: defaultLineItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -495,7 +515,12 @@ describe('cart-helper', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: type
|
coverageType: type
|
||||||
},
|
},
|
||||||
currentDeductible: 100,
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100
|
||||||
|
},
|
||||||
lineItems: nullLineItems
|
lineItems: nullLineItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -520,7 +545,12 @@ describe('cart-helper', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: type
|
coverageType: type
|
||||||
},
|
},
|
||||||
currentDeductible: 100,
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100
|
||||||
|
},
|
||||||
lineItems: emptyLineItems
|
lineItems: emptyLineItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -545,7 +575,12 @@ describe('cart-helper', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: type
|
coverageType: type
|
||||||
},
|
},
|
||||||
currentDeductible: 100,
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100
|
||||||
|
},
|
||||||
lineItems: defaultLineItems
|
lineItems: defaultLineItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@ function mapStringToState(str) {
|
||||||
const valueFromStore = getStoreValueFromString(match[2]);
|
const valueFromStore = getStoreValueFromString(match[2]);
|
||||||
if (!valueFromStore) {
|
if (!valueFromStore) {
|
||||||
console.warn('Unable to resolve global state data.');
|
console.warn('Unable to resolve global state data.');
|
||||||
|
console.warn(`Tried to resolve: ${match[2]}`);
|
||||||
return ''; // if we can't map our string to state data, return an empty string.
|
return ''; // if we can't map our string to state data, return an empty string.
|
||||||
}
|
}
|
||||||
const stringWithReplacement = str.replace(match[0], valueFromStore);
|
const stringWithReplacement = str.replace(match[0], valueFromStore);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,17 @@ export function createOrderedListFromStringOfParagraphs(stringOfParagraphs) {
|
||||||
return `<ol>${stringOfParagraphs.replaceAll('<p></p>', '').replaceAll('<p>', '<li>').replaceAll('</p>', '</li>')}</ol>`;
|
return `<ol>${stringOfParagraphs.replaceAll('<p></p>', '').replaceAll('<p>', '<li>').replaceAll('</p>', '</li>')}</ol>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function createUnorderedListFromStringOfParagraphs
|
||||||
|
* @summary
|
||||||
|
* Returns string with <p> tags changed to <li> and wrapped in an <ul>
|
||||||
|
* @param {string} stringOfParagraphs single string with 1 to N <p> tags
|
||||||
|
* @returns {string} converted string wrapped in an <ul>
|
||||||
|
*/
|
||||||
|
export function createUnorderedListFromStringOfParagraphs(stringOfParagraphs) {
|
||||||
|
return `<ul>${stringOfParagraphs.replaceAll('<p></p>', '').replaceAll('<p>', '<li>').replaceAll('</p>', '</li>')}</ul>`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function toTitleCase
|
* @function toTitleCase
|
||||||
* @summary Returns title cased string version of 'text'
|
* @summary Returns title cased string version of 'text'
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,13 @@
|
||||||
|
|
||||||
exports[`coverageStatement.vue returns the initial data 1`] = `
|
exports[`coverageStatement.vue returns the initial data 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"CANCEL_CLAIM_REF_NAME": "CancelClaimModal",
|
|
||||||
"DEDUCTIBLE_MODAL_REF_NAME": "DeductibleModal",
|
|
||||||
"RECAL_MODAL_REF_NAME": "RecalModal",
|
"RECAL_MODAL_REF_NAME": "RecalModal",
|
||||||
"SITE_FOOTER_REF_NAME": "siteFooter",
|
|
||||||
"baseServiceLineItems": Array [],
|
"baseServiceLineItems": Array [],
|
||||||
"deductibleText": "Your deductible is",
|
|
||||||
"rules": Object {
|
|
||||||
"selectionRequired": "option-required",
|
|
||||||
},
|
|
||||||
"selectedProvider": "",
|
|
||||||
"widget": Object {
|
"widget": Object {
|
||||||
"disclaimerText": "DisclaimerWidget",
|
"disclaimerText": "DisclaimerWidget",
|
||||||
"explanatoryText": "ExplanatoryTextWidget",
|
"explanatoryText": "ExplanatoryTextWidget",
|
||||||
"nextStep": "NextStepsWidget",
|
"nextStep": "NextStepsWidget",
|
||||||
"serviceProviderQuestion": "ServiceProviderQuestion",
|
|
||||||
"subheader": "SiteSubHeaderWidget",
|
"subheader": "SiteSubHeaderWidget",
|
||||||
"verifiedItacAlert": "VerifiedITACAlert",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ jest.mock('@/helpers/cms-content-helper', () => ({
|
||||||
|
|
||||||
jest.mock('@/helpers/text-helper', () => ({
|
jest.mock('@/helpers/text-helper', () => ({
|
||||||
createOrderedListFromStringOfParagraphs: jest.fn(),
|
createOrderedListFromStringOfParagraphs: jest.fn(),
|
||||||
|
createUnorderedListFromStringOfParagraphs: jest.fn(),
|
||||||
formatAmountInDollars: jest.fn()
|
formatAmountInDollars: jest.fn()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -98,9 +99,6 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu
|
||||||
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
||||||
|
|
||||||
const wrapper = shallowMount(coverageStatement, mountOptions);
|
const wrapper = shallowMount(coverageStatement, mountOptions);
|
||||||
wrapper.vm.$refs[CANCEL_CLAIM_REF_NAME].openModal = jest.fn();
|
|
||||||
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
|
|
||||||
wrapper.vm.$refs.siteFooter.enableForwardAction = jest.fn();
|
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,16 +163,6 @@ describe('coverageStatement.vue', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(secondaryText.exists()).toBe(true);
|
expect(secondaryText.exists()).toBe(true);
|
||||||
});
|
});
|
||||||
test('Should render site footer', () => {
|
|
||||||
// Arrange
|
|
||||||
const { wrapper } = getMountedComponent({});
|
|
||||||
|
|
||||||
// Act
|
|
||||||
const footer = wrapper.findComponent({ ref: 'siteFooter' });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(footer.exists()).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
describe('Computed', () => {
|
describe('Computed', () => {
|
||||||
describe.each([
|
describe.each([
|
||||||
|
|
@ -373,7 +361,7 @@ describe('coverageStatement.vue', () => {
|
||||||
[false, coverageStatuses.PENDING, coverageType.NO_COMP],
|
[false, coverageStatuses.PENDING, coverageType.NO_COMP],
|
||||||
[false, coverageStatuses.PENDING, coverageType.Deductible],
|
[false, coverageStatuses.PENDING, coverageType.Deductible],
|
||||||
[true, coverageStatuses.VERIFIED, coverageType.NO_COMP],
|
[true, coverageStatuses.VERIFIED, coverageType.NO_COMP],
|
||||||
[true, coverageStatuses.VERIFIED, coverageType.ITAC],
|
[false, coverageStatuses.VERIFIED, coverageType.ITAC],
|
||||||
[false, coverageStatuses.VERIFIED, coverageType.Deductible],
|
[false, coverageStatuses.VERIFIED, coverageType.Deductible],
|
||||||
[false, coverageStatuses.NO_COVERAGE, coverageType.NO_COMP],
|
[false, coverageStatuses.NO_COVERAGE, coverageType.NO_COMP],
|
||||||
[false, coverageStatuses.NO_COVERAGE, coverageType.ITAC],
|
[false, coverageStatuses.NO_COVERAGE, coverageType.ITAC],
|
||||||
|
|
@ -512,7 +500,10 @@ describe('coverageStatement.vue', () => {
|
||||||
coverageStatus: coverageStatuses.PENDING,
|
coverageStatus: coverageStatuses.PENDING,
|
||||||
coverageType: coverageType.NONE
|
coverageType: coverageType.NONE
|
||||||
},
|
},
|
||||||
currentDeductible: null
|
currentDeductible: {
|
||||||
|
repair: null,
|
||||||
|
replace: null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const { wrapper } = getMountedComponent(mainInitialState);
|
const { wrapper } = getMountedComponent(mainInitialState);
|
||||||
|
|
@ -539,7 +530,9 @@ describe('coverageStatement.vue', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: coverageType.Deductible
|
coverageType: coverageType.Deductible
|
||||||
},
|
},
|
||||||
currentDeductible: deductible
|
currentDeductible: {
|
||||||
|
replace: deductible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const { wrapper } = getMountedComponent(mainInitialState);
|
const { wrapper } = getMountedComponent(mainInitialState);
|
||||||
|
|
@ -566,7 +559,9 @@ describe('coverageStatement.vue', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: coverageType.ITAC
|
coverageType: coverageType.ITAC
|
||||||
},
|
},
|
||||||
currentDeductible: deductible
|
currentDeductible: {
|
||||||
|
replace: deductible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const { wrapper } = getMountedComponent(mainInitialState);
|
const { wrapper } = getMountedComponent(mainInitialState);
|
||||||
|
|
@ -584,7 +579,7 @@ describe('coverageStatement.vue', () => {
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
test('If Verified ITAC, selected other shop, navigate forward w/ CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP', () => {
|
test('If Verified ITAC, selected Cancel, navigate forward w/ CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const deductible = servicePrice + 1;
|
const deductible = servicePrice + 1;
|
||||||
const mainInitialState = {
|
const mainInitialState = {
|
||||||
|
|
@ -596,7 +591,9 @@ describe('coverageStatement.vue', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: coverageType.ITAC
|
coverageType: coverageType.ITAC
|
||||||
},
|
},
|
||||||
currentDeductible: deductible
|
currentDeductible: {
|
||||||
|
replace: deductible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const { wrapper } = getMountedComponent(mainInitialState);
|
const { wrapper } = getMountedComponent(mainInitialState);
|
||||||
|
|
@ -605,7 +602,7 @@ describe('coverageStatement.vue', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.navigateForward();
|
wrapper.vm.cancelClaim();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.$router.navigate)
|
expect(wrapper.vm.$router.navigate)
|
||||||
|
|
@ -667,7 +664,7 @@ describe('coverageStatement.vue', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.navigateForward();
|
wrapper.vm.cancelClaim();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.$router.navigate)
|
expect(wrapper.vm.$router.navigate)
|
||||||
|
|
@ -776,7 +773,9 @@ describe('coverageStatement.vue', () => {
|
||||||
vehicle: {
|
vehicle: {
|
||||||
policyVehicleId: 1
|
policyVehicleId: 1
|
||||||
},
|
},
|
||||||
currentDeductible: deductible
|
currentDeductible: {
|
||||||
|
replace: deductible
|
||||||
|
}
|
||||||
},
|
},
|
||||||
issConfig: {
|
issConfig: {
|
||||||
isClaimRegistrationRequired: true
|
isClaimRegistrationRequired: true
|
||||||
|
|
|
||||||
|
|
@ -15,72 +15,87 @@
|
||||||
<div class="coverage-statement-container iss-heritage-content-container-width">
|
<div class="coverage-statement-container iss-heritage-content-container-width">
|
||||||
<h5
|
<h5
|
||||||
ref="siteSubHeader"
|
ref="siteSubHeader"
|
||||||
class="sub-header text-black mt-4"
|
class="sub-header text-black"
|
||||||
v-html="coverageStatementSubHeader"></h5>
|
v-html="coverageStatementSubHeader"></h5>
|
||||||
<div
|
<div
|
||||||
ref="explanatoryText"
|
ref="explanatoryText"
|
||||||
class="body-text mt-2"
|
class="body-text"
|
||||||
v-html="explanatoryText"></div>
|
v-html="explanatoryText"></div>
|
||||||
|
<div
|
||||||
|
ref="explanatoryText2"
|
||||||
|
class="body-text mt-3"
|
||||||
|
v-html="explanatoryText2"></div>
|
||||||
<div
|
<div
|
||||||
ref="secondaryText"
|
ref="secondaryText"
|
||||||
class="mt-4 mb-1 fw-bold text-black"
|
class="mt-4 mb-1 fw-bold text-black"
|
||||||
v-html="secondaryText"></div>
|
v-html="secondaryText"></div>
|
||||||
<div
|
<div
|
||||||
v-if="isDeductibleVisible"
|
v-if="isITACQuoteVisible"
|
||||||
class="d-flex justify-content-center cost">
|
class="itac-price-container">
|
||||||
|
<div class="itac-deductible-value-container">
|
||||||
|
<div class="itac-deductible-value-text">
|
||||||
|
Your deductible:
|
||||||
|
</div>
|
||||||
|
<div class="itac-deductible-value">
|
||||||
|
{{ formatAmountInDollars(deductibleValue) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="separator"></div>
|
||||||
|
<div class="itac-cost-container">
|
||||||
|
<div class="itac-cost-text">
|
||||||
|
Safelite price*:
|
||||||
|
</div>
|
||||||
|
<div class="cost">
|
||||||
|
{{ formatAmountInDollars(totalServicePrice) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="showDeductibleOnly"
|
||||||
|
class="d-flex cost cost-underline">
|
||||||
{{ formatAmountInDollars(deductibleValue) }}
|
{{ formatAmountInDollars(deductibleValue) }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="isQuoteDisplayed"
|
class="fw-bold text-black mt-5"
|
||||||
class="d-flex justify-content-center cost mb-0">
|
|
||||||
{{ formatAmountInDollars(totalServicePrice) }}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="isITACQuoteVisible"
|
|
||||||
class="d-flex justify-content-center mb-4 deductible-text">
|
|
||||||
{{ deductibleText }}
|
|
||||||
<span class="text-success fw-bold">{{
|
|
||||||
formatAmountInDollars(deductibleValue)
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<alert
|
|
||||||
v-if="isITACQuoteVisible"
|
|
||||||
ref="verifiedITACAlert"
|
|
||||||
class="mb-5"
|
|
||||||
cmsWidgetName="VerifiedITACAlert"
|
|
||||||
:manualHeadline="verifiedItacAlertHeader"
|
|
||||||
:manualCopy="verifiedItacAlertBody"
|
|
||||||
alertClass="alert-success"
|
|
||||||
:isDismissible="false">
|
|
||||||
</alert>
|
|
||||||
<div
|
|
||||||
class="fw-bold text-black mt-5 mb-2"
|
|
||||||
v-html="nextStepsHeader"></div>
|
v-html="nextStepsHeader"></div>
|
||||||
<div
|
<div
|
||||||
class="body-text"
|
class="body-text"
|
||||||
v-html="nextStepsBody"></div>
|
v-html="nextStepsBody"></div>
|
||||||
<buttonQuestion
|
<div
|
||||||
|
v-if="isNoCompQuoteVisible"
|
||||||
|
class="no-comp-price-text">
|
||||||
|
Safelite price*:
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
v-if="isQuoteDisplayed"
|
v-if="isQuoteDisplayed"
|
||||||
v-model="selectedProvider"
|
class="d-flex justify-content-center cost mb-0 cost-underline">
|
||||||
cmsWidgetName="ServiceProviderQuestion"
|
{{ formatAmountInDollars(totalServicePrice) }}
|
||||||
:questionText="serviceProviderQuestionText"
|
</div>
|
||||||
:answers="serviceProviderQuestionAnswers"
|
<buttonMain
|
||||||
groupName="ServiceProviderQuestionOption"
|
ref="buttonMain"
|
||||||
buttonTypeString="listButton"
|
class="full-width-button mt-5 mb-5"
|
||||||
isRequired
|
variant="navigation"
|
||||||
:validationRules="rules.selectionRequired">
|
:buttonText="buttonText"
|
||||||
</buttonQuestion>
|
@clickEvent="navigateForward" />
|
||||||
<siteFooter
|
<textLink
|
||||||
:ref="SITE_FOOTER_REF_NAME"
|
v-if="isNoCompQuoteVisible || isITACQuoteVisible"
|
||||||
class="mt-5"
|
class="underlined-text cancel-link mt-5"
|
||||||
cmsWidgetName="SiteFooterWidget"
|
linkType="text"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
text="No, I want to cancel"
|
||||||
@backClicked="navigateBackByVehicleQuestions"
|
href="#"
|
||||||
@forwardClicked="navigateForward" />
|
@clickEvent="cancelClaim" />
|
||||||
<textBlock
|
<textBlock
|
||||||
v-if="isQuoteDisplayed"
|
v-if="isDisclaimerVisible"
|
||||||
|
class="mt-5 mb-5"
|
||||||
:customText="disclaimerText"
|
:customText="disclaimerText"
|
||||||
typeStyle="caption" />
|
typeStyle="caption" />
|
||||||
|
<div :class="getVariant + ' mb-5'">
|
||||||
|
<textLink
|
||||||
|
linkType="navigation"
|
||||||
|
text="Back"
|
||||||
|
href="#"
|
||||||
|
@clickEvent="navigateBackByVehicleQuestions" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -88,28 +103,17 @@
|
||||||
:ref="RECAL_MODAL_REF_NAME"
|
:ref="RECAL_MODAL_REF_NAME"
|
||||||
cssModalHeadlineClass="text-center"
|
cssModalHeadlineClass="text-center"
|
||||||
cmsWidgetName="RecalModal" />
|
cmsWidgetName="RecalModal" />
|
||||||
<contentGroupModal
|
|
||||||
:ref="DEDUCTIBLE_MODAL_REF_NAME"
|
|
||||||
cmsWidgetName="DeductibleModal"
|
|
||||||
class="deductible-modal" />
|
|
||||||
<cancelClaimModal
|
|
||||||
:ref="CANCEL_CLAIM_REF_NAME"
|
|
||||||
@cancelClaimConfirmation="cancelClaim"
|
|
||||||
@returnToClaim="continueClaim" />
|
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Import Component
|
// Import Component
|
||||||
import { Form } from 'vee-validate';
|
import { Form } from 'vee-validate';
|
||||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
|
||||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||||
import alert from '@/ux-components/alert/alert.vue';
|
|
||||||
import cancelClaimModal from '@/layouts/coverage-statement/cancel-claim-modal/cancel-claim-modal.vue';
|
|
||||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
||||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
|
||||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||||
|
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||||
|
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||||
// Import Supporting Files
|
// Import Supporting Files
|
||||||
import {
|
import {
|
||||||
fetchCmsContentForPage,
|
fetchCmsContentForPage,
|
||||||
|
|
@ -121,35 +125,28 @@ import settleAllPromises from '@/helpers/layout-helper.js';
|
||||||
import { getDamageString } from '@/helpers/damage-helper.js';
|
import { getDamageString } from '@/helpers/damage-helper.js';
|
||||||
import { useMainStore } from '@/store/index.js';
|
import { useMainStore } from '@/store/index.js';
|
||||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin.js';
|
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin.js';
|
||||||
import globalRules from '@/constants/global-rules.js';
|
|
||||||
import baseFormMixin from '@/mixins/base-form-mixin.js';
|
import baseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import navigationScenarios from '@/router/router-constants/navigation-scenarios.js';
|
import navigationScenarios from '@/router/router-constants/navigation-scenarios.js';
|
||||||
import bailoutMessage from '@/constants/bailoutMessage';
|
import bailoutMessage from '@/constants/bailoutMessage';
|
||||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||||
import { formatAmountInDollars, createOrderedListFromStringOfParagraphs } from '@/helpers/text-helper.js';
|
import { formatAmountInDollars, createUnorderedListFromStringOfParagraphs, createOrderedListFromStringOfParagraphs } from '@/helpers/text-helper.js';
|
||||||
import showIssLoadingModal from '@/helpers/loading-modal-helper';
|
import showIssLoadingModal from '@/helpers/loading-modal-helper';
|
||||||
import { getPriceOfLineItems } from '@/helpers/price-calculator';
|
import { getPriceOfLineItems } from '@/helpers/price-calculator';
|
||||||
import coverageStatuses from '@/constants/coverage-statuses';
|
import coverageStatuses from '@/constants/coverage-statuses';
|
||||||
import coverageType from '@/constants/coverage-type';
|
import coverageType from '@/constants/coverage-type';
|
||||||
|
|
||||||
const CANCEL_CLAIM_REF_NAME = 'CancelClaimModal';
|
|
||||||
const SAFELITE_PROVIDER = 'Safelite';
|
|
||||||
const RECAL_MODAL_REF_NAME = 'RecalModal';
|
const RECAL_MODAL_REF_NAME = 'RecalModal';
|
||||||
const DEDUCTIBLE_MODAL_REF_NAME = 'DeductibleModal';
|
|
||||||
const SITE_FOOTER_REF_NAME = 'siteFooter';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'coverage-statement',
|
name: 'coverage-statement',
|
||||||
components: {
|
components: {
|
||||||
siteFooter,
|
|
||||||
siteHeader,
|
siteHeader,
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
Form,
|
Form,
|
||||||
alert,
|
|
||||||
cancelClaimModal,
|
|
||||||
contentGroupModal,
|
contentGroupModal,
|
||||||
buttonQuestion,
|
buttonMain,
|
||||||
textBlock
|
textBlock,
|
||||||
|
textLink
|
||||||
},
|
},
|
||||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
@ -204,24 +201,13 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
baseServiceLineItems: [],
|
baseServiceLineItems: [],
|
||||||
selectedProvider: '',
|
|
||||||
deductibleText: 'Your deductible is',
|
|
||||||
// TODO update when design team gives appropriate text
|
|
||||||
rules: {
|
|
||||||
selectionRequired: globalRules.OPTION_REQUIRED
|
|
||||||
},
|
|
||||||
widget: {
|
widget: {
|
||||||
disclaimerText: 'DisclaimerWidget',
|
disclaimerText: 'DisclaimerWidget',
|
||||||
subheader: 'SiteSubHeaderWidget',
|
subheader: 'SiteSubHeaderWidget',
|
||||||
verifiedItacAlert: 'VerifiedITACAlert',
|
|
||||||
explanatoryText: 'ExplanatoryTextWidget',
|
explanatoryText: 'ExplanatoryTextWidget',
|
||||||
nextStep: 'NextStepsWidget',
|
nextStep: 'NextStepsWidget'
|
||||||
serviceProviderQuestion: 'ServiceProviderQuestion'
|
|
||||||
},
|
},
|
||||||
CANCEL_CLAIM_REF_NAME,
|
RECAL_MODAL_REF_NAME
|
||||||
RECAL_MODAL_REF_NAME,
|
|
||||||
DEDUCTIBLE_MODAL_REF_NAME,
|
|
||||||
SITE_FOOTER_REF_NAME
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -231,27 +217,15 @@ export default {
|
||||||
widgetFields.SUB_HEADER_WIDGET.SUB_HEADER_TEXT
|
widgetFields.SUB_HEADER_WIDGET.SUB_HEADER_TEXT
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
verifiedItacAlertHeader() {
|
secondaryText() {
|
||||||
return this.getCmsContent(
|
|
||||||
this.widget.verifiedItacAlert,
|
|
||||||
widgetFields.ALERT_WIDGET.HEADLINE_TEXT
|
|
||||||
);
|
|
||||||
},
|
|
||||||
verifiedItacAlertBody() {
|
|
||||||
const itacCostSavings =
|
const itacCostSavings =
|
||||||
this.deductibleValue - this.totalServicePrice;
|
this.deductibleValue - this.totalServicePrice;
|
||||||
return this.getCmsContent(
|
|
||||||
this.widget.verifiedItacAlert,
|
|
||||||
widgetFields.ALERT_WIDGET.BODY_TEXT
|
|
||||||
)?.replaceAll(
|
|
||||||
'{custom:costSavings}',
|
|
||||||
formatAmountInDollars(itacCostSavings)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
secondaryText() {
|
|
||||||
return this.getTextFromCmsWithCustomIfStatements(
|
return this.getTextFromCmsWithCustomIfStatements(
|
||||||
this.widget.subheader,
|
this.widget.subheader,
|
||||||
widgetFields.SUB_HEADER_WIDGET.SECONDARY_TEXT
|
widgetFields.SUB_HEADER_WIDGET.SECONDARY_TEXT
|
||||||
|
)?.replaceAll(
|
||||||
|
'{custom:costSavings}',
|
||||||
|
formatAmountInDollars(itacCostSavings)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
disclaimerText() {
|
disclaimerText() {
|
||||||
|
|
@ -266,6 +240,12 @@ export default {
|
||||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
explanatoryText2() {
|
||||||
|
return this.getTextFromCmsWithCustomIfStatements(
|
||||||
|
this.widget.explanatoryText,
|
||||||
|
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2
|
||||||
|
)?.replaceAll('{custom:currentReplaceDeductible}', formatAmountInDollars(this.mainStore.order.currentDeductible.replace));
|
||||||
|
},
|
||||||
nextStepsHeader() {
|
nextStepsHeader() {
|
||||||
return this.getTextFromCmsWithCustomIfStatements(
|
return this.getTextFromCmsWithCustomIfStatements(
|
||||||
this.widget.nextStep,
|
this.widget.nextStep,
|
||||||
|
|
@ -278,6 +258,9 @@ export default {
|
||||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||||
)?.replaceAll('{custom:damage}', this.damageText);
|
)?.replaceAll('{custom:damage}', this.damageText);
|
||||||
|
|
||||||
|
if (this.isITACQuoteVisible || this.isNoCompQuoteVisible) {
|
||||||
|
return createUnorderedListFromStringOfParagraphs(cmsText);
|
||||||
|
}
|
||||||
return createOrderedListFromStringOfParagraphs(cmsText);
|
return createOrderedListFromStringOfParagraphs(cmsText);
|
||||||
},
|
},
|
||||||
damageText() {
|
damageText() {
|
||||||
|
|
@ -285,7 +268,7 @@ export default {
|
||||||
return damageString === 'match' ? '' : damageString;
|
return damageString === 'match' ? '' : damageString;
|
||||||
},
|
},
|
||||||
deductibleValue() {
|
deductibleValue() {
|
||||||
return useMainStore().order.currentDeductible;
|
return this.mainStore.currentDeductible;
|
||||||
},
|
},
|
||||||
isNoCompQuoteVisible() {
|
isNoCompQuoteVisible() {
|
||||||
return this.mainStore.isVerified && this.mainStore.isNoComp;
|
return this.mainStore.isVerified && this.mainStore.isNoComp;
|
||||||
|
|
@ -309,21 +292,15 @@ export default {
|
||||||
totalServicePrice() {
|
totalServicePrice() {
|
||||||
return getPriceOfLineItems(this.baseServiceLineItems);
|
return getPriceOfLineItems(this.baseServiceLineItems);
|
||||||
},
|
},
|
||||||
serviceProviderQuestionText() {
|
|
||||||
return this.getCmsContent(
|
|
||||||
this.widget.serviceProviderQuestion,
|
|
||||||
widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT
|
|
||||||
);
|
|
||||||
},
|
|
||||||
serviceProviderQuestionAnswers() {
|
|
||||||
return this.getCmsContent(
|
|
||||||
this.widget.serviceProviderQuestion,
|
|
||||||
widgetFields.INPUT_QUESTION_WIDGET.ANSWERS
|
|
||||||
);
|
|
||||||
},
|
|
||||||
isQuoteDisplayed() {
|
isQuoteDisplayed() {
|
||||||
|
return this.isNoCompQuoteVisible;
|
||||||
|
},
|
||||||
|
isDisclaimerVisible() {
|
||||||
return this.isITACQuoteVisible || this.isNoCompQuoteVisible;
|
return this.isITACQuoteVisible || this.isNoCompQuoteVisible;
|
||||||
},
|
},
|
||||||
|
showDeductibleOnly() {
|
||||||
|
return this.isDeductibleVisible && !this.isRepairZeroDeductible;
|
||||||
|
},
|
||||||
shouldRegisterClaim() {
|
shouldRegisterClaim() {
|
||||||
const {
|
const {
|
||||||
vehicle,
|
vehicle,
|
||||||
|
|
@ -342,29 +319,24 @@ export default {
|
||||||
},
|
},
|
||||||
isRepair() {
|
isRepair() {
|
||||||
return this.mainStore.order.damage.isRepair;
|
return this.mainStore.order.damage.isRepair;
|
||||||
|
},
|
||||||
|
isRepairZeroDeductible() {
|
||||||
|
return this.isRepair && this.isDeductibleVisible && this.deductibleValue <= 0;
|
||||||
|
},
|
||||||
|
buttonText() {
|
||||||
|
return (this.isITACQuoteVisible || this.isNoCompQuoteVisible) ? 'Continue scheduling' : 'Continue';
|
||||||
|
},
|
||||||
|
getVariant() {
|
||||||
|
if (this.isITACQuoteVisible || this.isNoCompQuoteVisible) {
|
||||||
|
return 'text-center';
|
||||||
|
}
|
||||||
|
return 'text-left';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selectedProvider() {
|
|
||||||
if (this.selectedProvider) {
|
|
||||||
if (this.selectedProvider !== SAFELITE_PROVIDER) {
|
|
||||||
this.$refs[this.CANCEL_CLAIM_REF_NAME].openModal();
|
|
||||||
this.selectedProvider = '';
|
|
||||||
this.$refs.siteFooter.disableForwardButton();
|
|
||||||
} else {
|
|
||||||
this.$refs.siteFooter.enableForwardAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
nextStepsBody(newValue, oldValue) {
|
nextStepsBody(newValue, oldValue) {
|
||||||
if (newValue !== oldValue) {
|
if (newValue !== oldValue) {
|
||||||
setupModalLink(this, RECAL_MODAL_REF_NAME);
|
setupModalLink(this, RECAL_MODAL_REF_NAME);
|
||||||
setupModalLink(this, DEDUCTIBLE_MODAL_REF_NAME);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
verifiedItacAlertBody(newValue, oldValue) {
|
|
||||||
if (newValue !== oldValue) {
|
|
||||||
setupModalLink(this, DEDUCTIBLE_MODAL_REF_NAME);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -421,15 +393,10 @@ export default {
|
||||||
if (this.isUnverifiedVisible || this.isDeductibleVisible) {
|
if (this.isUnverifiedVisible || this.isDeductibleVisible) {
|
||||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD);
|
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD);
|
||||||
} else if (this.isITACQuoteVisible || this.isNoCompQuoteVisible) {
|
} else if (this.isITACQuoteVisible || this.isNoCompQuoteVisible) {
|
||||||
useMainStore().updateIsSafeliteProvider(this.selectedProvider === SAFELITE_PROVIDER);
|
this.mainStore.updateIsSafeliteProvider(true);
|
||||||
if (this.selectedProvider === SAFELITE_PROVIDER) {
|
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE);
|
||||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE);
|
|
||||||
} else {
|
|
||||||
useMainStore().setBailout(bailoutMessage.RequestCallback());
|
|
||||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
useMainStore().setBailout(bailoutMessage.coverageStatementInvalidState());
|
this.mainStore.setBailout(bailoutMessage.coverageStatementInvalidState());
|
||||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE);
|
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -449,28 +416,24 @@ export default {
|
||||||
switch (str) {
|
switch (str) {
|
||||||
case 'coverageUnverified':
|
case 'coverageUnverified':
|
||||||
return this.isUnverifiedVisible;
|
return this.isUnverifiedVisible;
|
||||||
case 'verifiedDeductible':
|
|
||||||
return this.isDeductibleVisible;
|
|
||||||
case 'verifiedITAC':
|
case 'verifiedITAC':
|
||||||
return this.isITACQuoteVisible;
|
return this.isITACQuoteVisible;
|
||||||
case 'verifiedNoComp':
|
case 'verifiedNoComp':
|
||||||
return this.isNoCompQuoteVisible;
|
return this.isNoCompQuoteVisible;
|
||||||
case 'ADASReplace':
|
case 'ADASReplace':
|
||||||
return !isRepair && this.isADAS;
|
return !isRepair && this.isADAS && !this.isNoCompQuoteVisible && !this.isITACQuoteVisible;
|
||||||
case 'nonADASReplace':
|
case 'nonADASReplace':
|
||||||
return !isRepair && !this.isADAS;
|
return !isRepair && !this.isADAS && !this.isNoCompQuoteVisible && !this.isITACQuoteVisible;
|
||||||
case 'nonADASRepair':
|
case 'verifiedRepairDeductible':
|
||||||
return isRepair;
|
|
||||||
case 'deductibleOverZero':
|
|
||||||
return (
|
|
||||||
this.isDeductibleVisible && this.deductibleValue > 0
|
|
||||||
);
|
|
||||||
case 'isDeductibleZero':
|
|
||||||
return (
|
|
||||||
this.isDeductibleVisible && this.deductibleValue <= 0
|
|
||||||
);
|
|
||||||
case 'verifiedRepair':
|
|
||||||
return isRepair && this.isDeductibleVisible;
|
return isRepair && this.isDeductibleVisible;
|
||||||
|
case 'verifiedRepairZeroDeductible':
|
||||||
|
return isRepair && this.isDeductibleVisible && this.deductibleValue <= 0;
|
||||||
|
case 'verifiedRepairZeroDeductibleReplaceDeductibleOverZero':
|
||||||
|
return isRepair && this.isDeductibleVisible && this.deductibleValue <= 0 && this.mainStore.order.currentDeductible.replace > 0;
|
||||||
|
case 'verifiedRepairDeductibleOverZero':
|
||||||
|
return isRepair && this.isDeductibleVisible && this.deductibleValue > 0;
|
||||||
|
case 'verifiedReplaceDeductible':
|
||||||
|
return !isRepair && this.isDeductibleVisible;
|
||||||
case 'verifiedReplaceZeroDeductible':
|
case 'verifiedReplaceZeroDeductible':
|
||||||
return !isRepair && this.isDeductibleVisible && this.deductibleValue <= 0;
|
return !isRepair && this.isDeductibleVisible && this.deductibleValue <= 0;
|
||||||
case 'verifiedReplaceDeductibleOverZero':
|
case 'verifiedReplaceDeductibleOverZero':
|
||||||
|
|
@ -484,13 +447,9 @@ export default {
|
||||||
},
|
},
|
||||||
formatAmountInDollars,
|
formatAmountInDollars,
|
||||||
cancelClaim() {
|
cancelClaim() {
|
||||||
useMainStore().updateIsSafeliteProvider(false);
|
this.mainStore.updateIsSafeliteProvider(false);
|
||||||
useMainStore().setBailout(bailoutMessage.RequestCallback());
|
this.mainStore.setBailout(bailoutMessage.RequestCallback());
|
||||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP);
|
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP);
|
||||||
},
|
|
||||||
continueClaim() {
|
|
||||||
useMainStore().updateIsSafeliteProvider(true);
|
|
||||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -501,46 +460,82 @@ export default {
|
||||||
.coverage-statement-container {
|
.coverage-statement-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
padding-left: .9375rem;
|
padding-left: .75rem;
|
||||||
padding-right: .9375rem;
|
padding-right: .75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.coverage-statement {
|
.coverage-statement {
|
||||||
.cost {
|
.cost {
|
||||||
color: $green;
|
color: $green;
|
||||||
font-size: 2rem;
|
font-size: 1.675rem;
|
||||||
font-weight: $font-weight-light;
|
font-weight: $font-weight-bold;
|
||||||
line-height: 2.75rem;
|
line-height: 2.5rem;
|
||||||
|
width: fit-content;
|
||||||
}
|
}
|
||||||
.deductible-text {
|
.cost-underline {
|
||||||
line-height: 1.5rem;
|
border-bottom: 4px solid #0c7e47;
|
||||||
}
|
}
|
||||||
.sub-header {
|
.sub-header {
|
||||||
line-height: 2rem;
|
line-height: 1.5rem;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.full-width-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.underlined-text {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.cancel-link {
|
||||||
|
display: block;
|
||||||
|
margin: 24px auto 0 auto;
|
||||||
|
}
|
||||||
|
.back-link {
|
||||||
|
display: inline-block;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
:deep(.body-text > ol > ul) {
|
||||||
|
list-style-position: outside;
|
||||||
|
list-style-type: disc;
|
||||||
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
:deep(ol) {
|
:deep(ol) {
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
}
|
||||||
|
:deep(li) {
|
||||||
|
margin-top: 1px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
:deep(ul) {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
padding-left: 1.125rem;
|
padding-left: 1.25rem;
|
||||||
padding-right: 1.125rem;
|
padding-right: 1.25rem;
|
||||||
line-height: 1.5rem;
|
line-height: 1.25rem;
|
||||||
font-size: .875rem;
|
|
||||||
|
|
||||||
li {
|
li {
|
||||||
margin-bottom: .5rem;
|
margin-top: .5rem;
|
||||||
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:deep(p) {
|
:deep(p) {
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
font-size: 0.875rem;
|
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
strong {
|
strong {
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:deep(.body-text) {
|
:deep(.body-text) {
|
||||||
font-size: 0.875rem;
|
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
|
color: $darker-gray;
|
||||||
|
strong {
|
||||||
|
color: $black;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
margin-top: 6px;
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
:deep(.question-text) {
|
:deep(.question-text) {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
|
|
@ -560,20 +555,45 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.itac-price-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
border: solid 1px #cacbcc;
|
||||||
|
border-radius: 5px;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $black;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
:deep(.deductible-modal) {
|
.itac-deductible-value-container {
|
||||||
p {
|
display: flex;
|
||||||
margin-bottom: 0 !important;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.itac-cost-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.itac-deductible-value {
|
||||||
|
font-size: 1.675rem;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
}
|
||||||
|
.separator {
|
||||||
|
width: 1px;
|
||||||
|
height: 60px;
|
||||||
|
background-color: #cacbcc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
img.mb-4 {
|
.no-comp-price-text {
|
||||||
margin: 0 !important;
|
font-weight: 500;
|
||||||
|
color: $black;
|
||||||
}
|
}
|
||||||
h5 {
|
:deep(.line-two) {
|
||||||
color: black;
|
margin-top: 20px;
|
||||||
}
|
display: block;
|
||||||
p:last-child {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,13 @@ const initialStore = {
|
||||||
lastName: 'Test',
|
lastName: 'Test',
|
||||||
servicePhone: '111-111-1111',
|
servicePhone: '111-111-1111',
|
||||||
emailAddress: 'test@email.com'
|
emailAddress: 'test@email.com'
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100,
|
||||||
|
repair: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -123,14 +130,20 @@ const sessionStorage = {
|
||||||
vaps: []
|
vaps: []
|
||||||
},
|
},
|
||||||
policy: {},
|
policy: {},
|
||||||
damage: {},
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
year: 2000,
|
year: 2000,
|
||||||
make: 'Honda',
|
make: 'Honda',
|
||||||
model: 'Civic'
|
model: 'Civic'
|
||||||
},
|
},
|
||||||
customer: {},
|
customer: {},
|
||||||
customerPortalLoginToken: 'token'
|
customerPortalLoginToken: 'token',
|
||||||
|
currentDeductible: {
|
||||||
|
replace: 100,
|
||||||
|
repair: 0
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}, mixin = mockMixin) {
|
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}, mixin = mockMixin) {
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,9 @@ describe('payment-method.vue', () => {
|
||||||
coverageStatus: coverageStatuses.VERIFIED,
|
coverageStatus: coverageStatuses.VERIFIED,
|
||||||
coverageType: coverageType.Deductible
|
coverageType: coverageType.Deductible
|
||||||
},
|
},
|
||||||
currentDeductible: 123
|
currentDeductible: {
|
||||||
|
replace: 123
|
||||||
|
}
|
||||||
},
|
},
|
||||||
issConfig: {
|
issConfig: {
|
||||||
isClaimRegistrationRequired: true,
|
isClaimRegistrationRequired: true,
|
||||||
|
|
@ -286,7 +288,7 @@ describe('payment-method.vue', () => {
|
||||||
test('returns true when coverageStatus is verified and deductibleTotal = 0', () => {
|
test('returns true when coverageStatus is verified and deductibleTotal = 0', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
store.order.insuranceCoverage.coverageStatus = coverageStatuses.VERIFIED;
|
store.order.insuranceCoverage.coverageStatus = coverageStatuses.VERIFIED;
|
||||||
store.order.currentDeductible = 0;
|
store.order.currentDeductible.replace = 0;
|
||||||
const wrapper = setupMocks({}, store, mixin);
|
const wrapper = setupMocks({}, store, mixin);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ export default {
|
||||||
isPayInAdvanceDisabled() {
|
isPayInAdvanceDisabled() {
|
||||||
const piaExperience = this.getSettingValue(experimentSettings.ISS_DISPLAY_PAY_IN_ADVANCE);
|
const piaExperience = this.getSettingValue(experimentSettings.ISS_DISPLAY_PAY_IN_ADVANCE);
|
||||||
const isEnabled = piaExperience === 'true';
|
const isEnabled = piaExperience === 'true';
|
||||||
const isDeductibleTotalEqualToZero = useMainStore().order.currentDeductible === 0;
|
const isDeductibleTotalEqualToZero = useMainStore().currentDeductible === 0;
|
||||||
|
|
||||||
return !isEnabled || useMainStore().isUnverified || (useMainStore().isDeductible && isDeductibleTotalEqualToZero);
|
return !isEnabled || useMainStore().isUnverified || (useMainStore().isDeductible && isDeductibleTotalEqualToZero);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,14 @@
|
||||||
:key="alert.cmsWidgetName"
|
:key="alert.cmsWidgetName"
|
||||||
:ref="alert.cmsWidgetName"
|
:ref="alert.cmsWidgetName"
|
||||||
class="mt-2 mb-3"
|
class="mt-2 mb-3"
|
||||||
|
:manualHeadline="alert.manualHeadline"
|
||||||
:cmsWidgetName="alert.cmsWidgetName"
|
:cmsWidgetName="alert.cmsWidgetName"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import alert from '@/ux-components/alert/alert.vue';
|
import alert from '@/ux-components/alert/alert.vue';
|
||||||
|
import widgetFields from '@/constants/cms-widget-fields';
|
||||||
|
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||||
import getAlertReasons from '@/layouts/schedule-page/helpers/schedule-helper';
|
import getAlertReasons from '@/layouts/schedule-page/helpers/schedule-helper';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -20,6 +23,10 @@ export default {
|
||||||
cmsWidgetPrefix: {
|
cmsWidgetPrefix: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
city: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -29,9 +36,14 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
prefixedAlertReasons() {
|
prefixedAlertReasons() {
|
||||||
|
if (!this.alertReasons || this.alertReasons.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
return this.alertReasons.reduce((newObj, alertReason) => {
|
return this.alertReasons.reduce((newObj, alertReason) => {
|
||||||
newObj.push({
|
newObj.push({
|
||||||
cmsWidgetName: `${this.cmsWidgetPrefix}${alertReason}`,
|
cmsWidgetName: `${this.cmsWidgetPrefix}${alertReason}`,
|
||||||
|
manualHeadline: this.getCmsCopyForAlertReason(alertReason),
|
||||||
alertReason
|
alertReason
|
||||||
});
|
});
|
||||||
return newObj;
|
return newObj;
|
||||||
|
|
@ -49,8 +61,11 @@ export default {
|
||||||
initializeComponent(initialData) {
|
initializeComponent(initialData) {
|
||||||
this.alertReasons = initialData;
|
this.alertReasons = initialData;
|
||||||
},
|
},
|
||||||
cmsHeadlineTextFound(widgetName) {
|
getCmsCopyForAlertReason(alertReason) {
|
||||||
return this.getCmsContent(widgetName, 'HeadlineText') !== '';
|
const widgetName = `${this.cmsWidgetPrefix}${alertReason}`;
|
||||||
|
let content = this.getCmsContent(widgetName, widgetFields.ALERT_WIDGET.HEADLINE_TEXT);
|
||||||
|
content = content.replace('{custom:city}', toTitleCase(this.city));
|
||||||
|
return content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -127,20 +127,19 @@ afterEach(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('schedule-page.vue', () => {
|
describe('schedule-page.vue', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
Object.defineProperty(window, 'matchMedia', { value: jest.fn().mockImplementation((query) => ({
|
||||||
|
matches: false,
|
||||||
|
media: query,
|
||||||
|
onchange: null,
|
||||||
|
addEventListener: jest.fn(),
|
||||||
|
removeEventListener: jest.fn(),
|
||||||
|
dispatchEvent: jest.fn()
|
||||||
|
})),
|
||||||
|
writable: true });
|
||||||
|
});
|
||||||
describe('Initial Load', () => {
|
describe('Initial Load', () => {
|
||||||
test('Should pass arePagePrerequisitesValid with a mobile order and no providerNumber', () => {
|
test('Should pass arePagePrerequisitesValid with a serviceLocation zipcode [in beforeEach]', () => {
|
||||||
// Arrange
|
|
||||||
const { wrapper } = getShallowMountedComponent();
|
|
||||||
wrapper.vm.mainStore.order.serviceLocation.appointmentType = 'Mobile';
|
|
||||||
wrapper.vm.mainStore.order.serviceLocation.provider = null;
|
|
||||||
|
|
||||||
// Act
|
|
||||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(arePagePrerequisitesValid).toBe(true);
|
|
||||||
});
|
|
||||||
test('Should pass arePagePrerequisitesValid with an inshop order and providerNumber', () => {
|
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getShallowMountedComponent();
|
const { wrapper } = getShallowMountedComponent();
|
||||||
|
|
||||||
|
|
@ -150,10 +149,10 @@ describe('schedule-page.vue', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(arePagePrerequisitesValid).toBe(true);
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
});
|
});
|
||||||
test('Should fail arePagePrerequisitesValid with an inshop order and no providerNumber', () => {
|
test('Should fail arePagePrerequisitesValid with no serviceLocation zipcode', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getShallowMountedComponent();
|
const { wrapper } = getShallowMountedComponent();
|
||||||
wrapper.vm.mainStore.order.serviceLocation.provider.providerNumber = null;
|
wrapper.vm.mainStore.order.serviceLocation.zipCode = null;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
@ -161,28 +160,6 @@ describe('schedule-page.vue', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(arePagePrerequisitesValid).toBeFalsy();
|
expect(arePagePrerequisitesValid).toBeFalsy();
|
||||||
});
|
});
|
||||||
test('Should fail arePagePrerequisitesValid if supportingItems is null', async () => {
|
|
||||||
// Arrange
|
|
||||||
const { wrapper } = getShallowMountedComponent();
|
|
||||||
wrapper.vm.mainStore.order.lineItems.supportingItems = null;
|
|
||||||
|
|
||||||
// Act
|
|
||||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(arePagePrerequisitesValid).toBe(false);
|
|
||||||
});
|
|
||||||
test('Should fail arePagePrerequisitesValid with an replace with no glass parts', async () => {
|
|
||||||
// Arrange
|
|
||||||
const { wrapper } = getShallowMountedComponent();
|
|
||||||
wrapper.vm.mainStore.order.lineItems.glassParts = [];
|
|
||||||
|
|
||||||
// Act
|
|
||||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(arePagePrerequisitesValid).toBe(false);
|
|
||||||
});
|
|
||||||
test('should return newShopTimeSlots when getAvailableDatesMethod is called', async () => {
|
test('should return newShopTimeSlots when getAvailableDatesMethod is called', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getShallowMountedComponent();
|
const { wrapper } = getShallowMountedComponent();
|
||||||
|
|
@ -290,7 +267,7 @@ describe('schedule-page.vue', () => {
|
||||||
expect(testValue).toStrictEqual('01234');
|
expect(testValue).toStrictEqual('01234');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('forwardButtonAction should call route method navigateWithoutSaving', async () => {
|
test.skip('forwardButtonAction should call route method navigateWithoutSaving', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = getShallowMountedComponent();
|
const { wrapper } = getShallowMountedComponent();
|
||||||
wrapper.vm.$router.navigate = jest.fn(() => ({}));
|
wrapper.vm.$router.navigate = jest.fn(() => ({}));
|
||||||
|
|
|
||||||
|
|
@ -15,31 +15,47 @@
|
||||||
cmsWidgetName="ScheduleSubHeaderWidget"
|
cmsWidgetName="ScheduleSubHeaderWidget"
|
||||||
secondaryTextClasses="text-center small sub-text"
|
secondaryTextClasses="text-center small sub-text"
|
||||||
class="mt-4" />
|
class="mt-4" />
|
||||||
<div class="main-content-container">
|
<div class="service-location-content-container">
|
||||||
|
<serviceLocation
|
||||||
|
ref="serviceLocation"
|
||||||
|
@appointmentTypeChanged="appointmentTypeChangedFromServiceLocation"
|
||||||
|
@cityUpdated="cityUpdatedFromServiceLocation"
|
||||||
|
@mobileZipUpdated="mobileZipUpdatedFromServiceLocation"
|
||||||
|
@providerChanged="providerChangedFromServiceLocation" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-show="hasNeededServiceLocationData"
|
||||||
|
class="date-picker-container iss-heritage-content-container-width">
|
||||||
|
<div class="date-picker-content-container">
|
||||||
<locationAlerts
|
<locationAlerts
|
||||||
ref="locationAlerts"
|
ref="locationAlerts"
|
||||||
cmsWidgetPrefix="LocationAlert-" />
|
cmsWidgetPrefix="LocationAlert-"
|
||||||
|
:city="selectedServiceLocationCity" />
|
||||||
<datePicker
|
<datePicker
|
||||||
ref="datePicker"
|
ref="datePicker"
|
||||||
v-model="selectedTimeSlotInfo"
|
v-model="selectedTimeSlotInfo"
|
||||||
customComponentId="dateQuestion"
|
customComponentId="dateQuestion"
|
||||||
selectableDatesSetting="custom"
|
selectableDatesSetting="custom"
|
||||||
class="text-link-small"
|
class="text-link-small"
|
||||||
|
:activeAppointmentType="selectedAppointmentType"
|
||||||
|
:isMobileView="isMobileView"
|
||||||
:showTimeSlotError="showDatePickerError"
|
:showTimeSlotError="showDatePickerError"
|
||||||
:customSelectableDatesCallback="
|
:customSelectableDatesCallback="getAvailableDatesMethod"
|
||||||
getAvailableDatesMethod
|
|
||||||
"
|
|
||||||
@dateSelected="dateSelectedFromPicker"
|
@dateSelected="dateSelectedFromPicker"
|
||||||
@timeSlotSelected="timeSlotSelectedFromPicker" />
|
@timeSlotSelected="timeSlotSelectedFromPicker" />
|
||||||
<siteFooter
|
|
||||||
ref="navbar"
|
|
||||||
class="mt-5"
|
|
||||||
cmsWidgetName="SiteFooterWidget"
|
|
||||||
:isForwardButtonNavigationDisabled="!isFormValid"
|
|
||||||
@backClicked="navigateBack"
|
|
||||||
@forwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="site-footer-container iss-heritage-content-container-width">
|
||||||
|
<siteFooter
|
||||||
|
ref="navbar"
|
||||||
|
class="mt-5"
|
||||||
|
cmsWidgetName="SiteFooterWidget"
|
||||||
|
:isForwardButtonHidden="!hasNeededServiceLocationData"
|
||||||
|
:isForwardButtonNavigationDisabled="!isFormValid"
|
||||||
|
@backClicked="navigateBack(this, navigateBackScenario)"
|
||||||
|
@forwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -50,6 +66,7 @@ import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||||
import locationAlerts from '@/layouts/schedule-page/location-alerts/location-alerts.vue';
|
import locationAlerts from '@/layouts/schedule-page/location-alerts/location-alerts.vue';
|
||||||
import datePicker from '@/digital-components/date-picker/date-picker.vue';
|
import datePicker from '@/digital-components/date-picker/date-picker.vue';
|
||||||
|
import serviceLocation from '@/layouts/schedule-page/service-location/service-location.vue';
|
||||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
|
|
@ -65,9 +82,16 @@ import {
|
||||||
} from '@/helpers/cms-content-helper';
|
} from '@/helpers/cms-content-helper';
|
||||||
import {
|
import {
|
||||||
calcDaysBetweenDates,
|
calcDaysBetweenDates,
|
||||||
|
convertDateToDateString,
|
||||||
sumDateString
|
sumDateString
|
||||||
} from '@/helpers/date-helper';
|
} from '@/helpers/date-helper';
|
||||||
import settleAllPromises from '@/helpers/layout-helper';
|
import settleAllPromises from '@/helpers/layout-helper';
|
||||||
|
import showIssLoadingModal from '@/helpers/loading-modal-helper.js';
|
||||||
|
import {
|
||||||
|
getPricedMobileFeePart,
|
||||||
|
getServiceabilityDetails,
|
||||||
|
getZipCodeData
|
||||||
|
} from '@/helpers/service-location-helper';
|
||||||
import { Form } from 'vee-validate';
|
import { Form } from 'vee-validate';
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
|
|
@ -79,7 +103,8 @@ const getAvailableDates = async (
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
appointmentType,
|
appointmentType,
|
||||||
providerNumber
|
providerNumber,
|
||||||
|
mobileZipCodeOverride = null
|
||||||
) => {
|
) => {
|
||||||
const apiEndDateLimit = sumDateString(
|
const apiEndDateLimit = sumDateString(
|
||||||
startDateString,
|
startDateString,
|
||||||
|
|
@ -113,7 +138,8 @@ const getAvailableDates = async (
|
||||||
storeAction: GET_MOBILE_TIME_SLOTS,
|
storeAction: GET_MOBILE_TIME_SLOTS,
|
||||||
payload: {
|
payload: {
|
||||||
startDate: apiStartDate,
|
startDate: apiStartDate,
|
||||||
endDate: apiEndDate
|
endDate: apiEndDate,
|
||||||
|
zipCodeOverride: mobileZipCodeOverride
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -153,14 +179,19 @@ const getAvailableDates = async (
|
||||||
} else {
|
} else {
|
||||||
timeSlotsResponse = await useMainStore().getMobileTimeSlots(
|
timeSlotsResponse = await useMainStore().getMobileTimeSlots(
|
||||||
storeAction.payload.startDate,
|
storeAction.payload.startDate,
|
||||||
storeAction.payload.endDate
|
storeAction.payload.endDate,
|
||||||
);
|
storeAction.payload.zipCodeOverride
|
||||||
|
).catch((error) => {
|
||||||
|
console.log('Error fetching mobile time slots:', error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
timeSlotsResponsesData.estimatedServiceMinutesMinimum =
|
if (!timeSlotsResponse || !timeSlotsResponse.data) {
|
||||||
timeSlotsResponse.data.estimatedServiceMinutesMinimum;
|
return;
|
||||||
timeSlotsResponsesData.estimatedServiceMinutesMaximum =
|
}
|
||||||
timeSlotsResponse.data.estimatedServiceMinutesMaximum;
|
|
||||||
|
timeSlotsResponsesData.estimatedServiceMinutesMinimum = timeSlotsResponse.data.estimatedServiceMinutesMinimum;
|
||||||
|
timeSlotsResponsesData.estimatedServiceMinutesMaximum = timeSlotsResponse.data.estimatedServiceMinutesMaximum;
|
||||||
timeSlotsResponsesData.days = [
|
timeSlotsResponsesData.days = [
|
||||||
...timeSlotsResponsesData.days,
|
...timeSlotsResponsesData.days,
|
||||||
...timeSlotsResponse.data.days
|
...timeSlotsResponse.data.days
|
||||||
|
|
@ -182,6 +213,7 @@ export default {
|
||||||
siteSubHeader,
|
siteSubHeader,
|
||||||
locationAlerts,
|
locationAlerts,
|
||||||
datePicker,
|
datePicker,
|
||||||
|
serviceLocation,
|
||||||
siteFooter,
|
siteFooter,
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
Form
|
Form
|
||||||
|
|
@ -189,23 +221,18 @@ export default {
|
||||||
mixins: [BaseFormMixin],
|
mixins: [BaseFormMixin],
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
// Call APIs
|
// Call APIs
|
||||||
let preSelectedDate = await useMainStore().order.schedule.date;
|
|
||||||
if (!preSelectedDate || preSelectedDate.startTime === null) {
|
|
||||||
preSelectedDate = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||||
|
const storeServiceLocation = useMainStore().order.serviceLocation;
|
||||||
const datePickerInitialDataPromise =
|
const storeSelectedAppointmentType = storeServiceLocation?.appointmentType;
|
||||||
await datePicker.methods.loadInitialData({
|
const storeSelectedProvider = storeServiceLocation?.provider;
|
||||||
selectableDatesSetting: 'custom',
|
const serviceZipCode = storeServiceLocation?.zipCode || useMainStore().order.customer.address.zipCode;
|
||||||
initialViewRowsToShow: 5,
|
const zipCodeData = getZipCodeData(serviceZipCode);
|
||||||
customSelectableDatesCallback: getAvailableDates,
|
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
||||||
preSelectedDate
|
const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
|
||||||
});
|
const getGlassFeesPromise = useMainStore().getGlassFees();
|
||||||
|
const providersPromise = useMainStore().getProviders(serviceZipCode);
|
||||||
|
|
||||||
const premiumFeePromise = useMainStore().getMobilePremiumFee();
|
const premiumFeePromise = useMainStore().getMobilePremiumFee();
|
||||||
|
|
||||||
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
||||||
if (result.data) {
|
if (result.data) {
|
||||||
return useMainStore().getCombinedQuote(result.data);
|
return useMainStore().getCombinedQuote(result.data);
|
||||||
|
|
@ -213,11 +240,6 @@ export default {
|
||||||
return result.data;
|
return result.data;
|
||||||
});
|
});
|
||||||
|
|
||||||
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
|
||||||
useMainStore().order.serviceLocation.zipCodeCtu,
|
|
||||||
useMainStore().order.serviceLocation.provider?.address?.zipCodeCtu
|
|
||||||
);
|
|
||||||
|
|
||||||
// Settle promises and get results
|
// Settle promises and get results
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
|
|
@ -225,12 +247,24 @@ export default {
|
||||||
promise: cmsContentPromise
|
promise: cmsContentPromise
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resultKey: 'alertReasons',
|
resultKey: 'mobileFeePart',
|
||||||
promise: alertReasonsPromise
|
promise: mobileFeePartPromise
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resultKey: 'datePickerInitialData',
|
resultKey: 'glassFees',
|
||||||
promise: datePickerInitialDataPromise
|
promise: getGlassFeesPromise
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: 'serviceabilityDetails',
|
||||||
|
promise: serviceabilityDetailsPromise
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: 'zipCodeData',
|
||||||
|
promise: zipCodeData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: 'providers',
|
||||||
|
promise: providersPromise
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resultKey: 'premiumFeeWithPrice',
|
resultKey: 'premiumFeeWithPrice',
|
||||||
|
|
@ -240,14 +274,32 @@ export default {
|
||||||
|
|
||||||
// use resultMap to populate layout content.
|
// use resultMap to populate layout content.
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
next((vm) => {
|
const serviceLocationData = {
|
||||||
|
glassFees: resultMap.glassFees,
|
||||||
|
mobileFeePart: resultMap.mobileFeePart,
|
||||||
|
providers: resultMap.providers,
|
||||||
|
serviceabilityDetails: resultMap.serviceabilityDetails,
|
||||||
|
zipCodeData: resultMap.zipCodeData
|
||||||
|
};
|
||||||
|
useMainStore().updateIsSafeliteProvider(true);
|
||||||
|
next(async (vm) => {
|
||||||
|
const providerToUse = resultMap.providers?.shopProviders
|
||||||
|
.find((provider) => provider.providerNumber === storeSelectedProvider?.providerNumber) || resultMap.providers?.shopProviders[0];
|
||||||
|
const isMobileAppointment = storeSelectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||||
|
|| storeSelectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||||
|
const initialServiceLocationObj = {
|
||||||
|
mobileProviderNumber: isMobileAppointment
|
||||||
|
? storeSelectedProvider?.providerNumber
|
||||||
|
: null,
|
||||||
|
provider: isMobileAppointment ? null : providerToUse,
|
||||||
|
zipCode: useMainStore().order.serviceLocation.zipCode || useMainStore().order.customer.address.zipCode,
|
||||||
|
zipCodeCtu: resultMap.zipCodeData?.zipCodeCtu
|
||||||
|
};
|
||||||
|
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData);
|
vm.$refs.serviceLocation.initializeComponent(serviceLocationData);
|
||||||
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
await vm.setData(resultMap.premiumFeeWithPrice, initialServiceLocationObj);
|
||||||
vm.setData(
|
showIssLoadingModal(false);
|
||||||
resultMap.datePickerInitialData.initialShopTimeSlotsResponse,
|
|
||||||
resultMap.premiumFeeWithPrice
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
|
@ -256,64 +308,133 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedDate: this.getSelectedDate(),
|
inShopDatesData: [],
|
||||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
isMobileView: false,
|
||||||
|
mobileDatesData: [],
|
||||||
|
mobileFeePart: null,
|
||||||
|
mobilePremiumAppointmentFee: null,
|
||||||
|
mobileProviderNumber: null,
|
||||||
|
mobileZipCodeOverride: null,
|
||||||
selectableDatesData: [],
|
selectableDatesData: [],
|
||||||
showDatePickerError: false,
|
selectedAppointmentType: this.getAppointmentType(),
|
||||||
mobilePremiumAppointmentFee: null
|
selectedDate: this.getSelectedDate(),
|
||||||
|
selectedProvider: this.getSelectedProvider(),
|
||||||
|
selectedServiceLocation: this.getServiceLocation(),
|
||||||
|
selectedServiceLocationCity: this.getServiceLocationCity(),
|
||||||
|
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||||
|
showDatePickerError: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
ChangeShopLinkText() {
|
hasNeededServiceLocationData() {
|
||||||
return this.getCmsContent('ChangeShopLink', 'Text');
|
const serviceLocationToUse = this.selectedServiceLocation;
|
||||||
},
|
if (!serviceLocationToUse || !this.selectedAppointmentType) {
|
||||||
ChangeShopLink() {
|
return false;
|
||||||
return this.splitCopyOnCMSPlaceHolder(this.ChangeShopLinkText);
|
}
|
||||||
},
|
|
||||||
appointmentType() {
|
const serviceLocationPreReqs = serviceLocationToUse.zipCode !== null
|
||||||
return useMainStore().order.serviceLocation.appointmentType;
|
&& serviceLocationToUse.zipCodeCtu !== null
|
||||||
|
&& serviceLocationToUse.appointmentType !== null
|
||||||
|
&& (((this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||||
|
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)
|
||||||
|
&& serviceLocationToUse.mobileProviderNumber)
|
||||||
|
|| (this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP
|
||||||
|
&& (this.selectedProvider?.providerNumber || serviceLocationToUse.provider?.providerNumber)));
|
||||||
|
|
||||||
|
const damageInfo = useMainStore().order.damage.isRepair
|
||||||
|
|| (useMainStore().order.lineItems?.glassParts != null && useMainStore().order.lineItems.glassParts.length > 0);
|
||||||
|
|
||||||
|
const supportingItems = this.supportingItems !== null;
|
||||||
|
|
||||||
|
return (serviceLocationPreReqs && supportingItems && damageInfo);
|
||||||
},
|
},
|
||||||
isFormValid() {
|
isFormValid() {
|
||||||
const hasTimeSlotSelected = this.selectedTimeSlotInfo?.timeSlot?.routeCode != null;
|
const hasTimeSlotSelected = this.selectedTimeSlotInfo?.timeSlot?.routeCode != null;
|
||||||
return hasTimeSlotSelected;
|
return hasTimeSlotSelected;
|
||||||
},
|
},
|
||||||
|
navigateBackScenario() {
|
||||||
|
const { isNoComp, isITAC } = useMainStore();
|
||||||
|
return isNoComp || isITAC
|
||||||
|
? this.navigationScenarios.CLICKED_BACK_CANNOT_REACH_TPA_FLOW
|
||||||
|
: this.navigationScenarios.CLICKED_BACK_CAN_REACH_TPA_FLOW;
|
||||||
|
},
|
||||||
supportingItems() {
|
supportingItems() {
|
||||||
return useMainStore().lineItems.supportingItems;
|
return useMainStore().lineItems.supportingItems;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
showIssLoadingModal(true);
|
||||||
|
this.mql = window.matchMedia('(min-width: 1200px)');
|
||||||
|
this.isMobileView = !this.mql.matches;
|
||||||
|
this.mql.addEventListener('change', this.handleMqlChange);
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
if (this.mql) {
|
||||||
|
this.mql.removeEventListener('change', this.handleMqlChange);
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
splitCopyOnCMSPlaceHolder,
|
splitCopyOnCMSPlaceHolder,
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
const { serviceLocation } = useMainStore().order;
|
return useMainStore().order.serviceLocation.zipCode !== null;
|
||||||
const serviceLocationPreReqs =
|
|
||||||
serviceLocation.zipCode
|
|
||||||
&& serviceLocation.zipCodeCtu
|
|
||||||
&& serviceLocation.appointmentType
|
|
||||||
&& (serviceLocation.appointmentType
|
|
||||||
=== AppointmentTypeStrings.MOBILE
|
|
||||||
|| serviceLocation.appointmentType
|
|
||||||
=== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
|
||||||
|| serviceLocation.provider.providerNumber);
|
|
||||||
const supportingItems = this.supportingItems !== null;
|
|
||||||
const damageInfo =
|
|
||||||
useMainStore().order.damage.isRepair
|
|
||||||
|| (useMainStore().order.lineItems?.glassParts != null
|
|
||||||
&& useMainStore().order.lineItems.glassParts.length > 0);
|
|
||||||
|
|
||||||
return serviceLocationPreReqs && supportingItems && damageInfo;
|
|
||||||
},
|
},
|
||||||
setData(initialShopTimeSlotsResponse, premiumFeeWithPriceResponse) {
|
async setData(premiumFeeWithPriceResponse, initialServiceLocationObj) {
|
||||||
this.selectableDatesData = initialShopTimeSlotsResponse;
|
this.selectedServiceLocation = initialServiceLocationObj;
|
||||||
this.mobilePremiumAppointmentFee = premiumFeeWithPriceResponse
|
this.mobilePremiumAppointmentFee = premiumFeeWithPriceResponse
|
||||||
? premiumFeeWithPriceResponse[0]
|
? premiumFeeWithPriceResponse[0]
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
if (initialServiceLocationObj?.zipCodeCtu) {
|
||||||
|
this.$refs.locationAlerts.loadInitialData(
|
||||||
|
initialServiceLocationObj.zipCodeCtu,
|
||||||
|
initialServiceLocationObj.provider?.ctu
|
||||||
|
).then((alertReasons) => {
|
||||||
|
this.$refs.locationAlerts.initializeComponent(alertReasons.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selectedAppointmentType !== AppointmentTypeStrings.MOBILE
|
||||||
|
&& this.selectedAppointmentType !== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||||
|
await this.getDatePickerInitialData(initialServiceLocationObj.provider?.providerNumber).then((initialData) => {
|
||||||
|
this.selectableDatesData = initialData.initialShopTimeSlotsResponse;
|
||||||
|
this.$refs.datePicker.setCalendarData(initialData);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.mobileProviderNumber = initialServiceLocationObj.mobileProviderNumber;
|
||||||
|
await this.getDatePickerInitialData().then((initialData) => {
|
||||||
|
this.selectableDatesData = initialData.initialShopTimeSlotsResponse;
|
||||||
|
this.$refs.datePicker.setCalendarData(initialData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
appointmentTypeChangedFromServiceLocation(newAppointmentType) {
|
||||||
|
this.selectedAppointmentType = newAppointmentType.appointmentType;
|
||||||
|
if (newAppointmentType.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||||
|
if (this.inShopDatesData?.initialShopTimeSlotsResponse?.days?.length > 0) {
|
||||||
|
this.selectableDatesData = this.inShopDatesData.initialShopTimeSlotsResponse;
|
||||||
|
this.$refs.datePicker.initializeComponent(this.inShopDatesData);
|
||||||
|
}
|
||||||
|
} else if (this.mobileDatesData?.initialShopTimeSlotsResponse?.days?.length > 0) {
|
||||||
|
this.selectableDatesData = this.mobileDatesData.initialShopTimeSlotsResponse;
|
||||||
|
this.$refs.datePicker.initializeComponent(this.mobileDatesData);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cityUpdatedFromServiceLocation(newCity) {
|
||||||
|
this.selectedServiceLocationCity = newCity;
|
||||||
|
},
|
||||||
|
dateSelectedFromPicker(date) {
|
||||||
|
this.selectedDate = date;
|
||||||
|
this.showDatePickerError = false;
|
||||||
|
},
|
||||||
|
getAppointmentType() {
|
||||||
|
return this.mainStore.order?.serviceLocation?.appointmentType;
|
||||||
},
|
},
|
||||||
async getAvailableDatesMethod(startDate, endDate) {
|
async getAvailableDatesMethod(startDate, endDate) {
|
||||||
const newShopTimeSlots = await getAvailableDates(
|
const newShopTimeSlots = await getAvailableDates(
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
this.appointmentType,
|
this.selectedAppointmentType,
|
||||||
this.mainStore.order.serviceLocation.provider.providerNumber
|
this.selectedProvider.providerNumber
|
||||||
);
|
);
|
||||||
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
||||||
this.selectableDatesData.days =
|
this.selectableDatesData.days =
|
||||||
|
|
@ -321,12 +442,131 @@ export default {
|
||||||
return newShopTimeSlots;
|
return newShopTimeSlots;
|
||||||
},
|
},
|
||||||
getAvailableDates,
|
getAvailableDates,
|
||||||
|
async getDatePickerInitialData(defaultProviderNumber = null) {
|
||||||
|
this.inShopDatesData = [];
|
||||||
|
this.mobileDatesData = [];
|
||||||
|
|
||||||
|
let todayDateString;
|
||||||
|
const todayDateObject = new Date();
|
||||||
|
const calendarViewDirection = 'future';
|
||||||
|
const initialDays = 15;
|
||||||
|
|
||||||
|
if (this.todayString) {
|
||||||
|
todayDateString = this.todayString;
|
||||||
|
} else {
|
||||||
|
todayDateString = convertDateToDateString(todayDateObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialViewStartDate = todayDateString;
|
||||||
|
const initialEndDate = new Date();
|
||||||
|
initialEndDate.setDate(initialEndDate.getDate() + (initialDays - 1));
|
||||||
|
let initialViewEndDate = convertDateToDateString(initialEndDate);
|
||||||
|
const preSelectedDate = this.mainStore.order.schedule.date;
|
||||||
|
|
||||||
|
const endDateObject = this.getEndDateForExistingDate(
|
||||||
|
todayDateObject,
|
||||||
|
preSelectedDate,
|
||||||
|
initialDays
|
||||||
|
);
|
||||||
|
|
||||||
|
if (endDateObject.endDateString !== initialViewEndDate) {
|
||||||
|
initialViewEndDate = endDateObject.endDateString;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mobileProviderNumberToUse = defaultProviderNumber;
|
||||||
|
if (this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||||
|
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||||
|
mobileProviderNumberToUse = this.selectedServiceLocation.mobileProviderNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialData = await getAvailableDates(
|
||||||
|
initialViewStartDate,
|
||||||
|
initialViewEndDate,
|
||||||
|
this.selectedAppointmentType || AppointmentTypeStrings.IN_SHOP,
|
||||||
|
this.selectedProvider?.providerNumber || mobileProviderNumberToUse,
|
||||||
|
this.selectedServiceLocation.zipCode
|
||||||
|
).then((response) => ({
|
||||||
|
todayDate: todayDateString,
|
||||||
|
initialViewStartDate,
|
||||||
|
initialViewEndDate,
|
||||||
|
calendarViewDirection,
|
||||||
|
initialShopTimeSlotsResponse: response,
|
||||||
|
preSelectedDate,
|
||||||
|
initialDaysLoaded: endDateObject.newDaysLoaded || initialDays,
|
||||||
|
daysFromStart: endDateObject.daysFromStart || null
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||||
|
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||||
|
this.mobileDatesData = initialData;
|
||||||
|
|
||||||
|
if (this.selectedProvider?.providerNumber) {
|
||||||
|
const inShopData = await getAvailableDates(
|
||||||
|
initialViewStartDate,
|
||||||
|
initialViewEndDate,
|
||||||
|
AppointmentTypeStrings.IN_SHOP,
|
||||||
|
this.selectedProvider?.providerNumber || defaultProviderNumber,
|
||||||
|
this.selectedServiceLocation.zipCode
|
||||||
|
).then((response) => ({
|
||||||
|
todayDate: todayDateString,
|
||||||
|
initialViewStartDate,
|
||||||
|
initialViewEndDate,
|
||||||
|
calendarViewDirection,
|
||||||
|
initialShopTimeSlotsResponse: response,
|
||||||
|
preSelectedDate,
|
||||||
|
initialDaysLoaded: endDateObject.newDaysLoaded || initialDays,
|
||||||
|
daysFromStart: endDateObject.daysFromStart || null
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.inShopDatesData = inShopData;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.inShopDatesData = initialData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return initialData;
|
||||||
|
},
|
||||||
|
getEndDateForExistingDate(startDate, selectedDateString, daysInView) {
|
||||||
|
const endDate = new Date(startDate);
|
||||||
|
endDate.setDate(endDate.getDate() + (daysInView - 1));
|
||||||
|
|
||||||
|
if (selectedDateString) {
|
||||||
|
const selectedDate = new Date(`${selectedDateString}T00:00:00`);
|
||||||
|
const daysDifferenceComparedToStartDate = Math.ceil((selectedDate - startDate) / (1000 * 60 * 60 * 24));
|
||||||
|
if (selectedDate > endDate) {
|
||||||
|
const daysDifferenceComparedToStartDateAsPages = Math.ceil(daysDifferenceComparedToStartDate / daysInView);
|
||||||
|
const newEndDate = new Date(startDate);
|
||||||
|
newEndDate.setDate(newEndDate.getDate() + (daysDifferenceComparedToStartDateAsPages * daysInView) - 1);
|
||||||
|
|
||||||
|
return {
|
||||||
|
endDateString: convertDateToDateString(newEndDate),
|
||||||
|
newDaysLoaded: (daysDifferenceComparedToStartDateAsPages * daysInView),
|
||||||
|
daysFromStart: daysDifferenceComparedToStartDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
endDateString: convertDateToDateString(endDate),
|
||||||
|
newDaysLoaded: null,
|
||||||
|
daysFromStart: daysDifferenceComparedToStartDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
endDateString: convertDateToDateString(endDate),
|
||||||
|
newDaysLoaded: null,
|
||||||
|
daysFromStart: null
|
||||||
|
};
|
||||||
|
},
|
||||||
getServiceZipCtuCodeFromStore() {
|
getServiceZipCtuCodeFromStore() {
|
||||||
return this.mainStore.order.serviceLocation.zipCodeCtu;
|
return this.mainStore.order.serviceLocation.zipCodeCtu;
|
||||||
},
|
},
|
||||||
getSelectedDate() {
|
getSelectedDate() {
|
||||||
return this.mainStore.order.schedule.date;
|
return this.mainStore.order.schedule.date;
|
||||||
},
|
},
|
||||||
|
getSelectedProvider() {
|
||||||
|
return this.mainStore.order.serviceLocation.provider;
|
||||||
|
},
|
||||||
getSelectedTimeSlotInfo() {
|
getSelectedTimeSlotInfo() {
|
||||||
const isPremiumAppointment =
|
const isPremiumAppointment =
|
||||||
!!(
|
!!(
|
||||||
|
|
@ -341,20 +581,52 @@ export default {
|
||||||
|
|
||||||
return selectedTimeSlotInfo;
|
return selectedTimeSlotInfo;
|
||||||
},
|
},
|
||||||
dateSelectedFromPicker(date) {
|
getServiceLocation() {
|
||||||
this.selectedDate = date;
|
return this.mainStore.order.serviceLocation;
|
||||||
this.showDatePickerError = false;
|
},
|
||||||
|
getServiceLocationCity() {
|
||||||
|
return this.mainStore.order.serviceLocation?.city;
|
||||||
|
},
|
||||||
|
handleMqlChange(e) {
|
||||||
|
this.isMobileView = !e.matches;
|
||||||
|
},
|
||||||
|
mobileZipUpdatedFromServiceLocation(mobileZipServiceLocation) {
|
||||||
|
if (mobileZipServiceLocation) {
|
||||||
|
this.mobileProviderNumber = mobileZipServiceLocation.mobileProviderNumber;
|
||||||
|
this.selectedServiceLocation = mobileZipServiceLocation;
|
||||||
|
|
||||||
|
if (mobileZipServiceLocation.refreshDatePicker) {
|
||||||
|
this.refreshDatePicker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
providerChangedFromServiceLocation(newProvider) {
|
||||||
|
this.selectedProvider = newProvider?.provider;
|
||||||
|
|
||||||
|
if (newProvider?.refreshDatePicker) {
|
||||||
|
showIssLoadingModal(true);
|
||||||
|
this.refreshDatePicker();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async refreshDatePicker() {
|
||||||
|
await this.getDatePickerInitialData().then((data) => {
|
||||||
|
this.selectableDatesData = data.initialShopTimeSlotsResponse;
|
||||||
|
this.$refs.datePicker.initializeComponent(data);
|
||||||
|
showIssLoadingModal(false);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
timeSlotSelectedFromPicker(timeSlot) {
|
timeSlotSelectedFromPicker(timeSlot) {
|
||||||
this.selectedTimeSlotInfo = timeSlot;
|
this.selectedTimeSlotInfo = timeSlot;
|
||||||
this.showDatePickerError = false;
|
this.showDatePickerError = false;
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
if (!this.isFormValid) {
|
if (!this.isFormValid) {
|
||||||
this.showDatePickerError = true;
|
this.showDatePickerError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save service location then schedule and navigate forward
|
||||||
|
await this.$refs.serviceLocation.forwardButtonAction();
|
||||||
this.mainStore.saveSchedule(this.selectedTimeSlotInfo.timeSlot);
|
this.mainStore.saveSchedule(this.selectedTimeSlotInfo.timeSlot);
|
||||||
this.$router.navigate(
|
this.$router.navigate(
|
||||||
this.navigationScenarios.CLICKED_FORWARD,
|
this.navigationScenarios.CLICKED_FORWARD,
|
||||||
|
|
@ -369,11 +641,12 @@ export default {
|
||||||
$page-side-padding: 1.5rem;
|
$page-side-padding: 1.5rem;
|
||||||
|
|
||||||
.iss-heritage-container-width {
|
.iss-heritage-container-width {
|
||||||
|
padding-right: 0.9375rem;
|
||||||
|
padding-left: 0.9375rem;
|
||||||
|
|
||||||
.schedule-page-container {
|
.schedule-page-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
padding-left: .9375rem;
|
|
||||||
padding-right: .9375rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useMainStore } from '@/store';
|
|
||||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
||||||
import { experimentSettings } from '@/constants/experiments';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'appointment-type-question',
|
name: 'appointment-type-question',
|
||||||
|
|
@ -63,12 +61,17 @@ export default {
|
||||||
this.$emit('update:modelValue', newValue);
|
this.$emit('update:modelValue', newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.appointment-type-question {
|
.appointment-type-question {
|
||||||
margin-bottom: 1.25rem;
|
margin-top: .625rem;
|
||||||
|
|
||||||
|
:deep(.list-button-content) {
|
||||||
|
padding-top: .625rem;
|
||||||
|
padding-bottom: .625rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -79,8 +79,6 @@ import modal from '@/digital-components/modal/modal.vue';
|
||||||
import alert from '@/ux-components/alert/alert.vue';
|
import alert from '@/ux-components/alert/alert.vue';
|
||||||
import { useField } from 'vee-validate';
|
import { useField } from 'vee-validate';
|
||||||
import addressQuestions from '@/iss-components/address-questions/address-questions.vue';
|
import addressQuestions from '@/iss-components/address-questions/address-questions.vue';
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
import vehicleProtectedQuestion from '@/layouts/service-location/mobile-location-modal-questions/vehicle-protected-question/vehicle-protected-question.vue';
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import { experimentSettings } from '@/constants/experiments';
|
import { experimentSettings } from '@/constants/experiments';
|
||||||
|
|
@ -90,10 +88,11 @@ import { useMainStore } from '@/store';
|
||||||
import {
|
import {
|
||||||
getMobileZipCodeData,
|
getMobileZipCodeData,
|
||||||
getPricedMobileFeePart,
|
getPricedMobileFeePart,
|
||||||
getServiceabilityDetails,
|
getServiceabilityDetails
|
||||||
getZipCodeData
|
|
||||||
} from '@/helpers/service-location-helper';
|
} from '@/helpers/service-location-helper';
|
||||||
import { deepClone } from '@/helpers/object-helper.js';
|
import { deepClone } from '@/helpers/object-helper.js';
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
import vehicleProtectedQuestion from '@/layouts/schedule-page/service-location/mobile-location-modal-question/vehicle-protected-question/vehicle-protected-question.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'mobile-location-modal-questions',
|
name: 'mobile-location-modal-questions',
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import baseMixin from '@/mixins/base-mixin';
|
import baseMixin from '@/mixins/base-mixin';
|
||||||
import { mount, flushPromises } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import { createTestingPinia } from '@pinia/testing';
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||||
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
|
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
|
||||||
import routerParams from '@/router/router-constants/router-params';
|
import routerParams from '@/router/router-constants/router-params';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import serviceLocation from '@/layouts/service-location/service-location.vue';
|
import serviceLocation from '@/layouts/schedule-page/service-location/service-location.vue';
|
||||||
import { getZipCodeData } from '@/helpers/service-location-helper';
|
|
||||||
|
|
||||||
const mockGetServiceabilityDetails = () => {
|
const mockGetServiceabilityDetails = () => {
|
||||||
const serviceabilityDetails = {
|
const serviceabilityDetails = {
|
||||||
|
|
@ -50,43 +49,41 @@ const mockZipcodeData = (zip) => {
|
||||||
state: null,
|
state: null,
|
||||||
zipCodeCtu: null
|
zipCodeCtu: null
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
const mockProviders = () => {
|
const mockProviders = () => Promise.resolve([
|
||||||
return Promise.resolve([
|
{
|
||||||
{
|
address: {
|
||||||
"address": {
|
city: 'COLUMBUS',
|
||||||
"city": "COLUMBUS",
|
country: 'US',
|
||||||
"country": "US",
|
state: 'OH',
|
||||||
"state": "OH",
|
streetAddress: '6826 Sawmill Rd',
|
||||||
"streetAddress": "6826 Sawmill Rd",
|
streetAddress2: '',
|
||||||
"streetAddress2": "",
|
zipCode: '43235',
|
||||||
"zipCode": "43235",
|
zipCodeCtu: '03357'
|
||||||
"zipCodeCtu": "03357"
|
|
||||||
},
|
|
||||||
"distanceInMiles": 4.136335989015438,
|
|
||||||
"providerNumber": "003357",
|
|
||||||
"companyName": "SAFELITE AUTOGLASS - COLUMBUS, OH",
|
|
||||||
"phoneNumber": "6142336400",
|
|
||||||
"isSafeliteShop": true
|
|
||||||
},
|
},
|
||||||
{
|
distanceInMiles: 4.136335989015438,
|
||||||
"address": {
|
providerNumber: '003357',
|
||||||
"city": "Lewis Center",
|
companyName: 'SAFELITE AUTOGLASS - COLUMBUS, OH',
|
||||||
"country": "US",
|
phoneNumber: '6142336400',
|
||||||
"state": "OH",
|
isSafeliteShop: true
|
||||||
"streetAddress": "1343 Cameron Ave",
|
},
|
||||||
"streetAddress2": "",
|
{
|
||||||
"zipCode": "43035",
|
address: {
|
||||||
"zipCodeCtu": "03357"
|
city: 'Lewis Center',
|
||||||
},
|
country: 'US',
|
||||||
"distanceInMiles": 8.193072412262042,
|
state: 'OH',
|
||||||
"providerNumber": "003417",
|
streetAddress: '1343 Cameron Ave',
|
||||||
"companyName": "SAFELITE AUTOGLASS - LEWIS CENTER, OH",
|
streetAddress2: '',
|
||||||
"phoneNumber": "6147815433",
|
zipCode: '43035',
|
||||||
"isSafeliteShop": true
|
zipCodeCtu: '03357'
|
||||||
}
|
},
|
||||||
])
|
distanceInMiles: 8.193072412262042,
|
||||||
}
|
providerNumber: '003417',
|
||||||
|
companyName: 'SAFELITE AUTOGLASS - LEWIS CENTER, OH',
|
||||||
|
phoneNumber: '6147815433',
|
||||||
|
isSafeliteShop: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
jest.mock(
|
jest.mock(
|
||||||
'@/helpers/service-location-helper',
|
'@/helpers/service-location-helper',
|
||||||
() => ({
|
() => ({
|
||||||
|
|
@ -138,13 +135,13 @@ const mountOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function setupMocks({ appointmentType = AppointmentTypeStrings.IN_SHOP }) {
|
function setupMocks({ appointmentType = AppointmentTypeStrings.IN_SHOP }) {
|
||||||
mountOptions.global.plugins = [createTestingPinia({
|
mountOptions.global.plugins = [createTestingPinia({
|
||||||
initialState: {
|
initialState: {
|
||||||
main: {
|
main: {
|
||||||
order: {
|
order: {
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
appointmentType: appointmentType
|
appointmentType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +201,7 @@ describe('service-location.vue', () => {
|
||||||
|
|
||||||
expect(wrapper.vm.zipContainsMilitaryBase).toBe(false);
|
expect(wrapper.vm.zipContainsMilitaryBase).toBe(false);
|
||||||
|
|
||||||
const newMobileServiceZipCode = '45433'
|
const newMobileServiceZipCode = '45433';
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
mobileServiceZipCodeQuestion.vm.$emit('update:modelValue', newMobileServiceZipCode);
|
mobileServiceZipCodeQuestion.vm.$emit('update:modelValue', newMobileServiceZipCode);
|
||||||
581
src/layouts/schedule-page/service-location/service-location.vue
Normal file
581
src/layouts/schedule-page/service-location/service-location.vue
Normal file
|
|
@ -0,0 +1,581 @@
|
||||||
|
<template>
|
||||||
|
<div class="service-location">
|
||||||
|
<alert
|
||||||
|
v-if="displayRecalibrationWarning"
|
||||||
|
ref="alertRecalNoMobile"
|
||||||
|
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
@textLinkClicked="openModalAction" />
|
||||||
|
<alert
|
||||||
|
v-if="displayBigTruckNoShops"
|
||||||
|
ref="alertBigTruckNoShops"
|
||||||
|
cmsWidgetName="AlertBigTruckNoShopsWidget"
|
||||||
|
alertClass="alert-warning" />
|
||||||
|
<div class="appointment-type">
|
||||||
|
<div class="appointment-type-question-text d-flex">
|
||||||
|
<span
|
||||||
|
v-if="recalibrationRequired"
|
||||||
|
class="recal-text">{{ scheduleRecalText }}</span>
|
||||||
|
<span
|
||||||
|
v-if="!requiresInshopRecalibration">{{ appointmentQuestionText }}</span>
|
||||||
|
</div>
|
||||||
|
<alert
|
||||||
|
v-if="displayServiceableInshopOnly"
|
||||||
|
ref="alertInshopOnly"
|
||||||
|
cmsWidgetName="AlertInshopOnlyWidget"
|
||||||
|
:manualCopy="inShopOnlyCopy"
|
||||||
|
:isCollapsible="true"
|
||||||
|
alertClass="alert-warning" />
|
||||||
|
<alert
|
||||||
|
v-if="displayServiceableMobileOnly"
|
||||||
|
ref="alertMobileOnly"
|
||||||
|
cmsWidgetName="AlertMobileOnlyWidget"
|
||||||
|
:manualCopy="mobileOnlyCopy"
|
||||||
|
:isCollapsible="true"
|
||||||
|
alertClass="alert-warning" />
|
||||||
|
<appointmentTypeQuestion
|
||||||
|
v-if="!requiresInshopRecalibration && isServiceableMobile"
|
||||||
|
ref="appointmentTypeQuestion"
|
||||||
|
v-model="selectedAppointmentType"
|
||||||
|
groupName="appointmentTypeQuestion"
|
||||||
|
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||||
|
validationRules="option-required" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isInshop">
|
||||||
|
<alert
|
||||||
|
v-if="displayLowAvailabilityInshop"
|
||||||
|
ref="alertLowAvailabilityInshop"
|
||||||
|
cmsWidgetName="AlertLowAvailabilityInshopWidget"
|
||||||
|
:isCollapsible="true"
|
||||||
|
alertClass="alert-warning" />
|
||||||
|
<shopAddress
|
||||||
|
ref="shopAddress"
|
||||||
|
v-model="selectedProvider"
|
||||||
|
:serviceZipcode="zipCode"
|
||||||
|
:selectedAppointmentType="selectedAppointmentType"
|
||||||
|
modalWidgetName="ChangeLocationModalWidget"
|
||||||
|
cmsWidgetName="ShopAddressWidget"
|
||||||
|
@zipUpdated="handleInShopZipUpdated" />
|
||||||
|
<!-- INTEGRATION TODO: Put this right under the calendar -->
|
||||||
|
<alert
|
||||||
|
v-if="selectedProvider === null"
|
||||||
|
ref="alertNoAvailableShops"
|
||||||
|
cmsWidgetName="AlertNoAvailableShopsWidget"
|
||||||
|
:isCollapsible="false"
|
||||||
|
alertClass="alert-danger" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isMobile">
|
||||||
|
<div class="expandable-link-container">
|
||||||
|
<a
|
||||||
|
v-if="displayMilitaryZipAlert && !militaryBaseWarningExpanded"
|
||||||
|
href="#"
|
||||||
|
class="expandable-link"
|
||||||
|
@click.prevent="militaryBaseWarningExpanded = true">
|
||||||
|
{{ militaryBaseWarningLinkText }}
|
||||||
|
</a>
|
||||||
|
<div
|
||||||
|
v-if="displayMilitaryZipAlert && militaryBaseWarningExpanded"
|
||||||
|
class="expandable-link-text">
|
||||||
|
{{ militaryBaseWarningText }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<serviceZipQuestion
|
||||||
|
ref="mobileServiceZipCodeQuestion"
|
||||||
|
v-model="mobileZipCode"
|
||||||
|
customInputId="mobileServiceZipCode"
|
||||||
|
class="mobile-service-zip-question"
|
||||||
|
:placeholderText="mobileZipPlaceholder"
|
||||||
|
:serviceZipFormatErrorMessage="errorMessages.MOBILE_SERVICE_ZIP_FORMAT"
|
||||||
|
:hasError="mobileZipError !== ''"
|
||||||
|
cmsWidgetName="MobileZipWidget" />
|
||||||
|
<div
|
||||||
|
v-if="mobileZipError"
|
||||||
|
ref="errorMessageDiv"
|
||||||
|
class="row my-1 form-test-error">
|
||||||
|
<span
|
||||||
|
class="d-inline-flex mt-0"
|
||||||
|
role="alert">{{ mobileZipError }}</span>
|
||||||
|
</div>
|
||||||
|
<textBlock
|
||||||
|
v-if="displayMobileFeeDisclaimer"
|
||||||
|
cmsWidgetName="MobileFeeDisclaimerWidget"
|
||||||
|
typeStyle="disclaimer" />
|
||||||
|
</div>
|
||||||
|
<contentGroupModal
|
||||||
|
:ref="RECAL_MODAL_REF_NAME"
|
||||||
|
cssModalHeadlineClass="text-center"
|
||||||
|
cmsWidgetName="RecalModal" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
// Import Supporting Files
|
||||||
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
||||||
|
import errorMessages from '@/constants/error-messages';
|
||||||
|
import { useMainStore } from '@/store';
|
||||||
|
import showIssLoadingModal from '@/helpers/loading-modal-helper.js';
|
||||||
|
import {
|
||||||
|
getAvailabilityRating,
|
||||||
|
getServiceabilityDetails,
|
||||||
|
getZipCodeData,
|
||||||
|
getMobileZipCodeData
|
||||||
|
} from '@/helpers/service-location-helper';
|
||||||
|
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||||
|
|
||||||
|
// Import Component
|
||||||
|
import alert from '@/ux-components/alert/alert.vue';
|
||||||
|
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||||
|
import appointmentTypeQuestion from '@/layouts/schedule-page/service-location/appointment-type-question/appointment-type-question.vue';
|
||||||
|
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||||
|
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
||||||
|
import shopAddress from '@/layouts/schedule-page/service-location/shop-address/shop-address.vue';
|
||||||
|
import serviceZipQuestion from '@/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue';
|
||||||
|
import widgetFields from '@/constants/cms-widget-fields';
|
||||||
|
|
||||||
|
const RECAL_MODAL_REF_NAME = 'RecalModal';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'service-location',
|
||||||
|
components: {
|
||||||
|
alert,
|
||||||
|
textBlock,
|
||||||
|
appointmentTypeQuestion,
|
||||||
|
contentGroupModal,
|
||||||
|
shopAddress,
|
||||||
|
serviceZipQuestion
|
||||||
|
},
|
||||||
|
mixins: [baseFormMixin],
|
||||||
|
emits: ['appointment-type-changed', 'city-updated', 'mobile-zip-updated', 'provider-changed'],
|
||||||
|
setup() {
|
||||||
|
const mainStore = useMainStore();
|
||||||
|
return { mainStore };
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
streetAddress: this.getServiceAddressFromStore(),
|
||||||
|
streetAddress2: this.getServiceAddress2FromStore(),
|
||||||
|
city: this.getServiceCityFromStore(),
|
||||||
|
state: this.getServiceStateFromStore(),
|
||||||
|
zipCode: this.getServiceZipCodeFromStore(),
|
||||||
|
isGlassServiceableInshop: null,
|
||||||
|
isRecalibrationServiceableInshop: null,
|
||||||
|
isGlassServiceableMobile: null,
|
||||||
|
isRecalibrationServiceableMobile: null,
|
||||||
|
selectedAppointmentType: this.getSelectedAppointmentType(),
|
||||||
|
selectedProvider: this.getSelectedProvider(),
|
||||||
|
mobileFeePart: null,
|
||||||
|
mobileProviderNumber: null,
|
||||||
|
zipContainsMilitaryBase: false,
|
||||||
|
zipCodeCtu: null,
|
||||||
|
mobileZipCode: '',
|
||||||
|
mobileZipError: '',
|
||||||
|
militaryBaseWarningExpanded: false,
|
||||||
|
availabilityRating: null,
|
||||||
|
RECAL_MODAL_REF_NAME,
|
||||||
|
errorMessages
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
appointmentQuestionText() {
|
||||||
|
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
|
||||||
|
},
|
||||||
|
displayBigTruckNoShops() {
|
||||||
|
return this.isBigTruck && !this.isServiceableInshop && !this.isServiceableMobile;
|
||||||
|
},
|
||||||
|
displayLowAvailabilityInshop() {
|
||||||
|
return this.availabilityRating === 'low' && this.isInshop;
|
||||||
|
},
|
||||||
|
displayMilitaryZipAlert() {
|
||||||
|
return this.zipContainsMilitaryBase && this.isServiceableMobile;
|
||||||
|
},
|
||||||
|
displayMobileFeeDisclaimer() {
|
||||||
|
return this.mainStore.isNoComp || this.mainStore.isITAC;
|
||||||
|
},
|
||||||
|
displayRecalibrationWarning() {
|
||||||
|
return this.requiresInshopRecalibration;
|
||||||
|
},
|
||||||
|
displayServiceableInshopOnly() {
|
||||||
|
return !this.isServiceableMobile && this.isServiceableInshop && !this.displayRecalibrationWarning;
|
||||||
|
},
|
||||||
|
displayServiceableMobileOnly() {
|
||||||
|
return this.isServiceableMobile && this.recalibrationRequired && !this.isServiceableInshop;
|
||||||
|
},
|
||||||
|
inShopOnlyCopy() {
|
||||||
|
let content = this.getCmsContent('AlertInshopOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||||
|
content = content.replace('{custom:city}', toTitleCase(this.city));
|
||||||
|
return content;
|
||||||
|
},
|
||||||
|
isBigTruck() {
|
||||||
|
return this.mainStore.order.vehicle.isBigTruck;
|
||||||
|
},
|
||||||
|
isInshop() {
|
||||||
|
return (
|
||||||
|
this.selectedAppointmentType === 'Inshop'
|
||||||
|
|| this.selectedAppointmentType === 'Dropoff'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
isMobile() {
|
||||||
|
return this.selectedAppointmentType === AppointmentTypeStrings.MOBILE;
|
||||||
|
},
|
||||||
|
isServiceableInshop() {
|
||||||
|
if (this.isRecalibrationServiceableInshop !== null) {
|
||||||
|
return (this.isGlassServiceableInshop && this.isRecalibrationServiceableInshop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.isGlassServiceableInshop;
|
||||||
|
},
|
||||||
|
isServiceableMobile() {
|
||||||
|
if (this.isRecalibrationServiceableMobile !== null) {
|
||||||
|
return (
|
||||||
|
this.isGlassServiceableMobile
|
||||||
|
&& this.isRecalibrationServiceableMobile
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.isGlassServiceableMobile;
|
||||||
|
},
|
||||||
|
militaryBaseWarningLinkText() {
|
||||||
|
return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.HEADLINE_TEXT);
|
||||||
|
},
|
||||||
|
militaryBaseWarningText() {
|
||||||
|
return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||||
|
},
|
||||||
|
mobileOnlyCopy() {
|
||||||
|
let content = this.getCmsContent('AlertMobileOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||||
|
content = content.replace('{custom:city}', toTitleCase(this.city));
|
||||||
|
return content;
|
||||||
|
},
|
||||||
|
mobileZipPlaceholder() {
|
||||||
|
return this.getCmsContent('MobileZipPlaceHolderWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
|
},
|
||||||
|
recalibrationRequired() {
|
||||||
|
return this.mainStore.hasRecalibrationPart;
|
||||||
|
},
|
||||||
|
requiresInshopRecalibration() {
|
||||||
|
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
||||||
|
return (
|
||||||
|
this.isServiceableInshop
|
||||||
|
&& this.isGlassServiceableMobile
|
||||||
|
&& this.isRecalibrationServiceableMobile === false
|
||||||
|
);
|
||||||
|
},
|
||||||
|
scheduleRecalText() {
|
||||||
|
if (this.requiresInshopRecalibration) {
|
||||||
|
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
|
||||||
|
}
|
||||||
|
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
city(newCity, oldCity) {
|
||||||
|
if (newCity !== oldCity) {
|
||||||
|
this.$emit('city-updated', newCity);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mobileZipCode(newZip, oldZip) {
|
||||||
|
if (newZip !== '' && newZip !== oldZip) {
|
||||||
|
showIssLoadingModal(true);
|
||||||
|
await this.updateMobileZip();
|
||||||
|
const updateMobileZipServiceLocationObj = {
|
||||||
|
mobileProviderNumber: this.mobileProviderNumber,
|
||||||
|
provider: null,
|
||||||
|
refreshDatePicker: true,
|
||||||
|
zipCode: this.zipCode,
|
||||||
|
zipCodeCtu: this.zipCodeCtu
|
||||||
|
};
|
||||||
|
this.$emit('mobile-zip-updated', updateMobileZipServiceLocationObj);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectedAppointmentType(newValue, oldValue) {
|
||||||
|
if (this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP && this.selectedProvider && this.availabilityRating === null) {
|
||||||
|
this.refreshAvailabilityRating();
|
||||||
|
|
||||||
|
const appointmenTypeServiceLocationObj = {
|
||||||
|
appointmentType: newValue,
|
||||||
|
mobileProviderNumber: null,
|
||||||
|
provider: this.selectedProvider,
|
||||||
|
refreshDatePicker: oldValue !== newValue && oldValue !== null,
|
||||||
|
resetDatePicker: oldValue !== newValue || oldValue === null,
|
||||||
|
zipCode: this.zipCode,
|
||||||
|
zipCodeCtu: this.zipCodeCtu
|
||||||
|
};
|
||||||
|
this.$emit('appointment-type-changed', appointmenTypeServiceLocationObj);
|
||||||
|
} else {
|
||||||
|
const appointmenTypeServiceLocationObj = {
|
||||||
|
appointmentType: newValue,
|
||||||
|
mobileProviderNumber: this.mobileProviderNumber,
|
||||||
|
provider: null,
|
||||||
|
refreshDatePicker: false,
|
||||||
|
resetDatePicker: true,
|
||||||
|
zipCode: this.zipCode,
|
||||||
|
zipCodeCtu: this.zipCodeCtu
|
||||||
|
};
|
||||||
|
this.$emit('appointment-type-changed', appointmenTypeServiceLocationObj);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectedProvider(newProvider, oldProvider) {
|
||||||
|
if (newProvider?.providerNumber !== oldProvider?.providerNumber) {
|
||||||
|
const appointmentIsInshop = this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP;
|
||||||
|
const returnedProvider = {
|
||||||
|
provider: newProvider,
|
||||||
|
refreshDatePicker: appointmentIsInshop && oldProvider?.providerNumber !== null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (appointmentIsInshop && newProvider?.providerNumber != null) {
|
||||||
|
this.refreshAvailabilityRating();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('provider-changed', returnedProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initializeComponent(initialData) {
|
||||||
|
this.setData(initialData);
|
||||||
|
},
|
||||||
|
async forwardButtonAction() {
|
||||||
|
let provider = this.selectedProvider;
|
||||||
|
this.mainStore.updateMobileFee(null);
|
||||||
|
if (this.isMobile) {
|
||||||
|
if (this.mainStore.isNoComp || this.mainStore.isITAC) {
|
||||||
|
this.mainStore.updateMobileFee(this.mobileFeePart);
|
||||||
|
}
|
||||||
|
|
||||||
|
provider = {
|
||||||
|
providerNumber: this.mobileProviderNumber,
|
||||||
|
address: {
|
||||||
|
streetAddress: null,
|
||||||
|
city: null,
|
||||||
|
state: null,
|
||||||
|
zipCode: null,
|
||||||
|
zipCodeCtu: null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mainStore.saveServiceLocation({
|
||||||
|
address: this.streetAddress,
|
||||||
|
address2: this.streetAddress2,
|
||||||
|
city: this.city,
|
||||||
|
state: this.state,
|
||||||
|
zipCode: this.zipCode,
|
||||||
|
zipCodeCtu: this.zipCodeCtu,
|
||||||
|
appointmentType: this.selectedAppointmentType,
|
||||||
|
provider
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openModalAction(modalName) {
|
||||||
|
this.$refs[modalName].openModal();
|
||||||
|
},
|
||||||
|
resetDependentState() {},
|
||||||
|
getServiceAddressFromStore() {
|
||||||
|
return useMainStore().order.serviceLocation.address;
|
||||||
|
},
|
||||||
|
getServiceAddress2FromStore() {
|
||||||
|
return useMainStore().order.serviceLocation.address2;
|
||||||
|
},
|
||||||
|
getServiceCityFromStore() {
|
||||||
|
return useMainStore().order.serviceLocation.city;
|
||||||
|
},
|
||||||
|
getServiceStateFromStore() {
|
||||||
|
return (
|
||||||
|
useMainStore().order.serviceLocation.state
|
||||||
|
|| useMainStore().order.customer.address.state
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getServiceZipCodeFromStore() {
|
||||||
|
return (
|
||||||
|
useMainStore().order.serviceLocation.zipCode
|
||||||
|
|| useMainStore().order.customer.address.zipCode
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getSelectedAppointmentType() {
|
||||||
|
return useMainStore().order.serviceLocation.appointmentType;
|
||||||
|
},
|
||||||
|
getSelectedProvider() {
|
||||||
|
return useMainStore().order.serviceLocation.provider;
|
||||||
|
},
|
||||||
|
async handleInShopZipUpdated(newZip) {
|
||||||
|
this.zipCode = newZip;
|
||||||
|
const zipCodeData = await getZipCodeData(this.zipCode);
|
||||||
|
this.city = zipCodeData.city;
|
||||||
|
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||||
|
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||||
|
|
||||||
|
const serviceabilityDetailsPromise = getServiceabilityDetails(this.zipCode);
|
||||||
|
await serviceabilityDetailsPromise.then((result) => {
|
||||||
|
const details = result.data;
|
||||||
|
if (details) {
|
||||||
|
this.setServiceabilityDetails(details);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
refreshAvailabilityRating() {
|
||||||
|
const startDate = new Date();
|
||||||
|
const endDate = new Date();
|
||||||
|
endDate.setDate(startDate.getDate() + 6);
|
||||||
|
const formattedStartDate = startDate.toISOString().split('T')[0];
|
||||||
|
const formattedEndDate = endDate.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
getAvailabilityRating(
|
||||||
|
formattedStartDate,
|
||||||
|
formattedEndDate,
|
||||||
|
AppointmentTypeStrings.IN_SHOP,
|
||||||
|
this.selectedProvider ? this.selectedProvider.providerNumber : null
|
||||||
|
).then((rating) => {
|
||||||
|
this.availabilityRating = rating;
|
||||||
|
}).catch(() => {
|
||||||
|
this.availabilityRating = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setCtuForMobile(val) {
|
||||||
|
this.zipCodeCtu = val;
|
||||||
|
},
|
||||||
|
setData(initialData) {
|
||||||
|
if (initialData.zipCodeData) {
|
||||||
|
this.zipContainsMilitaryBase = initialData.zipCodeData.containsMilitaryBase;
|
||||||
|
this.zipCodeCtu = initialData.zipCodeData.zipCodeCtu;
|
||||||
|
this.city = initialData.zipCodeData.city;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialData.serviceabilityDetails) {
|
||||||
|
this.setServiceabilityDetails(initialData.serviceabilityDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialData.mobileFeePart) {
|
||||||
|
this.mobileFeePart = initialData.mobileFeePart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialData.providers) {
|
||||||
|
this.setMobileProviderNumber(initialData.providers.mobileProviderNumber);
|
||||||
|
let foundMatch = false;
|
||||||
|
if (this.selectedProvider && this.selectedProvider.providerNumber) {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
const matchedProvider = initialData.providers.shopProviders.find((provider) => provider.providerNumber === this.selectedProvider.providerNumber);
|
||||||
|
if (matchedProvider) {
|
||||||
|
foundMatch = true;
|
||||||
|
this.selectedProvider = matchedProvider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initialData.providers.shopProviders.length > 0 && !foundMatch) {
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
|
this.selectedProvider = initialData.providers.shopProviders[0];
|
||||||
|
} else if (initialData.providers.shopProviders.length === 0) {
|
||||||
|
this.selectedProvider = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialData.glassFees) {
|
||||||
|
useMainStore().getCombinedQuote(initialData.glassFees)
|
||||||
|
.then((combinedQuote) => {
|
||||||
|
this.setGlassFeeItems(combinedQuote);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setContainsMilitaryBase(val) {
|
||||||
|
if (this.zipContainsMilitaryBase !== val) {
|
||||||
|
this.zipContainsMilitaryBase = val;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setGlassFeeItems(newGlassFeeItems) {
|
||||||
|
this.mainStore.updateGlassFees(newGlassFeeItems);
|
||||||
|
},
|
||||||
|
setMobileProviderNumber(providerNumber) {
|
||||||
|
this.mobileProviderNumber = providerNumber;
|
||||||
|
},
|
||||||
|
setServiceabilityDetails(serviceabilityDetails) {
|
||||||
|
this.isGlassServiceableInshop = serviceabilityDetails.isGlassServiceableInshop;
|
||||||
|
this.isRecalibrationServiceableInshop = serviceabilityDetails.isRecalibrationServiceableInshop;
|
||||||
|
this.isGlassServiceableMobile = serviceabilityDetails.isGlassServiceableMobile;
|
||||||
|
this.isRecalibrationServiceableMobile = serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||||
|
if (!this.isServiceableMobile) {
|
||||||
|
this.selectedAppointmentType = AppointmentTypeStrings.IN_SHOP;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async updateMobileZip() {
|
||||||
|
this.mobileZipError = '';
|
||||||
|
const zipCodeData = await getMobileZipCodeData(this.mobileZipCode);
|
||||||
|
|
||||||
|
if (!zipCodeData.isValid) {
|
||||||
|
this.mobileZipError = errorMessages.INVALID_ZIP;
|
||||||
|
} else if (!zipCodeData.isServiceable) {
|
||||||
|
this.mobileZipError = errorMessages.NO_SERVICE_IN_AREA(toTitleCase(zipCodeData.city));
|
||||||
|
} else {
|
||||||
|
this.city = zipCodeData.city;
|
||||||
|
this.zipCode = this.mobileZipCode;
|
||||||
|
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||||
|
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||||
|
|
||||||
|
const serviceabilityDetailsPromise = getServiceabilityDetails(this.mobileZipCode);
|
||||||
|
await serviceabilityDetailsPromise.then((result) => {
|
||||||
|
const details = result.data;
|
||||||
|
if (details) {
|
||||||
|
this.setServiceabilityDetails(details);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const providersPromise = useMainStore().getProviders(this.mobileZipCode);
|
||||||
|
await providersPromise.then((result) => {
|
||||||
|
const providers = result.data;
|
||||||
|
if (providers) {
|
||||||
|
this.setMobileProviderNumber(providers.mobileProviderNumber);
|
||||||
|
if (providers.shopProviders.length > 0) {
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
|
this.selectedProvider = providers.shopProviders[0];
|
||||||
|
} else {
|
||||||
|
this.selectedProvider = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$page-side-padding: 1.5rem;
|
||||||
|
|
||||||
|
.service-location {
|
||||||
|
> div {
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.form-test-error {
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
}
|
||||||
|
.appointment-type-question-text {
|
||||||
|
color: $black;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.625rem;
|
||||||
|
flex-direction: column;
|
||||||
|
.recal-text {
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mobile-service-zip-question {
|
||||||
|
:deep(.input-wrapper.has-text-button) {
|
||||||
|
button {
|
||||||
|
background-color: #1574a1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.form-test-error span) {
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.expandable-link-container {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.expandable-link {
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
text-decoration: none;
|
||||||
|
color: $heritage-blue-primary;
|
||||||
|
line-height: 1.375rem;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import serviceZipModalQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue';
|
import serviceZipModalQuestion from '@/layouts/schedule-page/service-location/service-zip-modal-question/service-zip-modal-question.vue';
|
||||||
|
|
||||||
global.crypto = crypto;
|
global.crypto = crypto;
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
import serviceZipQuestion from '@/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue';
|
||||||
import modal from '@/digital-components/modal/modal.vue';
|
import modal from '@/digital-components/modal/modal.vue';
|
||||||
import alert from '@/ux-components/alert/alert.vue';
|
import alert from '@/ux-components/alert/alert.vue';
|
||||||
|
|
||||||
|
|
@ -177,6 +177,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@import "@/styles/ux-variables-svg-strings.scss";
|
||||||
a#serviceZipLinkPromptId {
|
a#serviceZipLinkPromptId {
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
}
|
}
|
||||||
|
|
@ -186,7 +187,7 @@ a#serviceZipLinkPromptId {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 13px;
|
width: 13px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 13 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.49635 1.00142e-07C5.64734 -0.000153295 4.80722 0.175918 4.0274 0.517444C3.24757 0.858969 2.54443 1.35877 1.96099 1.98626C0.765713 3.27588 0.0999756 4.98141 0.0999756 6.75394C0.0999756 8.52646 0.765713 10.232 1.96099 11.5216L5.98324 15.777C6.04954 15.8475 6.12918 15.9036 6.21736 15.9419C6.30555 15.9802 6.40045 16 6.49635 16C6.59225 16 6.68716 15.9802 6.77534 15.9419C6.86353 15.9036 6.94317 15.8475 7.00946 15.777L11.0317 11.52C12.2391 10.2383 12.909 8.52914 12.8999 6.75394C12.9094 4.97818 12.2394 3.26832 11.0317 1.98626C10.4481 1.35899 9.74493 0.859347 8.96514 0.517839C8.18535 0.176331 7.34532 0.000130509 6.49635 1.00142e-07V1.00142e-07ZM6.49635 9.13131C6.02507 9.13131 5.56437 8.98913 5.17251 8.72275C4.78065 8.45637 4.47524 8.07776 4.29488 7.63479C4.11453 7.19181 4.06734 6.70438 4.15928 6.23412C4.25123 5.76387 4.47817 5.33191 4.81142 4.99287C5.14467 4.65384 5.56925 4.42295 6.03148 4.32941C6.49371 4.23587 6.97282 4.28388 7.40823 4.46736C7.84364 4.65085 8.21579 4.96157 8.47762 5.36023C8.73945 5.7589 8.87921 6.2276 8.87921 6.70707C8.87921 7.34974 8.62837 7.96611 8.18185 8.4207C7.73532 8.87528 7.12964 9.13088 6.49794 9.13131H6.49635Z' fill='%231574A1'/%3E%3C/svg%3E%0A");
|
background-image: url($svg-update-zip-text-link);
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
import serviceZipQuestion from '@/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue';
|
||||||
|
|
||||||
describe('service-zip-question.vue', () => {
|
describe('service-zip-question.vue', () => {
|
||||||
it('Should get the modelValue', async () => {
|
it('Should get the modelValue', async () => {
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
mask="#####"
|
mask="#####"
|
||||||
isRequired
|
isRequired
|
||||||
:hasError="hasError"
|
:hasError="hasError"
|
||||||
@clickEvent="updateModelValue"
|
:validationRules="`zip-required|${cmsWidgetName}-zip-format`"
|
||||||
:validationRules="`zip-required|${cmsWidgetName}-zip-format`" />
|
@clickEvent="updateModelValue" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -41,24 +41,26 @@ export default {
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
emits: ['update:modelValue'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
internalZipcode: this.modelValue
|
internalZipcode: this.modelValue
|
||||||
}
|
};
|
||||||
},
|
|
||||||
emits: ['update:modelValue'],
|
|
||||||
methods: {
|
|
||||||
updateModelValue() {
|
|
||||||
this.$emit('update:modelValue', this.internalZipcode);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
modelValue(newValue) {
|
modelValue(newValue) {
|
||||||
this.internalZipcode = newValue;
|
if (newValue !== this.internalZipcode) {
|
||||||
|
this.internalZipcode = newValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
defineRule(`${this.cmsWidgetName}-zip-format`, regex(/^\d{5}$/, this.serviceZipFormatErrorMessage));
|
defineRule(`${this.cmsWidgetName}-zip-format`, regex(/^\d{5}$/, this.serviceZipFormatErrorMessage));
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateModelValue() {
|
||||||
|
this.$emit('update:modelValue', this.internalZipcode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -5,7 +5,9 @@
|
||||||
<div
|
<div
|
||||||
class="shop-address"
|
class="shop-address"
|
||||||
aria-live="polite">
|
aria-live="polite">
|
||||||
<div class="address-header">{{ questionText }}</div>
|
<div class="address-header">
|
||||||
|
{{ questionText }}
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="modelValue"
|
v-if="modelValue"
|
||||||
class="current-address">
|
class="current-address">
|
||||||
|
|
@ -13,7 +15,9 @@
|
||||||
<span class="shop-name">{{ displayedShopName }}</span>
|
<span class="shop-name">{{ displayedShopName }}</span>
|
||||||
<span class="shop-distance">{{ modelValue.distanceInMiles?.toFixed(2) }} mi</span>
|
<span class="shop-distance">{{ modelValue.distanceInMiles?.toFixed(2) }} mi</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="address-line">{{ getProviderAddress(modelValue) }}</div>
|
<div class="address-line">
|
||||||
|
{{ getProviderAddress(modelValue) }}
|
||||||
|
</div>
|
||||||
<div class="address-line">
|
<div class="address-line">
|
||||||
{{ getProviderCityZipState(modelValue) }}
|
{{ getProviderCityZipState(modelValue) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -29,9 +33,9 @@
|
||||||
:variant="'primary'"
|
:variant="'primary'"
|
||||||
@clickEvent="openModal" />
|
@clickEvent="openModal" />
|
||||||
<alert
|
<alert
|
||||||
class="alert-shop-distance"
|
|
||||||
v-if="modelValue?.distanceInMiles > 30"
|
v-if="modelValue?.distanceInMiles > 30"
|
||||||
ref="alertShopDistance"
|
ref="alertShopDistance"
|
||||||
|
class="alert-shop-distance"
|
||||||
cmsWidgetName="AlertShopDistanceWidget"
|
cmsWidgetName="AlertShopDistanceWidget"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
<modal
|
<modal
|
||||||
|
|
@ -48,9 +52,9 @@
|
||||||
:markers="providerAddresses"
|
:markers="providerAddresses"
|
||||||
:zipCode="internalZipcode" />
|
:zipCode="internalZipcode" />
|
||||||
<dropdownQuestion
|
<dropdownQuestion
|
||||||
inputId="searchRadiusDropdown"
|
|
||||||
ref="searchRadiusQuestion"
|
ref="searchRadiusQuestion"
|
||||||
v-model="searchRadiusInMiles"
|
v-model="searchRadiusInMiles"
|
||||||
|
inputId="searchRadiusDropdown"
|
||||||
:cmsWidgetName="searchRadiusQuestionWidgetName"
|
:cmsWidgetName="searchRadiusQuestionWidgetName"
|
||||||
:variant="dropdownVariants.compact"
|
:variant="dropdownVariants.compact"
|
||||||
:options="searchRadiusOptions" />
|
:options="searchRadiusOptions" />
|
||||||
|
|
@ -93,7 +97,7 @@
|
||||||
import alert from '@/ux-components/alert/alert.vue';
|
import alert from '@/ux-components/alert/alert.vue';
|
||||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||||
import modal from '@/digital-components/modal/modal.vue';
|
import modal from '@/digital-components/modal/modal.vue';
|
||||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
import serviceZipQuestion from '@/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue';
|
||||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||||
|
|
@ -136,8 +140,9 @@ export default {
|
||||||
cmsWidgetName: String,
|
cmsWidgetName: String,
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
modalWidgetName: String,
|
modalWidgetName: String,
|
||||||
selectedAppointmentType: String,
|
selectedAppointmentType: String
|
||||||
},
|
},
|
||||||
|
emits: ['update:modelValue', 'zip-updated'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
toTitleCase,
|
toTitleCase,
|
||||||
|
|
@ -147,7 +152,7 @@ export default {
|
||||||
searchRadiusQuestionWidgetName: 'SearchRadiusQuestionWidget',
|
searchRadiusQuestionWidgetName: 'SearchRadiusQuestionWidget',
|
||||||
textboxQuestionWidgetName: 'ChangeLocationZipQuestionWidget',
|
textboxQuestionWidgetName: 'ChangeLocationZipQuestionWidget',
|
||||||
shopListButton: markRaw(shopListButton),
|
shopListButton: markRaw(shopListButton),
|
||||||
searchRadiusInMiles: "25",
|
searchRadiusInMiles: '25',
|
||||||
nearbyShops: [],
|
nearbyShops: [],
|
||||||
modalPositions,
|
modalPositions,
|
||||||
dropdownVariants,
|
dropdownVariants,
|
||||||
|
|
@ -157,7 +162,6 @@ export default {
|
||||||
SERVICE_ZIP_QUESTION_REF_NAME
|
SERVICE_ZIP_QUESTION_REF_NAME
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue', 'zip-updated'],
|
|
||||||
computed: {
|
computed: {
|
||||||
questionText() {
|
questionText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
|
return this.getCmsContent(this.cmsWidgetName, widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
|
||||||
|
|
@ -166,12 +170,13 @@ export default {
|
||||||
return this.getCmsContent('ShowMoreShopsLinkWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
return this.getCmsContent('ShowMoreShopsLinkWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
},
|
},
|
||||||
displayedShopName() {
|
displayedShopName() {
|
||||||
if(this.modelValue.isSafeliteShop) {
|
if (this.modelValue.isSafeliteShop) {
|
||||||
return this.getCmsContent('SafeliteShopNameWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
return this.getCmsContent('SafeliteShopNameWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
}
|
}
|
||||||
return toTitleCase(this.modelValue.companyName);
|
return toTitleCase(this.modelValue.companyName);
|
||||||
},
|
},
|
||||||
modalHeaderText() {
|
modalHeaderText() {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT).replaceAll('{custom:serviceZipcode}', this.internalZipcode);
|
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT).replaceAll('{custom:serviceZipcode}', this.internalZipcode);
|
||||||
},
|
},
|
||||||
modalFooterText() {
|
modalFooterText() {
|
||||||
|
|
@ -193,7 +198,7 @@ export default {
|
||||||
availabilityRatingCallback: getAvailabilityRating,
|
availabilityRatingCallback: getAvailabilityRating,
|
||||||
startDate: formattedStartDate,
|
startDate: formattedStartDate,
|
||||||
endDate: formattedEndDate,
|
endDate: formattedEndDate,
|
||||||
shopAppointmentType: "InshopOrDropoff"
|
shopAppointmentType: 'InshopOrDropoff'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
serviceZipPrompt() {
|
serviceZipPrompt() {
|
||||||
|
|
@ -218,8 +223,8 @@ export default {
|
||||||
},
|
},
|
||||||
searchRadiusOptions() {
|
searchRadiusOptions() {
|
||||||
const optionsObj = {};
|
const optionsObj = {};
|
||||||
if(this.searchRadiusArray) {
|
if (this.searchRadiusArray) {
|
||||||
this.searchRadiusArray.forEach(option => {
|
this.searchRadiusArray.forEach((option) => {
|
||||||
optionsObj[option.Name] = option.Text;
|
optionsObj[option.Name] = option.Text;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -231,11 +236,11 @@ export default {
|
||||||
fullAddress: this.getFullProviderAddress(provider),
|
fullAddress: this.getFullProviderAddress(provider),
|
||||||
addressLines: [this.getProviderAddress(provider), this.getProviderCityZipState(provider)]
|
addressLines: [this.getProviderAddress(provider), this.getProviderCityZipState(provider)]
|
||||||
})) ?? [];
|
})) ?? [];
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
async internalZipcode() {
|
async internalZipcode() {
|
||||||
if(this.openingModal) {
|
if (this.openingModal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const shopsUpdated = await this.updateShops();
|
const shopsUpdated = await this.updateShops();
|
||||||
|
|
@ -245,27 +250,28 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async searchRadiusInMiles() {
|
async searchRadiusInMiles() {
|
||||||
if(this.openingModal) {
|
if (this.openingModal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.updateShops();
|
await this.updateShops();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// eslint-disable-next-line consistent-return
|
||||||
async updateShops(autoExpand = false) {
|
async updateShops(autoExpand = false) {
|
||||||
this.errorMessage = '';
|
this.errorMessage = '';
|
||||||
let result = await this.getNearbyShops(this.searchRadiusInMiles);
|
let result = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||||
let currentSearchIndex = this.searchRadiusArray.findIndex(option => option.Name === this.searchRadiusInMiles);
|
let currentSearchIndex = this.searchRadiusArray.findIndex((option) => option.Name === this.searchRadiusInMiles);
|
||||||
while (autoExpand && result.length === 0 && currentSearchIndex < this.searchRadiusArray.length - 1) {
|
while (autoExpand && result.length === 0 && currentSearchIndex < this.searchRadiusArray.length - 1) {
|
||||||
const newSearchRadius = this.searchRadiusArray[currentSearchIndex + 1].Name;
|
const newSearchRadius = this.searchRadiusArray[currentSearchIndex + 1].Name;
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
result = await this.getNearbyShops(newSearchRadius);
|
result = await this.getNearbyShops(newSearchRadius);
|
||||||
currentSearchIndex++;
|
currentSearchIndex += 1;
|
||||||
}
|
}
|
||||||
if (result.length === 0) {
|
if (result.length === 0) {
|
||||||
this.errorMessage = errorMessages.ZIP_CODE_NOT_SERVICED_FOR_VEHICLE;
|
this.errorMessage = errorMessages.ZIP_CODE_NOT_SERVICED_FOR_VEHICLE;
|
||||||
}
|
} else {
|
||||||
else {
|
if (!result.find((shop) => shop.providerNumber === this.internalProviderNumber)) {
|
||||||
if (!result.find(shop => shop.providerNumber === this.internalProviderNumber)) {
|
|
||||||
this.internalProviderNumber = '';
|
this.internalProviderNumber = '';
|
||||||
await this.$nextTick();
|
await this.$nextTick();
|
||||||
}
|
}
|
||||||
|
|
@ -283,7 +289,7 @@ export default {
|
||||||
onModalOpened() {
|
onModalOpened() {
|
||||||
this.openingModal = true;
|
this.openingModal = true;
|
||||||
this.internalZipcode = this.serviceZipcode;
|
this.internalZipcode = this.serviceZipcode;
|
||||||
this.searchRadiusInMiles = "25";
|
this.searchRadiusInMiles = '25';
|
||||||
this.nearbyShops = [];
|
this.nearbyShops = [];
|
||||||
this.updateShops(true).then(() => {
|
this.updateShops(true).then(() => {
|
||||||
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
||||||
|
|
@ -295,7 +301,7 @@ export default {
|
||||||
this.forceServiceZipRerender();
|
this.forceServiceZipRerender();
|
||||||
},
|
},
|
||||||
async updateSelectedProvider() {
|
async updateSelectedProvider() {
|
||||||
const selectedShop = this.nearbyShops.find(shop => shop.providerNumber === this.internalProviderNumber);
|
const selectedShop = this.nearbyShops.find((shop) => shop.providerNumber === this.internalProviderNumber);
|
||||||
if (selectedShop) {
|
if (selectedShop) {
|
||||||
this.$emit('update:modelValue', selectedShop);
|
this.$emit('update:modelValue', selectedShop);
|
||||||
this.$emit('zip-updated', this.internalZipcode);
|
this.$emit('zip-updated', this.internalZipcode);
|
||||||
|
|
@ -303,7 +309,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getNearbyShops(radiusInMiles) {
|
async getNearbyShops(radiusInMiles) {
|
||||||
const result = await useMainStore().getProviders(this.internalZipcode, radiusInMiles);
|
const result = await useMainStore().getProviders(this.internalZipcode, radiusInMiles);
|
||||||
return result.data.shopProviders;
|
return result.data.shopProviders;
|
||||||
},
|
},
|
||||||
getFullProviderAddress(provider) {
|
getFullProviderAddress(provider) {
|
||||||
|
|
@ -341,7 +347,7 @@ export default {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.renderServiceZip = true;
|
this.renderServiceZip = true;
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -364,10 +370,11 @@ export default {
|
||||||
margin: .625rem 0;
|
margin: .625rem 0;
|
||||||
}
|
}
|
||||||
.no-shops-found {
|
.no-shops-found {
|
||||||
font-size: .75rem;
|
font-size: .8125rem;
|
||||||
margin: .75rem 0rem;
|
margin: .75rem 0rem;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
line-height: 1.375rem;
|
line-height: 1.375rem;
|
||||||
|
color: #4d4e53;
|
||||||
}
|
}
|
||||||
.more-shops-button {
|
.more-shops-button {
|
||||||
margin-bottom: 1.25rem;
|
margin-bottom: 1.25rem;
|
||||||
|
|
@ -1,658 +0,0 @@
|
||||||
<template>
|
|
||||||
<Form
|
|
||||||
ref="theForm"
|
|
||||||
v-slot="{ meta }"
|
|
||||||
@submit="onSubmit"
|
|
||||||
@invalidSubmit="onInvalidSubmit">
|
|
||||||
<div class="fade-on-route-transition">
|
|
||||||
<div class="justify-content-center">
|
|
||||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
|
||||||
</div>
|
|
||||||
<div class="iss-heritage-container-width">
|
|
||||||
<div class="service-location-container iss-heritage-content-container-width">
|
|
||||||
<siteSubHeader
|
|
||||||
cmsWidgetName="SiteSubHeaderWidget"
|
|
||||||
class="subheader" />
|
|
||||||
<alert
|
|
||||||
v-if="displayRecalibrationWarning"
|
|
||||||
ref="alertRecalNoMobile"
|
|
||||||
class="my-5"
|
|
||||||
cmsWidgetName="AlertRecalNoMobileWidget"
|
|
||||||
alertClass="alert-warning"
|
|
||||||
@text-link-clicked="openModalAction" />
|
|
||||||
<alert
|
|
||||||
v-if="displayBigTruckNoShops"
|
|
||||||
ref="alertBigTruckNoShops"
|
|
||||||
class="my-5"
|
|
||||||
cmsWidgetName="AlertBigTruckNoShopsWidget"
|
|
||||||
alertClass="alert-warning" />
|
|
||||||
<div class="appointment-type">
|
|
||||||
<div class="appointment-type-question-text d-flex">
|
|
||||||
<span class="w-100 recal-text" v-if="recalibrationRequired">{{ scheduleRecalText }}</span>
|
|
||||||
<span class="w-100" v-if="!requiresInshopRecalibration">{{ appointmentQuestionText }}</span>
|
|
||||||
</div>
|
|
||||||
<alert
|
|
||||||
v-if="displayServiceableInshopOnly"
|
|
||||||
ref="alertInshopOnly"
|
|
||||||
cmsWidgetName="AlertInshopOnlyWidget"
|
|
||||||
:manualCopy="inShopOnlyCopy"
|
|
||||||
:isCollapsible="true"
|
|
||||||
alertClass="alert-warning" />
|
|
||||||
<alert
|
|
||||||
v-if="displayServiceableMobileOnly"
|
|
||||||
ref="alertMobileOnly"
|
|
||||||
cmsWidgetName="AlertMobileOnlyWidget"
|
|
||||||
:manualCopy="mobileOnlyCopy"
|
|
||||||
:isCollapsible="true"
|
|
||||||
alertClass="alert-warning" />
|
|
||||||
<appointmentTypeQuestion
|
|
||||||
v-if="!requiresInshopRecalibration && isServiceableMobile"
|
|
||||||
ref="appointmentTypeQuestion"
|
|
||||||
v-model="selectedAppointmentType"
|
|
||||||
groupName="appointmentTypeQuestion"
|
|
||||||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
|
||||||
validationRules="option-required" />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="isInshop">
|
|
||||||
<alert
|
|
||||||
v-if="displayLowAvailabilityInshop"
|
|
||||||
ref="alertLowAvailabilityInshop"
|
|
||||||
cmsWidgetName="AlertLowAvailabilityInshopWidget"
|
|
||||||
:isCollapsible="true"
|
|
||||||
alertClass="alert-warning" />
|
|
||||||
<shopAddress
|
|
||||||
ref="shopAddress"
|
|
||||||
v-model="selectedProvider"
|
|
||||||
:serviceZipcode="zipCode"
|
|
||||||
:selectedAppointmentType="selectedAppointmentType"
|
|
||||||
modalWidgetName="ChangeLocationModalWidget"
|
|
||||||
cmsWidgetName="ShopAddressWidget"
|
|
||||||
@zip-updated="handleInShopZipUpdated" />
|
|
||||||
<!-- INTEGRATION TODO: Put this right under the calendar -->
|
|
||||||
<alert
|
|
||||||
v-if="selectedProvider === null"
|
|
||||||
ref="alertNoAvailableShops"
|
|
||||||
cmsWidgetName="AlertNoAvailableShopsWidget"
|
|
||||||
:isCollapsible="true"
|
|
||||||
alertClass="alert-danger" />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="isMobile">
|
|
||||||
<div class="expandable-link-container">
|
|
||||||
<a
|
|
||||||
v-if="displayMilitaryZipAlert && !militaryBaseWarningExpanded"
|
|
||||||
href="#"
|
|
||||||
class="expandable-link"
|
|
||||||
@click.prevent="militaryBaseWarningExpanded = true">
|
|
||||||
{{ militaryBaseWarningLinkText }}
|
|
||||||
</a>
|
|
||||||
<div
|
|
||||||
v-if="displayMilitaryZipAlert && militaryBaseWarningExpanded"
|
|
||||||
class="expandable-link-text">
|
|
||||||
{{ militaryBaseWarningText }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<serviceZipQuestion
|
|
||||||
ref="mobileServiceZipCodeQuestion"
|
|
||||||
v-model="mobileZipCode"
|
|
||||||
customInputId="mobileServiceZipCode"
|
|
||||||
class="mobile-service-zip-question"
|
|
||||||
:placeholderText="mobileZipPlaceholder"
|
|
||||||
:serviceZipFormatErrorMessage="errorMessages.MOBILE_SERVICE_ZIP_FORMAT"
|
|
||||||
:hasError="mobileZipError !== ''"
|
|
||||||
cmsWidgetName="MobileZipWidget" />
|
|
||||||
<div
|
|
||||||
v-if="mobileZipError"
|
|
||||||
ref="errorMessageDiv"
|
|
||||||
class="row my-1 form-test-error">
|
|
||||||
<span
|
|
||||||
class="d-inline-flex mt-0"
|
|
||||||
role="alert">{{ mobileZipError }}</span>
|
|
||||||
</div>
|
|
||||||
<textBlock
|
|
||||||
v-if="displayMobileFeeDisclaimer"
|
|
||||||
cmsWidgetName="MobileFeeDisclaimerWidget"
|
|
||||||
typeStyle="disclaimer" />
|
|
||||||
</div>
|
|
||||||
<contentGroupModal
|
|
||||||
:ref="RECAL_MODAL_REF_NAME"
|
|
||||||
cssModalHeadlineClass="text-center"
|
|
||||||
cmsWidgetName="RecalModal" />
|
|
||||||
<siteFooter
|
|
||||||
:ref="SITE_FOOTER_REF_NAME"
|
|
||||||
class="mt-5"
|
|
||||||
cmsWidgetName="SiteFooterWidget"
|
|
||||||
:isForwardActionDisabled="
|
|
||||||
!meta.valid || displayNoShopsAlert || displayBigTruckNoShops
|
|
||||||
"
|
|
||||||
@backClicked="navigateBack(this, navigateBackScenario)"
|
|
||||||
@forwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
// Import Supporting Files
|
|
||||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
|
||||||
import settleAllPromises from '@/helpers/layout-helper';
|
|
||||||
import errorMessages from '@/constants/error-messages';
|
|
||||||
import { useMainStore } from '@/store';
|
|
||||||
import {
|
|
||||||
getPricedMobileFeePart,
|
|
||||||
getServiceabilityDetails,
|
|
||||||
getZipCodeData,
|
|
||||||
getMobileZipCodeData
|
|
||||||
} from '@/helpers/service-location-helper';
|
|
||||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
|
||||||
import { getAvailabilityRating } from '@/helpers/service-location-helper';
|
|
||||||
|
|
||||||
// Import Component
|
|
||||||
import alert from '@/ux-components/alert/alert.vue';
|
|
||||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
|
||||||
import appointmentTypeQuestion from '@/layouts/service-location/appointment-type-question/appointment-type-question.vue';
|
|
||||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
|
||||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
|
||||||
import { Form, defineRule } from 'vee-validate';
|
|
||||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
|
||||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
|
||||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
|
||||||
import shopAddress from '@/layouts/service-location/shop-address/shop-address.vue';
|
|
||||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
|
||||||
import widgetFields from '@/constants/cms-widget-fields';
|
|
||||||
|
|
||||||
const RECAL_MODAL_REF_NAME = 'RecalModal';
|
|
||||||
const SITE_FOOTER_REF_NAME = 'siteFooter';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'service-location',
|
|
||||||
components: {
|
|
||||||
alert,
|
|
||||||
textBlock,
|
|
||||||
appointmentTypeQuestion,
|
|
||||||
contentGroupModal,
|
|
||||||
siteFooter,
|
|
||||||
siteHeader,
|
|
||||||
siteSubHeader,
|
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
|
||||||
Form,
|
|
||||||
shopAddress,
|
|
||||||
serviceZipQuestion
|
|
||||||
},
|
|
||||||
mixins: [baseFormMixin],
|
|
||||||
async beforeRouteEnter(to, from, next) {
|
|
||||||
// Call APIs
|
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
|
||||||
const serviceZipCode = useMainStore().order.serviceLocation.zipCode || useMainStore().order.customer.address.zipCode;
|
|
||||||
const zipCodeData = getZipCodeData(serviceZipCode);
|
|
||||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
|
||||||
const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
|
|
||||||
const getGlassFeesPromise = useMainStore().getGlassFees();
|
|
||||||
const providersPromise = useMainStore().getProviders(serviceZipCode);
|
|
||||||
|
|
||||||
// Settle promises and get results
|
|
||||||
const promiseResultMap = [
|
|
||||||
{
|
|
||||||
resultKey: 'cmsContent',
|
|
||||||
promise: cmsContentPromise
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: 'mobileFeePart',
|
|
||||||
promise: mobileFeePartPromise
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: 'glassFees',
|
|
||||||
promise: getGlassFeesPromise
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: 'serviceabilityDetails',
|
|
||||||
promise: serviceabilityDetailsPromise
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: 'zipCodeData',
|
|
||||||
promise: zipCodeData
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: 'providers',
|
|
||||||
promise: providersPromise
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
|
||||||
useMainStore().updateIsSafeliteProvider(true);
|
|
||||||
next(async (vm) => {
|
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
|
||||||
await vm.setData(
|
|
||||||
resultMap.zipCodeData,
|
|
||||||
resultMap.serviceabilityDetails,
|
|
||||||
resultMap.mobileFeePart,
|
|
||||||
resultMap.glassFees,
|
|
||||||
resultMap.providers
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const mainStore = useMainStore();
|
|
||||||
return { mainStore };
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
streetAddress: this.getServiceAddressFromStore(),
|
|
||||||
streetAddress2: this.getServiceAddress2FromStore(),
|
|
||||||
city: this.getServiceCityFromStore(),
|
|
||||||
state: this.getServiceStateFromStore(),
|
|
||||||
zipCode: this.getServiceZipCodeFromStore(),
|
|
||||||
isGlassServiceableInshop: null,
|
|
||||||
isRecalibrationServiceableInshop: null,
|
|
||||||
isGlassServiceableMobile: null,
|
|
||||||
isRecalibrationServiceableMobile: null,
|
|
||||||
selectedAppointmentType: this.getSelectedAppointmentType(),
|
|
||||||
selectedProvider: this.getSelectedProvider(),
|
|
||||||
mobileFeePart: null,
|
|
||||||
mobileProviderNumber: null,
|
|
||||||
zipContainsMilitaryBase: false,
|
|
||||||
zipCodeCtu: null,
|
|
||||||
mobileZipCode: '',
|
|
||||||
mobileZipError: '',
|
|
||||||
militaryBaseWarningExpanded: false,
|
|
||||||
availabilityRating: null,
|
|
||||||
RECAL_MODAL_REF_NAME,
|
|
||||||
SITE_FOOTER_REF_NAME,
|
|
||||||
errorMessages
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
questionText() {
|
|
||||||
return this.getCmsContent(
|
|
||||||
'ServiceTypeQuestionWidget',
|
|
||||||
'QuestionText'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
answersFromCms() {
|
|
||||||
return this.getCmsContent('ServiceTypeQuestionWidget', 'Answers');
|
|
||||||
},
|
|
||||||
isServiceableMobile() {
|
|
||||||
if (this.isRecalibrationServiceableMobile !== null) {
|
|
||||||
return (
|
|
||||||
this.isGlassServiceableMobile
|
|
||||||
&& this.isRecalibrationServiceableMobile
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return this.isGlassServiceableMobile;
|
|
||||||
},
|
|
||||||
isServiceableInshop() {
|
|
||||||
if (this.isRecalibrationServiceableInshop !== null) {
|
|
||||||
return (
|
|
||||||
this.isGlassServiceableInshop
|
|
||||||
&& this.isRecalibrationServiceableInshop
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.isGlassServiceableInshop;
|
|
||||||
},
|
|
||||||
isInshop() {
|
|
||||||
return (
|
|
||||||
this.selectedAppointmentType === 'Inshop'
|
|
||||||
|| this.selectedAppointmentType === 'Dropoff'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
isMobile() {
|
|
||||||
return this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
|
||||||
},
|
|
||||||
requiresInshopRecalibration() {
|
|
||||||
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
|
||||||
return (
|
|
||||||
this.isServiceableInshop
|
|
||||||
&& this.isGlassServiceableMobile
|
|
||||||
&& this.isRecalibrationServiceableMobile === false
|
|
||||||
);
|
|
||||||
},
|
|
||||||
displayMilitaryZipAlert() {
|
|
||||||
return this.zipContainsMilitaryBase && this.isServiceableMobile;
|
|
||||||
},
|
|
||||||
displayNoShopsAlert() {
|
|
||||||
return !this.isBigTruck && !this.isServiceableInshop && !this.isServiceableMobile;
|
|
||||||
},
|
|
||||||
displayBigTruckNoShops() {
|
|
||||||
return this.isBigTruck && !this.isServiceableInshop && !this.isServiceableMobile;
|
|
||||||
},
|
|
||||||
displayRecalibrationWarning() {
|
|
||||||
return this.requiresInshopRecalibration;
|
|
||||||
},
|
|
||||||
displayLowAvailabilityInshop() {
|
|
||||||
return this.availabilityRating === 'low' && this.isInshop;
|
|
||||||
},
|
|
||||||
displayServiceableInshopOnly() {
|
|
||||||
return !this.isServiceableMobile && this.isServiceableInshop && !this.displayRecalibrationWarning;
|
|
||||||
},
|
|
||||||
displayServiceableMobileOnly() {
|
|
||||||
return this.isServiceableMobile && this.recalibrationRequired && !this.isServiceableInshop;
|
|
||||||
},
|
|
||||||
displayMobileFeeDisclaimer() {
|
|
||||||
return this.mainStore.isNoComp || this.mainStore.isITAC;
|
|
||||||
},
|
|
||||||
navigateBackScenario() {
|
|
||||||
const { isNoComp, isITAC } = useMainStore();
|
|
||||||
return isNoComp || isITAC
|
|
||||||
? this.navigationScenarios.CLICKED_BACK_CANNOT_REACH_TPA_FLOW
|
|
||||||
: this.navigationScenarios.CLICKED_BACK_CAN_REACH_TPA_FLOW;
|
|
||||||
},
|
|
||||||
isBigTruck() {
|
|
||||||
return this.mainStore.order.vehicle.isBigTruck;
|
|
||||||
},
|
|
||||||
mobileZipPlaceholder() {
|
|
||||||
return this.getCmsContent('MobileZipPlaceHolderWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
|
||||||
},
|
|
||||||
militaryBaseWarningLinkText() {
|
|
||||||
return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.HEADLINE_TEXT);
|
|
||||||
},
|
|
||||||
militaryBaseWarningText() {
|
|
||||||
return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
|
||||||
},
|
|
||||||
appointmentQuestionText() {
|
|
||||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
|
|
||||||
},
|
|
||||||
scheduleRecalText() {
|
|
||||||
if(this.requiresInshopRecalibration) {
|
|
||||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
|
|
||||||
} else {
|
|
||||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
inShopOnlyCopy() {
|
|
||||||
let content = this.getCmsContent('AlertInshopOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
|
||||||
content = content.replace('{custom:city}', toTitleCase(this.city));
|
|
||||||
return content;
|
|
||||||
},
|
|
||||||
mobileOnlyCopy() {
|
|
||||||
let content = this.getCmsContent('AlertMobileOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
|
||||||
content = content.replace('{custom:city}', toTitleCase(this.city));
|
|
||||||
return content;
|
|
||||||
},
|
|
||||||
recalibrationRequired() {
|
|
||||||
return this.mainStore.hasRecalibrationPart;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
arePagePrerequisitesValid() {
|
|
||||||
return (
|
|
||||||
useMainStore().order.serviceLocation.zipCode !== null
|
|
||||||
);
|
|
||||||
},
|
|
||||||
async forwardButtonAction() {
|
|
||||||
let provider = this.selectedProvider;
|
|
||||||
this.mainStore.updateMobileFee(null);
|
|
||||||
if (this.isMobile) {
|
|
||||||
if (this.mainStore.isNoComp || this.mainStore.isITAC) {
|
|
||||||
this.mainStore.updateMobileFee(this.mobileFeePart);
|
|
||||||
}
|
|
||||||
|
|
||||||
provider = {
|
|
||||||
providerNumber: this.mobileProviderNumber,
|
|
||||||
address: {
|
|
||||||
streetAddress: null,
|
|
||||||
city: null,
|
|
||||||
state: null,
|
|
||||||
zipCode: null,
|
|
||||||
zipCodeCtu: null
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mainStore.saveServiceLocation({
|
|
||||||
address: this.streetAddress,
|
|
||||||
address2: this.streetAddress2,
|
|
||||||
city: this.city,
|
|
||||||
state: this.state,
|
|
||||||
zipCode: this.zipCode,
|
|
||||||
zipCodeCtu: this.zipCodeCtu,
|
|
||||||
appointmentType: this.selectedAppointmentType,
|
|
||||||
provider
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$router.navigate(
|
|
||||||
this.navigationScenarios.CLICKED_FORWARD,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
},
|
|
||||||
openModalAction(modalName) {
|
|
||||||
this.$refs[modalName].openModal();
|
|
||||||
},
|
|
||||||
resetDependentState() {},
|
|
||||||
getServiceAddressFromStore() {
|
|
||||||
return useMainStore().order.serviceLocation.address;
|
|
||||||
},
|
|
||||||
getServiceAddress2FromStore() {
|
|
||||||
return useMainStore().order.serviceLocation.address2;
|
|
||||||
},
|
|
||||||
getServiceCityFromStore() {
|
|
||||||
return useMainStore().order.serviceLocation.city;
|
|
||||||
},
|
|
||||||
getServiceStateFromStore() {
|
|
||||||
return (
|
|
||||||
useMainStore().order.serviceLocation.state
|
|
||||||
|| useMainStore().order.customer.address.state
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getServiceZipCodeFromStore() {
|
|
||||||
return (
|
|
||||||
useMainStore().order.serviceLocation.zipCode
|
|
||||||
|| useMainStore().order.customer.address.zipCode
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getSelectedAppointmentType() {
|
|
||||||
return useMainStore().order.serviceLocation.appointmentType;
|
|
||||||
},
|
|
||||||
getSelectedProvider() {
|
|
||||||
return useMainStore().order.serviceLocation.provider;
|
|
||||||
},
|
|
||||||
setCtuForMobile(val) {
|
|
||||||
this.zipCodeCtu = val;
|
|
||||||
},
|
|
||||||
async setData(
|
|
||||||
zipCodeData,
|
|
||||||
serviceabilityDetails,
|
|
||||||
mobileFeePart,
|
|
||||||
glassFees,
|
|
||||||
providers
|
|
||||||
) {
|
|
||||||
if (zipCodeData) {
|
|
||||||
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
|
|
||||||
this.zipCodeCtu = zipCodeData.zipCodeCtu;
|
|
||||||
this.city = zipCodeData.city;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serviceabilityDetails) {
|
|
||||||
this.setServiceabilityDetails(serviceabilityDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mobileFeePart) {
|
|
||||||
this.mobileFeePart = mobileFeePart;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (providers) {
|
|
||||||
this.setMobileProviderNumber(providers.mobileProviderNumber);
|
|
||||||
let foundMatch = false;
|
|
||||||
if(this.selectedProvider && this.selectedProvider.providerNumber) {
|
|
||||||
const matchedProvider = providers.shopProviders.find(
|
|
||||||
(provider) => provider.providerNumber === this.selectedProvider.providerNumber
|
|
||||||
);
|
|
||||||
if (matchedProvider) {
|
|
||||||
foundMatch = true;
|
|
||||||
this.selectedProvider = matchedProvider;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(providers.shopProviders.length > 0 && !foundMatch) {
|
|
||||||
this.selectedProvider = providers.shopProviders[0];
|
|
||||||
}
|
|
||||||
else if(providers.shopProviders.length === 0) {
|
|
||||||
this.selectedProvider = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glassFees) {
|
|
||||||
const pricedGlassFees = await useMainStore().getCombinedQuote(glassFees);
|
|
||||||
this.setGlassFeeItems(pricedGlassFees);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setContainsMilitaryBase(val) {
|
|
||||||
if (this.zipContainsMilitaryBase !== val) {
|
|
||||||
this.zipContainsMilitaryBase = val;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setGlassFeeItems(newGlassFeeItems) {
|
|
||||||
this.mainStore.updateGlassFees(newGlassFeeItems);
|
|
||||||
},
|
|
||||||
setMobileFeePart(mobileFeePart) {
|
|
||||||
this.mobileFeePart = mobileFeePart;
|
|
||||||
},
|
|
||||||
setMobileProviderNumber(providerNumber) {
|
|
||||||
this.mobileProviderNumber = providerNumber;
|
|
||||||
},
|
|
||||||
setServiceabilityDetails(serviceabilityDetails) {
|
|
||||||
this.isGlassServiceableInshop =
|
|
||||||
serviceabilityDetails.isGlassServiceableInshop;
|
|
||||||
this.isRecalibrationServiceableInshop =
|
|
||||||
serviceabilityDetails.isRecalibrationServiceableInshop;
|
|
||||||
this.isGlassServiceableMobile =
|
|
||||||
serviceabilityDetails.isGlassServiceableMobile;
|
|
||||||
this.isRecalibrationServiceableMobile =
|
|
||||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
|
||||||
if (!this.isServiceableMobile) {
|
|
||||||
this.selectedAppointmentType = AppointmentTypeStrings.IN_SHOP;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async updateMobileZip() {
|
|
||||||
this.mobileZipError = '';
|
|
||||||
|
|
||||||
const zipCodeData = await getMobileZipCodeData(this.mobileZipCode);
|
|
||||||
|
|
||||||
if (!zipCodeData.isValid) {
|
|
||||||
this.mobileZipError = errorMessages.INVALID_ZIP;
|
|
||||||
} else if (!zipCodeData.isServiceable) {
|
|
||||||
this.mobileZipError = errorMessages.NO_SERVICE_IN_AREA(toTitleCase(zipCodeData.city));
|
|
||||||
} else {
|
|
||||||
this.city = zipCodeData.city;
|
|
||||||
this.zipCode = this.mobileZipCode;
|
|
||||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
|
||||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
|
||||||
|
|
||||||
const serviceabilityDetailsPromise = getServiceabilityDetails(this.mobileZipCode);
|
|
||||||
serviceabilityDetailsPromise.then((result) => {
|
|
||||||
const details = result.data;
|
|
||||||
if (details) {
|
|
||||||
this.setServiceabilityDetails(details);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const providersPromise = useMainStore().getProviders(this.mobileZipCode);
|
|
||||||
providersPromise.then((result) => {
|
|
||||||
const providers = result.data;
|
|
||||||
if (providers) {
|
|
||||||
this.setMobileProviderNumber(providers.mobileProviderNumber);
|
|
||||||
if(providers.shopProviders.length > 0) {
|
|
||||||
this.selectedProvider = providers.shopProviders[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.selectedProvider = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async handleInShopZipUpdated(newZip) {
|
|
||||||
this.zipCode = newZip;
|
|
||||||
const zipCodeData = await getZipCodeData(this.zipCode);
|
|
||||||
this.city = zipCodeData.city;
|
|
||||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
|
||||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
|
||||||
|
|
||||||
const serviceabilityDetailsPromise = getServiceabilityDetails(this.zipCode);
|
|
||||||
serviceabilityDetailsPromise.then((result) => {
|
|
||||||
const details = result.data;
|
|
||||||
if (details) {
|
|
||||||
this.setServiceabilityDetails(details);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
mobileZipCode(newZip) {
|
|
||||||
if(newZip !== '') {
|
|
||||||
this.updateMobileZip();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectedAppointmentType() {
|
|
||||||
this.mobileZipCode = '';
|
|
||||||
if(this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP && this.selectedProvider) {
|
|
||||||
const startDate = new Date();
|
|
||||||
const endDate = new Date();
|
|
||||||
endDate.setDate(startDate.getDate() + 6);
|
|
||||||
const formattedStartDate = startDate.toISOString().split('T')[0];
|
|
||||||
const formattedEndDate = endDate.toISOString().split('T')[0];
|
|
||||||
getAvailabilityRating(
|
|
||||||
formattedStartDate,
|
|
||||||
formattedEndDate,
|
|
||||||
AppointmentTypeStrings.IN_SHOP,
|
|
||||||
this.selectedProvider ? this.selectedProvider.providerNumber : null
|
|
||||||
).then((rating) => {
|
|
||||||
this.availabilityRating = rating;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
$page-side-padding: 1.5rem;
|
|
||||||
.iss-heritage-container-width {
|
|
||||||
.service-location-container {
|
|
||||||
position: relative;
|
|
||||||
min-height: 1px;
|
|
||||||
padding-left: .9375rem;
|
|
||||||
padding-right: .9375rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-location-container {
|
|
||||||
.subheader {
|
|
||||||
margin: 1.25rem 0;
|
|
||||||
}
|
|
||||||
.form-test-error {
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
}
|
|
||||||
.appointment-type-question-text {
|
|
||||||
color: $black;
|
|
||||||
font-weight: 600;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
line-height: 1.625rem;
|
|
||||||
flex-direction: column;
|
|
||||||
.recal-text {
|
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.mobile-service-zip-question {
|
|
||||||
:deep(.form-test-error span) {
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.expandable-link-container {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
.expandable-link {
|
|
||||||
font-style: italic;
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
text-decoration: none;
|
|
||||||
color: $heritage-blue-primary;
|
|
||||||
line-height: 1.375rem;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -386,7 +386,7 @@ describe('tpa-submit', () => {
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
provider: {
|
provider: {
|
||||||
companyName: providerCompanyName
|
companyName: providerCompanyName
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
contactInfo: {
|
contactInfo: {
|
||||||
firstName,
|
firstName,
|
||||||
|
|
@ -431,7 +431,7 @@ describe('tpa-submit', () => {
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
provider: {
|
provider: {
|
||||||
companyName: providerCompanyName
|
companyName: providerCompanyName
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
contactInfo: {
|
contactInfo: {
|
||||||
firstName,
|
firstName,
|
||||||
|
|
@ -520,7 +520,9 @@ describe('tpa-submit', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const initialStore = {
|
const initialStore = {
|
||||||
order: {
|
order: {
|
||||||
currentDeductible: storeValue
|
currentDeductible: {
|
||||||
|
replace: storeValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const { wrapper } = getMountedComponent(initialStore);
|
const { wrapper } = getMountedComponent(initialStore);
|
||||||
|
|
@ -568,7 +570,10 @@ describe('tpa-submit', () => {
|
||||||
insuranceCoverage: {
|
insuranceCoverage: {
|
||||||
coverageStatus: status
|
coverageStatus: status
|
||||||
},
|
},
|
||||||
currentDeductible: deductible
|
currentDeductible: {
|
||||||
|
replace: deductible,
|
||||||
|
repair: deductible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const { wrapper } = getMountedComponent(initialStore);
|
const { wrapper } = getMountedComponent(initialStore);
|
||||||
|
|
@ -596,7 +601,10 @@ describe('tpa-submit', () => {
|
||||||
insuranceCoverage: {
|
insuranceCoverage: {
|
||||||
coverageStatus: status
|
coverageStatus: status
|
||||||
},
|
},
|
||||||
currentDeductible: deductible
|
currentDeductible: {
|
||||||
|
replace: deductible,
|
||||||
|
repair: deductible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const { wrapper } = getMountedComponent(initialStore);
|
const { wrapper } = getMountedComponent(initialStore);
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,11 @@
|
||||||
<alert
|
<alert
|
||||||
ref="alertIncomplete"
|
ref="alertIncomplete"
|
||||||
alertClass="alert-warning"
|
alertClass="alert-warning"
|
||||||
:cmsWidgetName="widget.alertIncomplete"
|
:cmsWidgetName="widget.alertIncomplete" />
|
||||||
/>
|
|
||||||
<textBlock
|
<textBlock
|
||||||
ref="subHeaderTitle"
|
ref="subHeaderTitle"
|
||||||
:customText="subHeaderTitle"
|
:customText="subHeaderTitle"
|
||||||
class="tpa-submit-title"/>
|
class="tpa-submit-title" />
|
||||||
<textBlock
|
<textBlock
|
||||||
id="tpaSubmitSubHeaderBodyOne"
|
id="tpaSubmitSubHeaderBodyOne"
|
||||||
ref="tpaSubmitSubHeaderBodyOne"
|
ref="tpaSubmitSubHeaderBodyOne"
|
||||||
|
|
@ -40,9 +39,15 @@
|
||||||
:headerText="recalModalContent.headerText"
|
:headerText="recalModalContent.headerText"
|
||||||
:footerButtonText="recalModalContent.footerButtonText"
|
:footerButtonText="recalModalContent.footerButtonText"
|
||||||
@footerButtonEvent="closeRecalModal">
|
@footerButtonEvent="closeRecalModal">
|
||||||
<div class="recal-modal-subheader">{{ recalModalContent.subHeaderText }}</div>
|
<div class="recal-modal-subheader">
|
||||||
<img class="recal-modal-image" :src="recalModalContent.image" />
|
{{ recalModalContent.subHeaderText }}
|
||||||
<div class="recal-modal-body" v-html="recalModalContent.bodyText"></div>
|
</div>
|
||||||
|
<img
|
||||||
|
class="recal-modal-image"
|
||||||
|
:src="recalModalContent.image" />
|
||||||
|
<div
|
||||||
|
class="recal-modal-body"
|
||||||
|
v-html="recalModalContent.bodyText"></div>
|
||||||
</modal>
|
</modal>
|
||||||
<hr />
|
<hr />
|
||||||
<div id="serviceSummarySection">
|
<div id="serviceSummarySection">
|
||||||
|
|
@ -155,7 +160,7 @@ export default {
|
||||||
alertIncomplete: 'AlertIncompleteWidget',
|
alertIncomplete: 'AlertIncompleteWidget',
|
||||||
alertRecalWarning: 'AlertRecalWarningWidget',
|
alertRecalWarning: 'AlertRecalWarningWidget',
|
||||||
editShopLinkText: 'EditShopLinkTextWidget',
|
editShopLinkText: 'EditShopLinkTextWidget',
|
||||||
contactDetails: 'ContactDetailsSectionWidget'
|
contactDetails: 'ContactDetailsSectionWidget'
|
||||||
},
|
},
|
||||||
modalPositions
|
modalPositions
|
||||||
};
|
};
|
||||||
|
|
@ -207,7 +212,7 @@ export default {
|
||||||
return this.mainStore.isVerified;
|
return this.mainStore.isVerified;
|
||||||
},
|
},
|
||||||
currentDeductible() {
|
currentDeductible() {
|
||||||
return this.mainStore.order.currentDeductible;
|
return this.mainStore.currentDeductible;
|
||||||
},
|
},
|
||||||
deductibleBoxValue() {
|
deductibleBoxValue() {
|
||||||
return this.isVerified
|
return this.isVerified
|
||||||
|
|
@ -269,7 +274,7 @@ export default {
|
||||||
bodyText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT),
|
bodyText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT),
|
||||||
footerButtonText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.FOOTER_TEXT),
|
footerButtonText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.FOOTER_TEXT),
|
||||||
image: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.IMAGE)
|
image: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.IMAGE)
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
recalibrationRequired() {
|
recalibrationRequired() {
|
||||||
return this.mainStore.hasRecalibrationPart;
|
return this.mainStore.hasRecalibrationPart;
|
||||||
|
|
@ -281,9 +286,9 @@ export default {
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
glassShop: this.getPreferredShopTitle,
|
glassShop: this.getPreferredShopTitle,
|
||||||
contactPhone: contactPhone,
|
contactPhone,
|
||||||
contactEmail: this.mainStore.contactInfo.emailAddress ?? ''
|
contactEmail: this.mainStore.contactInfo.emailAddress ?? ''
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -293,7 +298,7 @@ export default {
|
||||||
this.getPreferredShopTitle,
|
this.getPreferredShopTitle,
|
||||||
this.getPreferredShopLines,
|
this.getPreferredShopLines,
|
||||||
this.getEditShopLinkText,
|
this.getEditShopLinkText,
|
||||||
() => this.navigate(this.navigationScenarios.EDIT_PREFERRED_SHOP),
|
() => this.navigate(this.navigationScenarios.EDIT_PREFERRED_SHOP)
|
||||||
),
|
),
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
this.getSection(
|
this.getSection(
|
||||||
|
|
@ -306,7 +311,7 @@ export default {
|
||||||
},
|
},
|
||||||
getSection(title, lines, editLinkText, onClick) {
|
getSection(title, lines, editLinkText, onClick) {
|
||||||
return {
|
return {
|
||||||
title: title,
|
title,
|
||||||
lines,
|
lines,
|
||||||
editLinkText,
|
editLinkText,
|
||||||
onClickEdit: onClick
|
onClickEdit: onClick
|
||||||
|
|
|
||||||
|
|
@ -354,7 +354,7 @@ describe('vehicle-questions-mixin', () => {
|
||||||
const testCases = [
|
const testCases = [
|
||||||
[issPageValues.PART_QUESTIONS, issPageValues.VEHICLE_PARTS, false],
|
[issPageValues.PART_QUESTIONS, issPageValues.VEHICLE_PARTS, false],
|
||||||
[issPageValues.VEHICLE_PARTS, issPageValues.VEHICLE_PARTS, false],
|
[issPageValues.VEHICLE_PARTS, issPageValues.VEHICLE_PARTS, false],
|
||||||
[issPageValues.VEHICLE_PARTS, issPageValues.SERVICE_LOCATION, true],
|
[issPageValues.VEHICLE_PARTS, issPageValues.SCHEDULE_PAGE, true],
|
||||||
[issPageValues.VEHICLE_PARTS, issPageValues.PART_QUESTIONS, true],
|
[issPageValues.VEHICLE_PARTS, issPageValues.PART_QUESTIONS, true],
|
||||||
[issPageValues.PART_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, false],
|
[issPageValues.PART_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, false],
|
||||||
[issPageValues.MOLDING_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, false]
|
[issPageValues.MOLDING_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, false]
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ const issPageValues = Object.freeze({
|
||||||
POLICY_HOLDER_DETAILS: 'policy-holder-details',
|
POLICY_HOLDER_DETAILS: 'policy-holder-details',
|
||||||
PROVIDER_PREFERENCE: 'provider-preference',
|
PROVIDER_PREFERENCE: 'provider-preference',
|
||||||
REVEAL: 'reveal',
|
REVEAL: 'reveal',
|
||||||
SERVICE_LOCATION: 'service-location',
|
|
||||||
TPA_CONFIRMATION: 'tpa-confirmation',
|
TPA_CONFIRMATION: 'tpa-confirmation',
|
||||||
SERVICE_PACKAGES: 'service-packages',
|
SERVICE_PACKAGES: 'service-packages',
|
||||||
SCHEDULE_PAGE: 'schedule-page',
|
SCHEDULE_PAGE: 'schedule-page',
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,8 @@ const navigationScenarios = Object.freeze({
|
||||||
CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS: 'CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS',
|
CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS: 'CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS',
|
||||||
|
|
||||||
// Schedule
|
// Schedule
|
||||||
CLICKED_CHANGE_LOCATION: 'CLICKED_CHANGE_LOCATION',
|
CLICKED_BACK_CANNOT_REACH_TPA_FLOW: 'CLICKED_BACK_CANNOT_REACH_TPA_FLOW',
|
||||||
|
CLICKED_BACK_CAN_REACH_TPA_FLOW: 'CLICKED_BACK_CAN_REACH_TPA_FLOW',
|
||||||
|
|
||||||
// Coverage Statement
|
// Coverage Statement
|
||||||
CLICKED_BACK_WITH_REPAIR: 'CLICKED_BACK_WITH_REPAIR',
|
CLICKED_BACK_WITH_REPAIR: 'CLICKED_BACK_WITH_REPAIR',
|
||||||
|
|
@ -83,10 +84,6 @@ const navigationScenarios = Object.freeze({
|
||||||
EDIT_PREFERRED_SHOP: 'EDIT_PREFERRED_SHOP',
|
EDIT_PREFERRED_SHOP: 'EDIT_PREFERRED_SHOP',
|
||||||
EDIT_CONTACT_DETAILS: 'EDIT_CONTACT_DETAILS',
|
EDIT_CONTACT_DETAILS: 'EDIT_CONTACT_DETAILS',
|
||||||
|
|
||||||
// Service location
|
|
||||||
CLICKED_BACK_CANNOT_REACH_TPA_FLOW: 'CLICKED_BACK_CANNOT_REACH_TPA_FLOW',
|
|
||||||
CLICKED_BACK_CAN_REACH_TPA_FLOW: 'CLICKED_BACK_CAN_REACH_TPA_FLOW',
|
|
||||||
|
|
||||||
// Provider Preference
|
// Provider Preference
|
||||||
CLICKED_FORWARD_WITH_SAFELITE: 'CLICKED_FORWARD_WITH_SAFELITE',
|
CLICKED_FORWARD_WITH_SAFELITE: 'CLICKED_FORWARD_WITH_SAFELITE',
|
||||||
CLICKED_FORWARD_WITH_TPA_ENABLED: 'CLICKED_FORWARD_WITH_TPA_ENABLED',
|
CLICKED_FORWARD_WITH_TPA_ENABLED: 'CLICKED_FORWARD_WITH_TPA_ENABLED',
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,7 @@ const routingTable = () => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
|
||||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
destinationIssPageValue: issPageValues.SCHEDULE_PAGE
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
|
||||||
|
|
@ -559,7 +559,7 @@ const routingTable = () => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
|
||||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
destinationIssPageValue: issPageValues.SCHEDULE_PAGE
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED,
|
||||||
|
|
@ -572,7 +572,7 @@ const routingTable = () => [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
issPageValue: issPageValues.SERVICE_LOCATION,
|
issPageValue: issPageValues.SCHEDULE_PAGE,
|
||||||
maps: [
|
maps: [
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_BACK_CANNOT_REACH_TPA_FLOW,
|
scenario: navigationScenarios.CLICKED_BACK_CANNOT_REACH_TPA_FLOW,
|
||||||
|
|
@ -582,26 +582,9 @@ const routingTable = () => [
|
||||||
scenario: navigationScenarios.CLICKED_BACK_CAN_REACH_TPA_FLOW,
|
scenario: navigationScenarios.CLICKED_BACK_CAN_REACH_TPA_FLOW,
|
||||||
destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE
|
destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE
|
||||||
},
|
},
|
||||||
{
|
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
|
||||||
destinationIssPageValue: issPageValues.SCHEDULE_PAGE
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
issPageValue: issPageValues.SCHEDULE_PAGE,
|
|
||||||
maps: [
|
|
||||||
{
|
|
||||||
scenario: navigationScenarios.CLICKED_BACK,
|
|
||||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||||
destinationIssPageValue: issPageValues.CONTACT_DETAILS
|
destinationIssPageValue: issPageValues.CONTACT_DETAILS
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: navigationScenarios.CLICKED_CHANGE_LOCATION,
|
|
||||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -750,7 +733,7 @@ const routingTable = () => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP,
|
||||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
destinationIssPageValue: issPageValues.SCHEDULE_PAGE
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
|
||||||
|
|
|
||||||
|
|
@ -220,8 +220,16 @@ export const getDefaultState = () => ({
|
||||||
settledTenderAmount: null,
|
settledTenderAmount: null,
|
||||||
lockToken: null,
|
lockToken: null,
|
||||||
customerPortalLoginToken: null,
|
customerPortalLoginToken: null,
|
||||||
originalDeductible: null,
|
originalDeductible: {
|
||||||
currentDeductible: null,
|
repair: null,
|
||||||
|
replace: null
|
||||||
|
},
|
||||||
|
currentDeductible: {
|
||||||
|
repair: null,
|
||||||
|
replace: null
|
||||||
|
},
|
||||||
|
totalTaxAmount: null,
|
||||||
|
waiverReasons: null,
|
||||||
carrierPhoneNumber: null,
|
carrierPhoneNumber: null,
|
||||||
loadedFromCookie: false,
|
loadedFromCookie: false,
|
||||||
loadedFromDupeCheck: null,
|
loadedFromDupeCheck: null,
|
||||||
|
|
@ -439,7 +447,9 @@ export const useMainStore = defineStore({
|
||||||
experimentSettings: (state) => state.applicationUser.experiments
|
experimentSettings: (state) => state.applicationUser.experiments
|
||||||
.filter((x) => !!x.isActive)
|
.filter((x) => !!x.isActive)
|
||||||
.map((x) => x.settings)
|
.map((x) => x.settings)
|
||||||
.reduce((r, c) => Object.assign(r, c), {}) ?? {}
|
.reduce((r, c) => Object.assign(r, c), {}) ?? {},
|
||||||
|
originalDeductible: (state) => (state.order.damage.isRepair ? state.order.originalDeductible.repair : state.order.originalDeductible.replace),
|
||||||
|
currentDeductible: (state) => (state.order.damage.isRepair ? state.order.currentDeductible.repair : state.order.currentDeductible.replace)
|
||||||
},
|
},
|
||||||
actions:
|
actions:
|
||||||
{
|
{
|
||||||
|
|
@ -653,7 +663,7 @@ export const useMainStore = defineStore({
|
||||||
safelitePolicy: {
|
safelitePolicy: {
|
||||||
policies: []
|
policies: []
|
||||||
},
|
},
|
||||||
actualDeductible: this.order.currentDeductible?.toString() ?? ''
|
actualDeductible: this.currentDeductible.toString() ?? ''
|
||||||
},
|
},
|
||||||
lossInfo: {
|
lossInfo: {
|
||||||
dateOfLoss: this.order.policy.dateOfLoss,
|
dateOfLoss: this.order.policy.dateOfLoss,
|
||||||
|
|
@ -716,8 +726,8 @@ export const useMainStore = defineStore({
|
||||||
manualGlassNames: manualGlassNamesArray,
|
manualGlassNames: manualGlassNamesArray,
|
||||||
policyState: this.order.customer.address.state,
|
policyState: this.order.customer.address.state,
|
||||||
status: this.order.policy.status,
|
status: this.order.policy.status,
|
||||||
originalDeductible: this.order.originalDeductible,
|
originalDeductible: this.originalDeductible,
|
||||||
currentDeductible: this.order.currentDeductible,
|
currentDeductible: this.currentDeductible,
|
||||||
noCoverage: false,
|
noCoverage: false,
|
||||||
isRepair: this.order.damage.isRepair,
|
isRepair: this.order.damage.isRepair,
|
||||||
policyNumber: this.order.policy.policyNumber,
|
policyNumber: this.order.policy.policyNumber,
|
||||||
|
|
@ -731,7 +741,7 @@ export const useMainStore = defineStore({
|
||||||
}
|
}
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
this.order.policy.policyData = r.data.policyData;
|
this.order.policy.policyData = r.data.policyData;
|
||||||
this.updateDeductible(r.data.deductible);
|
this.updateDeductible(r.data);
|
||||||
return resolve(r);
|
return resolve(r);
|
||||||
}).catch((error) => reject(error));
|
}).catch((error) => reject(error));
|
||||||
});
|
});
|
||||||
|
|
@ -875,7 +885,7 @@ export const useMainStore = defineStore({
|
||||||
logApiCall: true
|
logApiCall: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getMobileTimeSlots(startDate, endDate) {
|
getMobileTimeSlots(startDate, endDate, zipCodeOverride = null) {
|
||||||
const { order } = this;
|
const { order } = this;
|
||||||
const { vehicle } = this.order;
|
const { vehicle } = this.order;
|
||||||
let lineItems = [
|
let lineItems = [
|
||||||
|
|
@ -921,8 +931,9 @@ export const useMainStore = defineStore({
|
||||||
style: vehicle.style,
|
style: vehicle.style,
|
||||||
vin: vehicle.vin ?? ''
|
vin: vehicle.vin ?? ''
|
||||||
},
|
},
|
||||||
zipCode: order.serviceLocation.zipCode
|
zipCode: zipCodeOverride ?? order.serviceLocation.zipCode
|
||||||
};
|
};
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetMobileTimeSlots.method,
|
method: endpoints.GetMobileTimeSlots.method,
|
||||||
endpoint: endpoints.GetMobileTimeSlots.url,
|
endpoint: endpoints.GetMobileTimeSlots.url,
|
||||||
|
|
@ -931,7 +942,7 @@ export const useMainStore = defineStore({
|
||||||
additionalSuccessEventDataHandler: (response) =>
|
additionalSuccessEventDataHandler: (response) =>
|
||||||
getTimeSlotsAdditionalEventData(
|
getTimeSlotsAdditionalEventData(
|
||||||
response.data.provisionalTriggers,
|
response.data.provisionalTriggers,
|
||||||
order.serviceLocation.zipCode,
|
zipCodeOverride ?? order.serviceLocation.zipCode,
|
||||||
response.data.days?.[0]?.date
|
response.data.days?.[0]?.date
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
@ -1197,7 +1208,7 @@ export const useMainStore = defineStore({
|
||||||
Model: vehicle.model
|
Model: vehicle.model
|
||||||
},
|
},
|
||||||
Insurance: {
|
Insurance: {
|
||||||
Deductible: this.order.currentDeductible ?? 0,
|
Deductible: this.currentDeductible ?? 0,
|
||||||
PolicyNumber: policy.policyNumber,
|
PolicyNumber: policy.policyNumber,
|
||||||
CoverageStatus: insuranceCoverage.coverageStatus,
|
CoverageStatus: insuranceCoverage.coverageStatus,
|
||||||
CoverageType: insuranceCoverage.coverageType
|
CoverageType: insuranceCoverage.coverageType
|
||||||
|
|
@ -1447,8 +1458,8 @@ export const useMainStore = defineStore({
|
||||||
},
|
},
|
||||||
policyNumber: policy.policyNumber,
|
policyNumber: policy.policyNumber,
|
||||||
policyZipCode: policy.policyZipCode,
|
policyZipCode: policy.policyZipCode,
|
||||||
originalDeductible: this.order.originalDeductible,
|
originalDeductible: this.originalDeductible,
|
||||||
currentDeductible: this.order.currentDeductible,
|
currentDeductible: this.currentDeductible,
|
||||||
OemEndorsement: this.hasOemEndorsement,
|
OemEndorsement: this.hasOemEndorsement,
|
||||||
noCoverage: this.isNoComp,
|
noCoverage: this.isNoComp,
|
||||||
isItac: this.isITAC
|
isItac: this.isITAC
|
||||||
|
|
@ -2030,9 +2041,10 @@ export const useMainStore = defineStore({
|
||||||
this.order.policy.deductible.repair = coverage?.repairWaived ?? false ? 0 : coverage.deductible;
|
this.order.policy.deductible.repair = coverage?.repairWaived ?? false ? 0 : coverage.deductible;
|
||||||
this.order.policy.endorsements = coverage?.endorsements;
|
this.order.policy.endorsements = coverage?.endorsements;
|
||||||
|
|
||||||
// TODO logic should be more complicated later on
|
this.order.originalDeductible.replace = this.order.policy.deductible.replace;
|
||||||
this.order.originalDeductible = coverage.deductible;
|
this.order.currentDeductible.replace = this.order.policy.deductible.replace;
|
||||||
this.order.currentDeductible = coverage.deductible;
|
this.order.originalDeductible.repair = this.order.policy.deductible.repair;
|
||||||
|
this.order.currentDeductible.repair = this.order.policy.deductible.repair;
|
||||||
},
|
},
|
||||||
|
|
||||||
resetOrder() {
|
resetOrder() {
|
||||||
|
|
@ -2045,8 +2057,10 @@ export const useMainStore = defineStore({
|
||||||
this.order.settledTenderAmount = null;
|
this.order.settledTenderAmount = null;
|
||||||
this.order.lockToken = null;
|
this.order.lockToken = null;
|
||||||
this.order.eon = null;
|
this.order.eon = null;
|
||||||
this.order.originalDeductible = null;
|
this.order.originalDeductible.repair = null;
|
||||||
this.order.currentDeductible = null;
|
this.order.originalDeductible.replace = null;
|
||||||
|
this.order.currentDeductible.repair = null;
|
||||||
|
this.order.currentDeductible.replace = null;
|
||||||
this.order.loadedFromDupeCheck = null;
|
this.order.loadedFromDupeCheck = null;
|
||||||
this.order.loadedSessionClearedPreviousData = null;
|
this.order.loadedSessionClearedPreviousData = null;
|
||||||
this.order.availableVaps = null;
|
this.order.availableVaps = null;
|
||||||
|
|
@ -2316,8 +2330,12 @@ export const useMainStore = defineStore({
|
||||||
updateIsSafeliteProvider(isSafelite) {
|
updateIsSafeliteProvider(isSafelite) {
|
||||||
this.order.serviceLocation.IsSafeliteProvider = isSafelite;
|
this.order.serviceLocation.IsSafeliteProvider = isSafelite;
|
||||||
},
|
},
|
||||||
updateDeductible(finalDeductible) {
|
updateDeductible(deductibleInfo) {
|
||||||
this.order.currentDeductible = finalDeductible;
|
if (this.order.damage.isRepair) {
|
||||||
|
this.order.currentDeductible.repair = deductibleInfo.deductible;
|
||||||
|
} else {
|
||||||
|
this.order.currentDeductible.replace = deductibleInfo.deductible;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
savePartQuestionAnswers(partQuestionAnswersArray) {
|
savePartQuestionAnswers(partQuestionAnswersArray) {
|
||||||
// if part question answers have changed, reset subsequent question answers
|
// if part question answers have changed, reset subsequent question answers
|
||||||
|
|
@ -2717,19 +2735,6 @@ export const useMainStore = defineStore({
|
||||||
},
|
},
|
||||||
|
|
||||||
saveServiceLocation(serviceLocationInfo) {
|
saveServiceLocation(serviceLocationInfo) {
|
||||||
if (this.order.serviceLocation) {
|
|
||||||
if (
|
|
||||||
serviceLocationInfo.zipCode !== this.order.serviceLocation.zipCode
|
|
||||||
|| !providersEqual(
|
|
||||||
serviceLocationInfo.provider,
|
|
||||||
this.order.serviceLocation.provider
|
|
||||||
)
|
|
||||||
|| serviceLocationInfo.appointmentType
|
|
||||||
!== this.order.serviceLocation.appointmentType
|
|
||||||
) {
|
|
||||||
this.resetSchedule();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.updateServiceLocation(serviceLocationInfo);
|
this.updateServiceLocation(serviceLocationInfo);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import coverageStatuses from '@/constants/coverage-statuses.js';
|
||||||
import { paymentMethods } from '@/constants/payment-method-constants';
|
import { paymentMethods } from '@/constants/payment-method-constants';
|
||||||
import endpoints from '@/constants/endpoints';
|
import endpoints from '@/constants/endpoints';
|
||||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||||
import bailoutCode from '@/constants/bailoutCode';
|
|
||||||
import coverageType from '@/constants/coverage-type';
|
import coverageType from '@/constants/coverage-type';
|
||||||
import { getEnumName } from '@/helpers/unit-test-helper';
|
import { getEnumName } from '@/helpers/unit-test-helper';
|
||||||
|
|
||||||
|
|
@ -227,6 +226,10 @@ describe('Store', () => {
|
||||||
test(`CoverageType is set to expected ${getEnumName(coverageType, expected)} when vehicle noCoverage is ${noCoverage} and enableNoCompQuote is ${enableNoCompQuote}`, () => {
|
test(`CoverageType is set to expected ${getEnumName(coverageType, expected)} when vehicle noCoverage is ${noCoverage} and enableNoCompQuote is ${enableNoCompQuote}`, () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
store.issConfig.enableNoCompQuote = enableNoCompQuote;
|
store.issConfig.enableNoCompQuote = enableNoCompQuote;
|
||||||
|
store.order.currentDeductible = {
|
||||||
|
replace: 500,
|
||||||
|
repair: 0
|
||||||
|
};
|
||||||
const vehicleCoverage = {
|
const vehicleCoverage = {
|
||||||
noCoverage
|
noCoverage
|
||||||
};
|
};
|
||||||
|
|
@ -407,6 +410,10 @@ describe('Store', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
store.order.insuranceCoverage.coverageType = coverageType.NO_COMP;
|
store.order.insuranceCoverage.coverageType = coverageType.NO_COMP;
|
||||||
|
store.order.currentDeductible = {
|
||||||
|
replace: 500,
|
||||||
|
repair: 0
|
||||||
|
};
|
||||||
|
|
||||||
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response));
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response));
|
||||||
|
|
||||||
|
|
@ -434,6 +441,10 @@ describe('Store', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
store.order.insuranceCoverage.coverageType = coverageType.Deductible;
|
store.order.insuranceCoverage.coverageType = coverageType.Deductible;
|
||||||
|
store.order.currentDeductible = {
|
||||||
|
replace: 500,
|
||||||
|
repair: 0
|
||||||
|
};
|
||||||
|
|
||||||
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response));
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response));
|
||||||
|
|
||||||
|
|
@ -453,6 +464,10 @@ describe('Store', () => {
|
||||||
const error = 'register claim error';
|
const error = 'register claim error';
|
||||||
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
|
||||||
store.order.insuranceCoverage.coverageStatus = coverageStatuses.PENDING;
|
store.order.insuranceCoverage.coverageStatus = coverageStatuses.PENDING;
|
||||||
|
store.order.currentDeductible = {
|
||||||
|
replace: 500,
|
||||||
|
repair: 0
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await store.registerClaim().catch((e) => {
|
await store.registerClaim().catch((e) => {
|
||||||
|
|
@ -501,7 +516,7 @@ describe('Store', () => {
|
||||||
home: homePhone,
|
home: homePhone,
|
||||||
service: servicePhone,
|
service: servicePhone,
|
||||||
alternative: altPhone,
|
alternative: altPhone,
|
||||||
extension: extension
|
extension
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
@ -670,10 +685,22 @@ describe('Store', () => {
|
||||||
const policyZipCode = getRandomString(6, 6);
|
const policyZipCode = getRandomString(6, 6);
|
||||||
const status = getRandomEnum(coverageStatuses);
|
const status = getRandomEnum(coverageStatuses);
|
||||||
const type = getRandomEnum(coverageType);
|
const type = getRandomEnum(coverageType);
|
||||||
const originalDeductible = getRandomString(6, 6);
|
const originalDeductible = {
|
||||||
const currentDeductible = getRandomString(6, 6);
|
replace: 500,
|
||||||
store.order.originalDeductible = originalDeductible;
|
repair: 0
|
||||||
store.order.currentDeductible = currentDeductible;
|
};
|
||||||
|
const currentDeductible = {
|
||||||
|
replace: 500,
|
||||||
|
repair: 0
|
||||||
|
};
|
||||||
|
store.order.originalDeductible = {
|
||||||
|
replace: originalDeductible.replace,
|
||||||
|
repair: originalDeductible.repair
|
||||||
|
};
|
||||||
|
store.order.currentDeductible = {
|
||||||
|
replace: currentDeductible.replace,
|
||||||
|
repair: currentDeductible.repair
|
||||||
|
};
|
||||||
store.order.customer.firstName = customerFirstName;
|
store.order.customer.firstName = customerFirstName;
|
||||||
store.order.customer.lastName = customerLastName;
|
store.order.customer.lastName = customerLastName;
|
||||||
store.order.customer.emailAddress = customerEmail;
|
store.order.customer.emailAddress = customerEmail;
|
||||||
|
|
@ -684,6 +711,7 @@ describe('Store', () => {
|
||||||
store.order.policy.policyZipCode = policyZipCode;
|
store.order.policy.policyZipCode = policyZipCode;
|
||||||
store.order.insuranceCoverage.coverageStatus = status;
|
store.order.insuranceCoverage.coverageStatus = status;
|
||||||
store.order.insuranceCoverage.coverageType = type;
|
store.order.insuranceCoverage.coverageType = type;
|
||||||
|
store.order.damage.isRepair = false;
|
||||||
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
|
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -702,8 +730,8 @@ describe('Store', () => {
|
||||||
}),
|
}),
|
||||||
policyNumber,
|
policyNumber,
|
||||||
policyZipCode,
|
policyZipCode,
|
||||||
originalDeductible,
|
originalDeductible: originalDeductible.replace,
|
||||||
currentDeductible
|
currentDeductible: currentDeductible.replace
|
||||||
}),
|
}),
|
||||||
insuranceCoverage: expect.objectContaining({
|
insuranceCoverage: expect.objectContaining({
|
||||||
coverageStatus: status,
|
coverageStatus: status,
|
||||||
|
|
@ -1717,8 +1745,8 @@ describe('Store', () => {
|
||||||
const manualGlassNames = [location];
|
const manualGlassNames = [location];
|
||||||
const policyState = getRandomString(2, 2);
|
const policyState = getRandomString(2, 2);
|
||||||
const status = getRandomString(6, 8);
|
const status = getRandomString(6, 8);
|
||||||
const currentDeductible = getRandomInt(0, 5000);
|
const currentDeductible = 500;
|
||||||
const originalDeductible = getRandomInt(0, 5000);
|
const originalDeductible = 500;
|
||||||
const isRepair = getRandomBoolean();
|
const isRepair = getRandomBoolean();
|
||||||
const policyNumber = getRandomString(10, 20);
|
const policyNumber = getRandomString(10, 20);
|
||||||
const insuredFirstName = getRandomString(10, 20);
|
const insuredFirstName = getRandomString(10, 20);
|
||||||
|
|
@ -1730,8 +1758,14 @@ describe('Store', () => {
|
||||||
|
|
||||||
store.order.referralCorrelationId = referralCorrelationId;
|
store.order.referralCorrelationId = referralCorrelationId;
|
||||||
store.order.parentAccountNumber = parentAccountNumber;
|
store.order.parentAccountNumber = parentAccountNumber;
|
||||||
store.order.currentDeductible = currentDeductible;
|
store.order.currentDeductible = {
|
||||||
store.order.originalDeductible = originalDeductible;
|
replace: currentDeductible,
|
||||||
|
repair: currentDeductible
|
||||||
|
};
|
||||||
|
store.order.originalDeductible = {
|
||||||
|
replace: originalDeductible,
|
||||||
|
repair: originalDeductible
|
||||||
|
};
|
||||||
store.order.policy.status = status;
|
store.order.policy.status = status;
|
||||||
store.order.customer.address.state = policyState;
|
store.order.customer.address.state = policyState;
|
||||||
store.order.damage.isRepair = isRepair;
|
store.order.damage.isRepair = isRepair;
|
||||||
|
|
@ -1827,8 +1861,14 @@ describe('Store', () => {
|
||||||
|
|
||||||
store.order.referralCorrelationId = referralCorrelationId;
|
store.order.referralCorrelationId = referralCorrelationId;
|
||||||
store.order.parentAccountNumber = parentAccountNumber;
|
store.order.parentAccountNumber = parentAccountNumber;
|
||||||
store.order.currentDeductible = currentDeductible;
|
store.order.currentDeductible = {
|
||||||
store.order.originalDeductible = originalDeductible;
|
replace: currentDeductible,
|
||||||
|
repair: currentDeductible
|
||||||
|
};
|
||||||
|
store.order.originalDeductible = {
|
||||||
|
replace: originalDeductible,
|
||||||
|
repair: originalDeductible
|
||||||
|
};
|
||||||
store.order.policy.status = status;
|
store.order.policy.status = status;
|
||||||
store.order.customer.address.state = policyState;
|
store.order.customer.address.state = policyState;
|
||||||
store.order.policy.endorsementQuestionAnswers = endorsementAnswers;
|
store.order.policy.endorsementQuestionAnswers = endorsementAnswers;
|
||||||
|
|
@ -1898,23 +1938,29 @@ describe('Store', () => {
|
||||||
describe('updateDeductible method', () => {
|
describe('updateDeductible method', () => {
|
||||||
it('final deductible is saved as currentDeductible in store', () => {
|
it('final deductible is saved as currentDeductible in store', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const finalDeductible = getRandomInt(0, 5000);
|
store.order.damage.isRepair = false;
|
||||||
|
const deductibleInfo = {
|
||||||
|
deductible: 500
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
store.updateDeductible(finalDeductible);
|
store.updateDeductible(deductibleInfo);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(store.order.currentDeductible).toEqual(finalDeductible);
|
expect(store.order.currentDeductible.replace).toEqual(deductibleInfo.deductible);
|
||||||
});
|
});
|
||||||
it('null final deductible => currentDeductible in store set to null', () => {
|
it('null final deductible => currentDeductible in store set to null', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const finalDeductible = null;
|
store.order.damage.isRepair = false;
|
||||||
|
const deductibleInfo = {
|
||||||
|
deductible: null
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
store.updateDeductible(finalDeductible);
|
store.updateDeductible(deductibleInfo);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(store.order.currentDeductible).toEqual(finalDeductible);
|
expect(store.order.currentDeductible.replace).toEqual(deductibleInfo.deductible);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,18 @@
|
||||||
//Define colors for namespaced classes
|
//Define colors for namespaced classes
|
||||||
$header-background: #ffd100;
|
$header-background: #ffd100;
|
||||||
$accent-fill: #e6f1f3; // Calendar background
|
$accent-fill: #e6f1f3; // Calendar background
|
||||||
$accent-color: #09748b;
|
$accent-color: #0070d1;
|
||||||
$link: #09748b;
|
$link: #0070d1;
|
||||||
$svg-fill-color: '%2309748b'; // Color of calendar icon. Place HEX code *after* %23
|
$svg-fill-color: '%2309748b'; // Color of calendar icon. Place HEX code *after* %23
|
||||||
$progress-bar-success-color: #1a1446;
|
$progress-bar-success-color: #1a1446;
|
||||||
$progress-bar-background-color: #ffffff;
|
$progress-bar-background-color: #ffffff;
|
||||||
|
|
||||||
|
a,
|
||||||
svg,
|
svg,
|
||||||
.modal-text {
|
.modal-text {
|
||||||
fill: $accent-color;
|
fill: $accent-color;
|
||||||
|
color: $accent-color;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,21 @@
|
||||||
cssClassNameForCmsWidget,
|
cssClassNameForCmsWidget,
|
||||||
]">
|
]">
|
||||||
<div class="alert-header">
|
<div class="alert-header">
|
||||||
<svg class="alert-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="21" viewBox="0 0 20 21">
|
<div class="alert-icon-container">
|
||||||
<path fill-rule="nonzero" d="M10 .5c5.523 0 10 4.477 10 10s-4.477 10-10 10-10-4.477-10-10S4.477.5 10 .5zm.043 13.6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm.77-9.2h-1.54l-.088.009a.502.502 0 0 0-.299.193.66.66 0 0 0-.125.47l.747 6.806.017.096c.065.249.263.425.495.426l.084-.008c.22-.042.396-.246.427-.51l.793-6.805.004-.102a.651.651 0 0 0-.127-.37.489.489 0 0 0-.388-.205z"/>
|
<svg
|
||||||
</svg>
|
class="alert-icon"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="21"
|
||||||
|
viewBox="0 0 20 21">
|
||||||
|
<path
|
||||||
|
fill-rule="nonzero"
|
||||||
|
d="M10 .5c5.523 0 10 4.477 10 10s-4.477 10-10 10-10-4.477-10-10S4.477.5 10 .5zm.043 13.6a1
|
||||||
|
1 0 1 0 0 2 1 1 0 0 0 0-2zm.77-9.2h-1.54l-.088.009a.502.502 0 0 0-.299.193.66.66 0 0
|
||||||
|
0-.125.47l.747 6.806.017.096c.065.249.263.425.495.426l.084-.008c.22-.042.396-.246.427-.51l.793-6.805.004-.102a.651.651
|
||||||
|
0 0 0-.127-.37.489.489 0 0 0-.388-.205z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<span class="m-0 alert-header-text">
|
<span class="m-0 alert-header-text">
|
||||||
{{ alertHeadline }}
|
{{ alertHeadline }}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -19,10 +31,18 @@
|
||||||
class="btn-collapse"
|
class="btn-collapse"
|
||||||
type="button"
|
type="button"
|
||||||
@click="toggleCollapse">
|
@click="toggleCollapse">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="9" viewBox="0 0 15 9"
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="15"
|
||||||
|
height="9"
|
||||||
|
viewBox="0 0 15 9"
|
||||||
class="btn-collapse-icon"
|
class="btn-collapse-icon"
|
||||||
:class="{ 'rotated': !collapsed }">
|
:class="{ 'rotated': !collapsed }">
|
||||||
<path fill-rule="nonzero" d="M7.5 0a.806.806 0 0 0-.593.265L.246 7.455a.957.957 0 0 0 0 1.28.796.796 0 0 0 1.185 0l6.07-6.55 6.068 6.55a.796.796 0 0 0 1.186 0 .957.957 0 0 0 0-1.28L8.093.265A.806.806 0 0 0 7.5 0"/>
|
<path
|
||||||
|
fill-rule="nonzero"
|
||||||
|
d="M7.5 0a.806.806 0 0 0-.593.265L.246 7.455a.957.957 0 0 0 0 1.28.796.796 0 0 0
|
||||||
|
1.185 0l6.07-6.55 6.068 6.55a.796.796 0 0 0 1.186 0 .957.957 0 0 0 0-1.28L8.093.265A.806.806
|
||||||
|
0 0 0 7.5 0" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
|
@ -36,13 +56,16 @@
|
||||||
viewBox="0 0 23.7 23.7"
|
viewBox="0 0 23.7 23.7"
|
||||||
xml:space="preserve">
|
xml:space="preserve">
|
||||||
<path
|
<path
|
||||||
d="m23.24 2.7-9.15 9.15L23.24 21a1.581 1.581 0 0 1-1.12 2.7c-.42 0-.82-.16-1.12-.46l-9.15-9.15-9.15 9.15c-.3.3-.7.46-1.12.46A1.581 1.581 0 0 1 .46 21l8.47-8.47.68-.68L.46 2.7c-.62-.62-.62-1.62 0-2.24.62-.62 1.62-.62 2.24 0l8.47 8.47.68.68L21 .46a1.57 1.57 0 0 1 2.23 0c.63.62.63 1.62.01 2.24z" />
|
d="m23.24 2.7-9.15 9.15L23.24 21a1.581 1.581 0 0 1-1.12 2.7c-.42 0-.82-.16-1.12-.46l-9.15-9.15-9.15 9.15c-.3.3-.7.46-1.12.46A1.581
|
||||||
|
1.581 0 0 1 .46 21l8.47-8.47.68-.68L.46 2.7c-.62-.62-.62-1.62 0-2.24.62-.62 1.62-.62 2.24 0l8.47 8.47.68.68L21
|
||||||
|
.46a1.57 1.57 0 0 1 2.23 0c.63.62.63 1.62.01 2.24z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert-body"
|
<div
|
||||||
v-show="alertCopy"
|
v-show="alertCopy"
|
||||||
:id="collapseId">
|
:id="collapseId"
|
||||||
|
class="alert-body">
|
||||||
<template
|
<template
|
||||||
v-for="paragraph in splitAlertCopyForParagraphTag"
|
v-for="paragraph in splitAlertCopyForParagraphTag"
|
||||||
:key="paragraph">
|
:key="paragraph">
|
||||||
|
|
@ -69,9 +92,7 @@
|
||||||
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
||||||
href="#!"
|
href="#!"
|
||||||
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)"
|
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)"
|
||||||
@click-event="
|
@clickEvent="$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))" />
|
||||||
$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))
|
|
||||||
" />
|
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else
|
||||||
|
|
@ -132,10 +153,11 @@ export default {
|
||||||
},
|
},
|
||||||
startCollapsed: Boolean
|
startCollapsed: Boolean
|
||||||
},
|
},
|
||||||
|
emits: ['textLinkClicked'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
collapsed: this.startCollapsed || false,
|
collapsed: this.startCollapsed || false,
|
||||||
collapseElement: null,
|
collapseElement: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -159,7 +181,7 @@ export default {
|
||||||
return this.isCollapsible
|
return this.isCollapsible
|
||||||
? `${this.cmsWidgetName}-collapse`
|
? `${this.cmsWidgetName}-collapse`
|
||||||
: null;
|
: null;
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.ensureAlertIsInViewPort();
|
this.ensureAlertIsInViewPort();
|
||||||
|
|
@ -198,7 +220,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.collapseElement.show();
|
this.collapseElement.show();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -210,13 +232,18 @@ export default {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
.alert-header {
|
.alert-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
padding: .75rem 1rem .75rem 1rem;
|
padding: .75rem 1rem .75rem 1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
|
.alert-icon-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 1.625rem;
|
||||||
|
}
|
||||||
.alert-icon {
|
.alert-icon {
|
||||||
min-width: 1rem;
|
min-width: 1rem;
|
||||||
max-height: 1rem;
|
max-height: 1rem;
|
||||||
|
|
@ -259,7 +286,7 @@ export default {
|
||||||
padding: .5rem 1rem .75rem 1rem;
|
padding: .5rem 1rem .75rem 1rem;
|
||||||
border-top: 1px solid;
|
border-top: 1px solid;
|
||||||
color: $darker-gray;
|
color: $darker-gray;
|
||||||
line-height: 26px;
|
line-height: 1.625rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
&.alert-info {
|
&.alert-info {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue