Merge branch 'develop' into feature/CSR-2199
This commit is contained in:
commit
c56c1338f7
48 changed files with 983 additions and 338 deletions
|
|
@ -84,6 +84,10 @@ const endpoints = {
|
||||||
url: "/parts/api/v1/parts/supporting-items",
|
url: "/parts/api/v1/parts/supporting-items",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
GetRecalPart: {
|
||||||
|
url: "/parts/api/v1/parts/recal-parts",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
GetAlertReasons: {
|
GetAlertReasons: {
|
||||||
url: "/location/api/v1/location/alert-reasons",
|
url: "/location/api/v1/location/alert-reasons",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ const experimentSettings = {
|
||||||
SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA",
|
SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA",
|
||||||
IS_EMAIL_OPTIONAL: "isEmailOptional",
|
IS_EMAIL_OPTIONAL: "isEmailOptional",
|
||||||
SERVICE_PACKAGE_DISCOUNT: "OfferServicePackageDiscount",
|
SERVICE_PACKAGE_DISCOUNT: "OfferServicePackageDiscount",
|
||||||
|
PROMO_ON_PACKAGE: "Offer_Promo_On_Pkg",
|
||||||
RECAL_PRICE_REMOVE: "RecalPriceRemove",
|
RECAL_PRICE_REMOVE: "RecalPriceRemove",
|
||||||
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold",
|
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold",
|
||||||
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold",
|
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold",
|
||||||
|
|
|
||||||
6
src/constants/external-parameters.js
Normal file
6
src/constants/external-parameters.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
const externalParameterStatus = {
|
||||||
|
NOT_SET: null,
|
||||||
|
ACTIVE: 1,
|
||||||
|
INACTIVE: 0,
|
||||||
|
};
|
||||||
|
export { externalParameterStatus };
|
||||||
|
|
@ -29,6 +29,19 @@ export function coverageStatusValue(intCoverageStatus) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function coverageStatusEnum(strCoverageStatus) {
|
||||||
|
switch (strCoverageStatus) {
|
||||||
|
case coverageStatus.PENDING:
|
||||||
|
return 0;
|
||||||
|
case coverageStatus.NOCOMP:
|
||||||
|
return 1;
|
||||||
|
case coverageStatus.VERIFIED:
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const coverageType = {
|
export const coverageType = {
|
||||||
NONE: "None",
|
NONE: "None",
|
||||||
DEDUCTIBLE: "Deductible",
|
DEDUCTIBLE: "Deductible",
|
||||||
|
|
@ -50,3 +63,18 @@ export function coverageTypeValue(intCoverageType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function coverageTypeEnum(strCoverageType) {
|
||||||
|
switch (strCoverageType) {
|
||||||
|
case coverageType.NONE:
|
||||||
|
return 0;
|
||||||
|
case coverageType.DEDUCTIBLE:
|
||||||
|
return 1;
|
||||||
|
case coverageType.ITAC:
|
||||||
|
return 2;
|
||||||
|
case coverageType.NOCOMP:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ const partTypeStrings = {
|
||||||
FRONT_WIPER: "FRONT WIPER",
|
FRONT_WIPER: "FRONT WIPER",
|
||||||
REAR_WIPER: "REAR WIPER",
|
REAR_WIPER: "REAR WIPER",
|
||||||
RAIN_DEFENSE: "RAIN DEFENSE",
|
RAIN_DEFENSE: "RAIN DEFENSE",
|
||||||
|
ADAS_RECALIBRATION: "ADAS RECALIBRATION",
|
||||||
RECALIBRATION: "RECALIBRATION",
|
RECALIBRATION: "RECALIBRATION",
|
||||||
REPLACE_FEE: "REPLACE FEE",
|
REPLACE_FEE: "REPLACE FEE",
|
||||||
RECYCLE_FEE: "RECYCLE FEE",
|
RECYCLE_FEE: "RECYCLE FEE",
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,10 @@ const storeActions = {
|
||||||
REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA: "revalidateOrderPromosAndSaveServerData",
|
REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA: "revalidateOrderPromosAndSaveServerData",
|
||||||
GET_INSURANCE_COMPANY_LIST: "getInsuranceCompanyList",
|
GET_INSURANCE_COMPANY_LIST: "getInsuranceCompanyList",
|
||||||
GET_BILL_TO_ACCOUNT_NUMBER: "getBillToAccountNumber",
|
GET_BILL_TO_ACCOUNT_NUMBER: "getBillToAccountNumber",
|
||||||
|
GET_RECAL_PARTS_AND_SAVE_TO_LINE_ITEMS: "getRecalPartsAndSaveToLineItems",
|
||||||
|
|
||||||
// DEPENDENCY MUTATIONS
|
// DEPENDENCY MUTATIONS
|
||||||
|
RESET_VEHICLE_STATE_AND_DEPENDENCIES: "resetVehicleStateAndDependencies",
|
||||||
RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies",
|
RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies",
|
||||||
RESET_REGISTRATION_STATE_AND_DEPENDENCIES: "resetRegistrationAndDependencies",
|
RESET_REGISTRATION_STATE_AND_DEPENDENCIES: "resetRegistrationAndDependencies",
|
||||||
RESET_PARTS_STATE_AND_DEPENDENCIES: "resetPartsAndDependencies",
|
RESET_PARTS_STATE_AND_DEPENDENCIES: "resetPartsAndDependencies",
|
||||||
|
|
|
||||||
|
|
@ -602,6 +602,24 @@ function setupMocks({
|
||||||
|
|
||||||
if (props) resultingMountOptions.propsData = props;
|
if (props) resultingMountOptions.propsData = props;
|
||||||
|
|
||||||
|
if (isShallowMount) {
|
||||||
|
resultingMountOptions.global.stubs = {
|
||||||
|
...(resultingMountOptions.global.stubs ?? {}),
|
||||||
|
textboxQuestion: {
|
||||||
|
template: `<span></span>`,
|
||||||
|
methods: {
|
||||||
|
handleChange: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dropdownQuestion: {
|
||||||
|
template: `<span></span>`,
|
||||||
|
methods: {
|
||||||
|
handleChange: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const wrapper = isShallowMount
|
const wrapper = isShallowMount
|
||||||
? shallowMount(addressQuestions, resultingMountOptions)
|
? shallowMount(addressQuestions, resultingMountOptions)
|
||||||
: mount(addressQuestions, resultingMountOptions);
|
: mount(addressQuestions, resultingMountOptions);
|
||||||
|
|
|
||||||
|
|
@ -371,6 +371,12 @@ export default {
|
||||||
self.addressModel.state = state;
|
self.addressModel.state = state;
|
||||||
self.addressModel.zipCode = zipCode;
|
self.addressModel.zipCode = zipCode;
|
||||||
|
|
||||||
|
this.$refs.autocomplete.handleChange(streetNumber);
|
||||||
|
this.$refs.apartmentNumberOrBusinessName.handleChange(route);
|
||||||
|
this.$refs.city.handleChange(city);
|
||||||
|
this.$refs.state.handleChange(state);
|
||||||
|
this.$refs.zipCode.handleChange(zipCode);
|
||||||
|
|
||||||
if (!this.displayVerificationWarning) {
|
if (!this.displayVerificationWarning) {
|
||||||
this.displayVerificationWarning = place.partial_match || !isAddressComplete;
|
this.displayVerificationWarning = place.partial_match || !isAddressComplete;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
<span>{{ subtotalText }}</span>
|
<span>{{ subtotalText }}</span>
|
||||||
<span>{{ getLineItemAmount(subTotal, showCoverageAsPending) }}</span>
|
<span>{{ getLineItemAmount(subTotal, showCoverageAsPending) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="sales-tax">
|
<div class="sales-tax" v-show="showSalesTax">
|
||||||
<span>{{ salesTaxText }}</span>
|
<span>{{ salesTaxText }}</span>
|
||||||
<span>{{ getLineItemAmount(salesTax) }}</span>
|
<span>{{ getLineItemAmount(salesTax) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -188,6 +188,8 @@ export default {
|
||||||
insuranceCompanyName: String,
|
insuranceCompanyName: String,
|
||||||
showInsuranceCoverageAs: String,
|
showInsuranceCoverageAs: String,
|
||||||
shouldHideRecalibration: Boolean,
|
shouldHideRecalibration: Boolean,
|
||||||
|
isItac: Boolean,
|
||||||
|
isNoComp: Boolean,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -305,8 +307,8 @@ export default {
|
||||||
if (!this.lineItems || this.lineItems.length < 1) return;
|
if (!this.lineItems || this.lineItems.length < 1) return;
|
||||||
|
|
||||||
const lineItemsCopy = deepClone(this.lineItems);
|
const lineItemsCopy = deepClone(this.lineItems);
|
||||||
lineItemsCopy.supportingItems = lineItemsCopy.supportingItems
|
lineItemsCopy.glassParts = lineItemsCopy.glassParts
|
||||||
? baseMixin.methods.filterOutRecalibration(lineItemsCopy?.supportingItems)
|
? baseMixin.methods.filterOutRecalibration(lineItemsCopy?.glassParts)
|
||||||
: [];
|
: [];
|
||||||
return lineItemsCopy;
|
return lineItemsCopy;
|
||||||
},
|
},
|
||||||
|
|
@ -316,6 +318,10 @@ export default {
|
||||||
showCoverageAsVerified() {
|
showCoverageAsVerified() {
|
||||||
return this.showInsuranceCoverageAs === coverageStatus.VERIFIED;
|
return this.showInsuranceCoverageAs === coverageStatus.VERIFIED;
|
||||||
},
|
},
|
||||||
|
showSalesTax() {
|
||||||
|
const tax = parseFloat(this.salesTax).toFixed(2);
|
||||||
|
return tax > 0;
|
||||||
|
},
|
||||||
currentDeductible() {
|
currentDeductible() {
|
||||||
const deductible = this.insuranceDeductible;
|
const deductible = this.insuranceDeductible;
|
||||||
if (!(deductible === 0 || deductible > 0)) {
|
if (!(deductible === 0 || deductible > 0)) {
|
||||||
|
|
@ -1007,6 +1013,16 @@ export default {
|
||||||
},
|
},
|
||||||
salesTax() {
|
salesTax() {
|
||||||
if (!this.lineItems || this.lineItems.length < 1) return;
|
if (!this.lineItems || this.lineItems.length < 1) return;
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.isInsurance &&
|
||||||
|
!this.showCoverageAsVerified &&
|
||||||
|
!this.isItac &&
|
||||||
|
!this.isNoComp
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return this.isInsurance || !this.shouldHideRecalibration
|
return this.isInsurance || !this.shouldHideRecalibration
|
||||||
? baseMixin.methods.getSalesTax(this.lineItems) // calculate with recal (if on order)
|
? baseMixin.methods.getSalesTax(this.lineItems) // calculate with recal (if on order)
|
||||||
: baseMixin.methods.getSalesTax(this.lineItemsWithoutRecal); // calculated without recal
|
: baseMixin.methods.getSalesTax(this.lineItemsWithoutRecal); // calculated without recal
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ export default {
|
||||||
return this.leftAlignHeader ? "justify-content-start" : "justify-content-center";
|
return this.leftAlignHeader ? "justify-content-start" : "justify-content-center";
|
||||||
},
|
},
|
||||||
subText() {
|
subText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "HeaderSubText");
|
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
||||||
},
|
},
|
||||||
backButtonAccessibleText() {
|
backButtonAccessibleText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText");
|
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText");
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import store from "@/store";
|
||||||
|
|
||||||
import { applicationConfig } from "@/constants/application-config.js";
|
import { applicationConfig } from "@/constants/application-config.js";
|
||||||
import { GaCategories, GaActions, GaLabels } from "@/constants/analytics";
|
import { GaCategories, GaActions, GaLabels } from "@/constants/analytics";
|
||||||
|
import { getSessionKeyValue } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
import { headerKeys } from "@/constants/header-keys";
|
import { headerKeys } from "@/constants/header-keys";
|
||||||
import axiosResponseInterceptorMessages from "@/constants/axios-response-interceptor-messages.js";
|
import axiosResponseInterceptorMessages from "@/constants/axios-response-interceptor-messages.js";
|
||||||
|
|
||||||
|
|
@ -65,7 +66,7 @@ export default {
|
||||||
const headers = {
|
const headers = {
|
||||||
[headerKeys.EXPERIMENT]: JSON.stringify(store.getters.experimentSettings),
|
[headerKeys.EXPERIMENT]: JSON.stringify(store.getters.experimentSettings),
|
||||||
[headerKeys.APPLICATION_NAME]: applicationConfig.APPLICATION_NAME,
|
[headerKeys.APPLICATION_NAME]: applicationConfig.APPLICATION_NAME,
|
||||||
[headerKeys.SESSION_SEQUENCE_NUMBER]: store.getters.applicationUser?.savedSessionId,
|
[headerKeys.SESSION_SEQUENCE_NUMBER]: getSessionKeyValue(),
|
||||||
[headerKeys.REFERRAL_SEQUENCE_NUMBER]: order?.referralSequenceNumber,
|
[headerKeys.REFERRAL_SEQUENCE_NUMBER]: order?.referralSequenceNumber,
|
||||||
[headerKeys.TRANSACTION_ID]: crypto.randomUUID(),
|
[headerKeys.TRANSACTION_ID]: crypto.randomUUID(),
|
||||||
[headerKeys.EON]: order?.eon,
|
[headerKeys.EON]: order?.eon,
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,10 @@ export async function getImplicitNavigation(toRoute) {
|
||||||
export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog }) {
|
export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog }) {
|
||||||
const log = getQuerystringParameter(queryStrings.LOG);
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
if (eval(log)) {
|
if (eval(log)) {
|
||||||
|
console.log("------------- Navigate to heritage start -----------------");
|
||||||
console.log(new Date() + " applicationConfig: " + JSON.stringify(applicationConfig));
|
console.log(new Date() + " applicationConfig: " + JSON.stringify(applicationConfig));
|
||||||
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL);
|
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL);
|
||||||
|
console.log("------------- Navigate to heritage end -----------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the order (or save existing order) when navigating to Heritage Funnel.
|
// Create the order (or save existing order) when navigating to Heritage Funnel.
|
||||||
|
|
@ -132,6 +134,8 @@ export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("fixmyglasstest") &&
|
||||||
|
process.env.VUE_APP_CURRENT_ENVIRONMENT === "Localhost") ||
|
||||||
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("fixmyglassdev") &&
|
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("fixmyglassdev") &&
|
||||||
process.env.VUE_APP_CURRENT_ENVIRONMENT === "Localhost") ||
|
process.env.VUE_APP_CURRENT_ENVIRONMENT === "Localhost") ||
|
||||||
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("localhost") &&
|
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("localhost") &&
|
||||||
|
|
|
||||||
60
src/helpers/recal-helper.js
Normal file
60
src/helpers/recal-helper.js
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { deepClone } from "@/helpers/object-helper";
|
||||||
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
|
|
||||||
|
const recalPartTypes = [partTypeStrings.RECALIBRATION, partTypeStrings.ADAS_RECALIBRATION];
|
||||||
|
|
||||||
|
export function isRecalPartOrHasChildRecalPart(lineItem) {
|
||||||
|
if (lineItem.childParts && lineItem.childParts.length > 0) {
|
||||||
|
return isRecalPart(lineItem) || containsRecalParts(lineItem.childParts);
|
||||||
|
} else {
|
||||||
|
return isRecalPart(lineItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isRecalPart(lineItem) {
|
||||||
|
return recalPartTypes.some((type) => lineItem.partType === type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function containsRecalParts(lineItems) {
|
||||||
|
if (!lineItems) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(lineItems)) {
|
||||||
|
return lineItems.some((li) => isRecalPartOrHasChildRecalPart(li));
|
||||||
|
} else {
|
||||||
|
// complex object form -- flatten and re-call.
|
||||||
|
const flattened = [
|
||||||
|
...(lineItems.glassParts ?? []),
|
||||||
|
...(lineItems.supportingItems ?? []),
|
||||||
|
...(lineItems.vaps ?? []),
|
||||||
|
...(lineItems.promos ?? []),
|
||||||
|
];
|
||||||
|
|
||||||
|
return flattened.some((li) => isRecalPartOrHasChildRecalPart(li));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getItemsWithoutRecalParts(lineItems) {
|
||||||
|
const copy = deepClone(lineItems);
|
||||||
|
|
||||||
|
const firstLevelFiltered = copy.filter((li) => !isRecalPart(li));
|
||||||
|
|
||||||
|
const childrenFiltered = firstLevelFiltered.map((li) => {
|
||||||
|
if (li.childParts && li.childParts.length > 0) {
|
||||||
|
li.childParts = getItemsWithoutRecalParts(li.childParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return li;
|
||||||
|
});
|
||||||
|
|
||||||
|
return childrenFiltered;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTopLevelPartsWithRecal(lineItems) {
|
||||||
|
if (!lineItems) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lineItems.filter((li) => isRecalPartOrHasChildRecalPart(li));
|
||||||
|
}
|
||||||
|
|
@ -239,6 +239,15 @@ export function getPackageNameByType(packageType) {
|
||||||
return package_names[packageType] || null;
|
return package_names[packageType] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDiscountPackageName(discountPackage) {
|
||||||
|
const package_names = {
|
||||||
|
ECON: packageNames.TIER_ONE,
|
||||||
|
STANDARD: packageNames.TIER_TWO,
|
||||||
|
PREMIUM: packageNames.TIER_THREE,
|
||||||
|
};
|
||||||
|
return package_names[discountPackage] || null;
|
||||||
|
}
|
||||||
|
|
||||||
function maxTier(tierA, tierB) {
|
function maxTier(tierA, tierB) {
|
||||||
if (tierA === packageNames.TIER_THREE || tierB === packageNames.TIER_THREE) {
|
if (tierA === packageNames.TIER_THREE || tierB === packageNames.TIER_THREE) {
|
||||||
return packageNames.TIER_THREE;
|
return packageNames.TIER_THREE;
|
||||||
|
|
|
||||||
|
|
@ -375,6 +375,7 @@ export default {
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
await this.getAndSaveBillToAccountNumber();
|
||||||
|
|
||||||
return await this.navigateForward(carsFound);
|
return await this.navigateForward(carsFound);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import questionsPageLayout from "@/fmg-components/layouts/questions-page-layout/
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { required } from "@/helpers/validation-rules";
|
||||||
|
|
@ -52,9 +53,20 @@ export default {
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next(async (vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||||
|
if (store.getters.externalParameterServiceZip.zipCode) {
|
||||||
|
await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
zipCode: store.getters.externalParameterServiceZip.zipCode,
|
||||||
|
state: null,
|
||||||
|
zipCodeCtu: null,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ describe("computed properties...", () => {
|
||||||
const testValue = wrapper.vm.AppointmentWordingText;
|
const testValue = wrapper.vm.AppointmentWordingText;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(testValue).toEqual("wording Text 123, test,<br/> test, AZ 12345");
|
expect(testValue).toEqual("wording Text test, 123,<br/> test, AZ 12345");
|
||||||
});
|
});
|
||||||
test("AppointmentWordingText should return DROP_OFF text in expected format.", () => {
|
test("AppointmentWordingText should return DROP_OFF text in expected format.", () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
|
|
@ -419,7 +419,7 @@ describe("computed properties...", () => {
|
||||||
const testValue = wrapper.vm.ServiceLocationFullAddress;
|
const testValue = wrapper.vm.ServiceLocationFullAddress;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(testValue).toEqual("123, test,<br/> test, AZ 12345");
|
expect(testValue).toEqual("test, 123,<br/> test, AZ 12345");
|
||||||
});
|
});
|
||||||
test("ProviderFullAddress should return text in expected format.", () => {
|
test("ProviderFullAddress should return text in expected format.", () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,13 @@
|
||||||
v-model="lineItems"
|
v-model="lineItems"
|
||||||
:showAsPaid="isPia"
|
:showAsPaid="isPia"
|
||||||
servicePackageOptionsCmsName="ServicePackageTitle"
|
servicePackageOptionsCmsName="ServicePackageTitle"
|
||||||
|
:isInsurance="isInsurance"
|
||||||
:insuranceDeductible="currentDeductible"
|
:insuranceDeductible="currentDeductible"
|
||||||
:insuranceCompanyName="insuranceCompanyName"
|
:insuranceCompanyName="insuranceCompanyName"
|
||||||
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
||||||
:shouldHideRecalibration="shouldHideRecalibration" />
|
:shouldHideRecalibration="shouldHideRecalibration"
|
||||||
|
:isItac="isItac"
|
||||||
|
:isNoComp="isNoComp" />
|
||||||
|
|
||||||
<hr class="mb-5" />
|
<hr class="mb-5" />
|
||||||
|
|
||||||
|
|
@ -108,6 +111,7 @@ import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helpe
|
||||||
import { experimentSettings } from "@/constants/experiments";
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
||||||
|
import { containsRecalParts } from "@/helpers/recal-helper.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "confirmation",
|
name: "confirmation",
|
||||||
|
|
@ -170,10 +174,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isRecalibrationOnOrder() {
|
isRecalibrationOnOrder() {
|
||||||
return containsLineItemWithPartType(
|
return containsRecalParts(this?.lineItems);
|
||||||
partTypeStrings.RECALIBRATION,
|
|
||||||
this?.lineItems?.supportingItems
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
shouldHideRecalibration() {
|
shouldHideRecalibration() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -313,11 +314,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ServiceLocationFullAddress() {
|
ServiceLocationFullAddress() {
|
||||||
return `${this.ServiceLocationAddress2 ? this.ServiceLocationAddress2 + "," : ""} ${
|
return `${this.ServiceLocationAddress}${this.ServiceLocationAddress2 ? ", " + this.ServiceLocationAddress2 : ""},<br/> ${this.ServiceLocationCity}, ${this.ServiceLocationState} ${this.ServiceLocationZipCode}`;
|
||||||
this.ServiceLocationAddress
|
|
||||||
},<br/> ${this.ServiceLocationCity}, ${this.ServiceLocationState} ${
|
|
||||||
this.ServiceLocationZipCode
|
|
||||||
}`;
|
|
||||||
},
|
},
|
||||||
ProviderFullAddress() {
|
ProviderFullAddress() {
|
||||||
return `${this.ProviderAddress},<br/> ${this.ProviderCity}, ${this.ProviderState} ${this.ProviderZipCode}`;
|
return `${this.ProviderAddress},<br/> ${this.ProviderCity}, ${this.ProviderState} ${this.ProviderZipCode}`;
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,10 @@ export default {
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
|
//Reload page if serve from bfcache.
|
||||||
|
if (performance.getEntriesByType("navigation")[0].type === "back_forward") {
|
||||||
|
vm.handlePageShow();
|
||||||
|
}
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
vm.originalList = resultMap.insuranceCompanyList;
|
vm.originalList = resultMap.insuranceCompanyList;
|
||||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||||
|
|
@ -93,6 +97,9 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handlePageShow() {
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
isCashParentAccountNumber() {
|
isCashParentAccountNumber() {
|
||||||
return (
|
return (
|
||||||
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER.toString() ===
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER.toString() ===
|
||||||
|
|
@ -121,6 +128,20 @@ export default {
|
||||||
this.parentAccountNumber.toString(),
|
this.parentAccountNumber.toString(),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const billToAccountNumber = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
|
storeActions.GET_BILL_TO_ACCOUNT_NUMBER,
|
||||||
|
{},
|
||||||
|
"insurance-company",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
||||||
|
billToAccountNumber,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
navigateToHeritageFunnel({
|
navigateToHeritageFunnel({
|
||||||
shouldSaveSession: true,
|
shouldSaveSession: true,
|
||||||
pageNameToLog: "insurance-company",
|
pageNameToLog: "insurance-company",
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,7 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await this.getAndSaveBillToAccountNumber();
|
||||||
return await this.navigateForward();
|
return await this.navigateForward();
|
||||||
},
|
},
|
||||||
lookupVin(plate, state) {
|
lookupVin(plate, state) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import questionsPageLayout from "@/fmg-components/layouts/questions-page-layout/
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { required } from "@/helpers/validation-rules";
|
||||||
|
|
@ -52,9 +53,21 @@ export default {
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next(async (vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||||
|
if (store.getters.externalParameterServiceZip.zipCode) {
|
||||||
|
await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
zipCode: store.getters.externalParameterServiceZip.zipCode,
|
||||||
|
state: null,
|
||||||
|
zipCodeCtu: null,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import questionsPageLayout from "@/fmg-components/layouts/questions-page-layout/
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { required } from "@/helpers/validation-rules";
|
||||||
|
|
@ -52,9 +53,22 @@ export default {
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next(async (vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||||
|
if (store.getters.externalParameterServiceZip.zipCode) {
|
||||||
|
const serviceState = store.getters.order.serviceLocation.state;
|
||||||
|
const serviceZipCtu = store.getters.order.serviceLocation.zipCodeCtu;
|
||||||
|
await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
zipCode: store.getters.externalParameterServiceZip.zipCode,
|
||||||
|
state: serviceState ?? null,
|
||||||
|
zipCodeCtu: serviceZipCtu ?? null,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,9 @@
|
||||||
:insuranceDeductible="currentDeductible"
|
:insuranceDeductible="currentDeductible"
|
||||||
:insuranceCompanyName="insuranceCompanyName"
|
:insuranceCompanyName="insuranceCompanyName"
|
||||||
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
||||||
:shouldHideRecalibration="shouldHideRecalibration" />
|
:shouldHideRecalibration="shouldHideRecalibration"
|
||||||
|
:isItac="isItac"
|
||||||
|
:isNoComp="isNoComp" />
|
||||||
|
|
||||||
<hr class="my-5" />
|
<hr class="my-5" />
|
||||||
|
|
||||||
|
|
@ -76,7 +78,7 @@
|
||||||
validationRules="payment-method-required" />
|
validationRules="payment-method-required" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
v-if="!showPaymentMethodQuestions && !forwardClicked"
|
v-if="showHavePaymentReadyAlert"
|
||||||
:isDismissible="false"
|
:isDismissible="false"
|
||||||
alertClass="alert-info"
|
alertClass="alert-info"
|
||||||
cmsWidgetName="NoPiaDisclaimerWidget"
|
cmsWidgetName="NoPiaDisclaimerWidget"
|
||||||
|
|
@ -153,6 +155,7 @@ import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { mapTaxedLineItemsToStoreFormat } from "../../store";
|
import { mapTaxedLineItemsToStoreFormat } from "../../store";
|
||||||
import { coverageStatus } from "@/constants/insurance";
|
import { coverageStatus } from "@/constants/insurance";
|
||||||
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
||||||
|
import { containsRecalParts } from "@/helpers/recal-helper";
|
||||||
|
|
||||||
defineRule("payment-method-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("payment-method-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
defineRule("recal-ack-required", required(errorMessages.RECAL_ACK_REQUIRED));
|
defineRule("recal-ack-required", required(errorMessages.RECAL_ACK_REQUIRED));
|
||||||
|
|
@ -586,10 +589,11 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isRecalibrationOnOrder() {
|
isRecalibrationOnOrder() {
|
||||||
return containsLineItemWithPartType(
|
const order = baseMixin.methods.hasSubmittedOrder()
|
||||||
partTypeStrings.RECALIBRATION,
|
? baseMixin.methods.getSubmittedOrder()
|
||||||
this.$store.getters.order.lineItems?.supportingItems
|
: this.$store.getters.order;
|
||||||
);
|
|
||||||
|
return containsRecalParts(order.lineItems);
|
||||||
},
|
},
|
||||||
shouldHideRecalibration() {
|
shouldHideRecalibration() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -626,13 +630,16 @@ export default {
|
||||||
},
|
},
|
||||||
showInsuranceCoverageAs() {
|
showInsuranceCoverageAs() {
|
||||||
if (!this.isInsurance) return null;
|
if (!this.isInsurance) return null;
|
||||||
|
|
||||||
if (this.isNoComp || this.isItac) {
|
if (this.isNoComp || this.isItac) {
|
||||||
return coverageStatus.NOCOMP;
|
return coverageStatus.NOCOMP;
|
||||||
} else {
|
|
||||||
return this.hasSubmittedOrder()
|
|
||||||
? this.getSubmittedOrder()?.payment.insuranceCoverage.coverageStatus
|
|
||||||
: this.$store.getters.payment.insuranceCoverage.coverageStatus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.$store.getters.coverageIsVerified) {
|
||||||
|
return coverageStatus.VERIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return coverageStatus.PENDING;
|
||||||
},
|
},
|
||||||
currentDeductible() {
|
currentDeductible() {
|
||||||
return this.hasSubmittedOrder()
|
return this.hasSubmittedOrder()
|
||||||
|
|
@ -674,6 +681,11 @@ export default {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
showHavePaymentReadyAlert() {
|
||||||
|
return (
|
||||||
|
!this.showPaymentMethodQuestions && !this.forwardClicked && this.totalAmountDue > 0
|
||||||
|
);
|
||||||
|
},
|
||||||
totalAmountDue() {
|
totalAmountDue() {
|
||||||
return baseMixin.methods.getAmountDue(this.lineItems);
|
return baseMixin.methods.getAmountDue(this.lineItems);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,9 @@
|
||||||
recyclingModalCmsWidgetName="RecycleModal"
|
recyclingModalCmsWidgetName="RecycleModal"
|
||||||
:insuranceDeductible="currentDeductible"
|
:insuranceDeductible="currentDeductible"
|
||||||
:insuranceCompanyName="insuranceCompanyName"
|
:insuranceCompanyName="insuranceCompanyName"
|
||||||
:showInsuranceCoverageAs="showInsuranceCoverageAs" />
|
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
||||||
|
:isItac="isItac"
|
||||||
|
:isNocomp="isNocomp" />
|
||||||
|
|
||||||
<hr class="mb-5" />
|
<hr class="mb-5" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
import { splitCopyOnCMSPlaceHolder } from "@/helpers/cms-content-helper";
|
import { splitCopyOnCMSPlaceHolder } from "@/helpers/cms-content-helper";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { getPromosThatMatchLineItemsOnOrder } from "@/helpers/promotions-helper";
|
import { getPromosThatMatchLineItemsOnOrder } from "@/helpers/promotions-helper";
|
||||||
import { getArrayOfAllLineItems } from "@/store";
|
import { getArrayOfAllLineItemsAndChildParts } from "@/store";
|
||||||
|
|
||||||
const INLINE_IMAGE_TOKEN = "custom:inlineImage";
|
const INLINE_IMAGE_TOKEN = "custom:inlineImage";
|
||||||
const AFTERPAY_PRICE_TOKEN = "custom:afterpayPrice";
|
const AFTERPAY_PRICE_TOKEN = "custom:afterpayPrice";
|
||||||
|
|
@ -76,7 +76,7 @@ export default {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
||||||
},
|
},
|
||||||
afterpayPrice() {
|
afterpayPrice() {
|
||||||
let allLineItems = getArrayOfAllLineItems(this.lineItems);
|
let allLineItems = getArrayOfAllLineItemsAndChildParts(this.lineItems);
|
||||||
if (this.lineItems.promos) {
|
if (this.lineItems.promos) {
|
||||||
allLineItems = allLineItems?.filter((item) => item.partType !== "PROMO_DISCOUNT");
|
allLineItems = allLineItems?.filter((item) => item.partType !== "PROMO_DISCOUNT");
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.lineItems.promos) {
|
if (this.lineItems.promos) {
|
||||||
let allLineItems = getArrayOfAllLineItems(this.lineItems);
|
let allLineItems = getArrayOfAllLineItemsAndChildParts(this.lineItems);
|
||||||
const promos = getPromosThatMatchLineItemsOnOrder(
|
const promos = getPromosThatMatchLineItemsOnOrder(
|
||||||
this.lineItems.promos,
|
this.lineItems.promos,
|
||||||
allLineItems
|
allLineItems
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,28 @@ jest.mock("@/mixins/base-mixin", () => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const mockExperimentSettings = experimentSettings;
|
||||||
|
|
||||||
|
jest.mock("@/mixins/experiment-mixin.js", () => ({
|
||||||
|
methods: {
|
||||||
|
getSettingValue(settingName) {
|
||||||
|
if (settingName === mockExperimentSettings.SERVICE_PACKAGE_DISCOUNT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
settingName === mockExperimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL
|
||||||
|
) {
|
||||||
|
return 300;
|
||||||
|
} else if (
|
||||||
|
settingName === mockExperimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL
|
||||||
|
) {
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
return "test";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const mockMixin = {
|
const mockMixin = {
|
||||||
methods: {
|
methods: {
|
||||||
filterOutFees: jest.fn().mockImplementation(() => {
|
filterOutFees: jest.fn().mockImplementation(() => {
|
||||||
|
|
@ -73,12 +95,6 @@ const mockMixin = {
|
||||||
isFormValid: jest.fn().mockImplementation(() => {
|
isFormValid: jest.fn().mockImplementation(() => {
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
getSettingValue: jest.fn((settingName) => {
|
|
||||||
if (settingName === experimentSettings.SERVICE_PACKAGE_DISCOUNT) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mockTierOnePrice = 501;
|
let mockTierOnePrice = 501;
|
||||||
|
|
@ -309,7 +325,7 @@ describe("quote.vue", () => {
|
||||||
|
|
||||||
wrapper.vm.$route = { query: { isInsurance: "false" } };
|
wrapper.vm.$route = { query: { isInsurance: "false" } };
|
||||||
|
|
||||||
const isServicePackageDiscount = mockMixin.methods.getSettingValue(
|
const isServicePackageDiscount = experimentMixin.methods.getSettingValue(
|
||||||
experimentSettings.SERVICE_PACKAGE_DISCOUNT
|
experimentSettings.SERVICE_PACKAGE_DISCOUNT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -364,7 +380,7 @@ describe("quote.vue", () => {
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
||||||
});
|
});
|
||||||
test("should default to cash if query param 'isInsurance' is false", async () => {
|
test("should use amount threshold if query param 'isInsurance' is false", async () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
store.getters = {
|
store.getters = {
|
||||||
lineItems: {
|
lineItems: {
|
||||||
|
|
@ -391,6 +407,7 @@ describe("quote.vue", () => {
|
||||||
settingName: "SERVICE_PACKAGE_DISCOUNT",
|
settingName: "SERVICE_PACKAGE_DISCOUNT",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
mockTierOnePrice = 200;
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
|
|
@ -701,7 +718,7 @@ describe("quote.vue", () => {
|
||||||
inactivePromos: [],
|
inactivePromos: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
externalParameterState: { isExternalParameter: true },
|
externalParameterState: { isExternalParameter: 1 },
|
||||||
externalParameterQuote: {
|
externalParameterQuote: {
|
||||||
isInsurance: true,
|
isInsurance: true,
|
||||||
servicePackage: "glassonly",
|
servicePackage: "glassonly",
|
||||||
|
|
@ -758,8 +775,6 @@ function setupMocks({ customMountOptions }) {
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal = jest.fn();
|
baseMixin.methods.ResetExternalParamsAndHideModal = jest.fn();
|
||||||
baseMixin.methods.isFormValid = jest.fn().mockReturnValue(true);
|
baseMixin.methods.isFormValid = jest.fn().mockReturnValue(true);
|
||||||
mountOptions.global.mocks["$store"] = store;
|
mountOptions.global.mocks["$store"] = store;
|
||||||
store.getters.experimentSettings = "test value";
|
|
||||||
|
|
||||||
mountOptions["attachTo"] = document.body;
|
mountOptions["attachTo"] = document.body;
|
||||||
|
|
||||||
const wrapper = shallowMount(quote, mountOptions);
|
const wrapper = shallowMount(quote, mountOptions);
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
alertClass="alert-info" />
|
alertClass="alert-info" />
|
||||||
|
|
||||||
<promoModalQuestion
|
<promoModalQuestion
|
||||||
class="small mt-6 d-md-flex justify-content-md-center"
|
class="small mt-6 d-flex justify-content-center"
|
||||||
v-model="lineItems"
|
v-model="lineItems"
|
||||||
:addableVaps="addableVaps"
|
:addableVaps="addableVaps"
|
||||||
pageName="quote"
|
pageName="quote"
|
||||||
|
|
@ -69,9 +69,9 @@
|
||||||
|
|
||||||
<textBlock
|
<textBlock
|
||||||
cmsWidgetName="quoteDisclaimer"
|
cmsWidgetName="quoteDisclaimer"
|
||||||
justifyText="left"
|
justifyText="center"
|
||||||
typeStyle="caption"
|
typeStyle="caption"
|
||||||
class="mt-6" />
|
class="mt-6 quote-disclaimer" />
|
||||||
|
|
||||||
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
||||||
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
||||||
|
|
@ -135,6 +135,9 @@ import {
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { packageNames } from "@/constants/package-names";
|
import { packageNames } from "@/constants/package-names";
|
||||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
|
import { containsRecalParts } from "@/helpers/recal-helper";
|
||||||
|
import { externalParameterStatus } from "@/constants/external-parameters";
|
||||||
|
|
||||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
const INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT = 300;
|
const INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT = 300;
|
||||||
|
|
@ -296,8 +299,9 @@ export default {
|
||||||
|
|
||||||
const getIsInsuranceSelectedValue = (availableLineItems, insuranceThreshold) => {
|
const getIsInsuranceSelectedValue = (availableLineItems, insuranceThreshold) => {
|
||||||
const serviceLocationState = store.getters.order.serviceLocation.state;
|
const serviceLocationState = store.getters.order.serviceLocation.state;
|
||||||
// Override if coming back from QuoteDetails. Remove override after Quote release
|
|
||||||
const isInsuranceOverrideValue = to.query?.isInsurance;
|
// usually true when returning from heritage but can be false when returning from heritage on a save quote
|
||||||
|
const isInsuranceFromQueryString = to.query?.isInsurance || to.query?.isinsurance;
|
||||||
const defaultIsInsuranceSelectedValue = store.getters.order.payment.isInsurance;
|
const defaultIsInsuranceSelectedValue = store.getters.order.payment.isInsurance;
|
||||||
const hideRecalCost =
|
const hideRecalCost =
|
||||||
experimentMixin.methods
|
experimentMixin.methods
|
||||||
|
|
@ -308,72 +312,88 @@ export default {
|
||||||
if (
|
if (
|
||||||
serviceLocationState != null &&
|
serviceLocationState != null &&
|
||||||
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
||||||
)
|
) {
|
||||||
return true;
|
return true;
|
||||||
else if (isInsuranceOverrideValue != null) {
|
|
||||||
return isInsuranceOverrideValue == "true";
|
|
||||||
} else if (defaultIsInsuranceSelectedValue != null) {
|
|
||||||
return defaultIsInsuranceSelectedValue;
|
|
||||||
} else {
|
|
||||||
if (availableLineItems) {
|
|
||||||
const lineItemsForCalculatingPrice = hideRecalCost
|
|
||||||
? baseMixin.methods.filterOutFees(
|
|
||||||
baseMixin.methods.filterOutRecalibration(availableLineItems) // Strip out recal before filtering out fees
|
|
||||||
)
|
|
||||||
: baseMixin.methods.filterOutFees(availableLineItems);
|
|
||||||
|
|
||||||
return (
|
|
||||||
baseMixin.methods.getTierOnePackagePrice(lineItemsForCalculatingPrice) >
|
|
||||||
insuranceThreshold
|
|
||||||
); // compare base price vs arbitrary threshold (representing insurance price)
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (defaultIsInsuranceSelectedValue != null) {
|
||||||
|
return defaultIsInsuranceSelectedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (availableLineItems) {
|
||||||
|
const lineItemsForCalculatingPrice = hideRecalCost
|
||||||
|
? baseMixin.methods.filterOutFees(
|
||||||
|
baseMixin.methods.filterOutRecalibration(availableLineItems) // Strip out recal before filtering out fees
|
||||||
|
)
|
||||||
|
: baseMixin.methods.filterOutFees(availableLineItems);
|
||||||
|
|
||||||
|
if (isInsuranceFromQueryString != null) {
|
||||||
|
if (isInsuranceFromQueryString.toLowerCase() === "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
baseMixin.methods.getTierOnePackagePrice(lineItemsForCalculatingPrice) >
|
||||||
|
insuranceThreshold
|
||||||
|
); // compare base price vs arbitrary threshold (representing insurance price)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
let thresholdToUse = INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT;
|
let thresholdToUse = INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT;
|
||||||
let internalThreshold = experimentMixin.methods.getSettingValue(
|
let internalThreshold = experimentMixin.methods.getSettingValue(
|
||||||
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL
|
||||||
);
|
);
|
||||||
|
let externalThreshold = experimentMixin.methods.getSettingValue(
|
||||||
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL
|
||||||
|
);
|
||||||
|
const isExternalParameter = store.getters.externalParameterState?.isExternalParameter;
|
||||||
|
|
||||||
if (!store.getters.externalParameterState?.isExternalParameter) {
|
// prettier-ignore
|
||||||
// there are no external parameters
|
{
|
||||||
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
|
if (eval(log)) {
|
||||||
|
console.log("------------- quote.vue thresholds start -----------------");
|
||||||
|
console.log(new Date() + " isExternalParameter: " + isExternalParameter);
|
||||||
|
console.log(new Date() + " internalThreshold: " + internalThreshold);
|
||||||
|
console.log(new Date() + " externalThreshold: " + externalThreshold);
|
||||||
|
console.log("------------- quote.vue thresholds end -----------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isExternalParameter === externalParameterStatus.NOT_SET) {
|
||||||
|
// there are no active or inactive external parameters; use internal threshold
|
||||||
if (internalThreshold) thresholdToUse = internalThreshold;
|
if (internalThreshold) thresholdToUse = internalThreshold;
|
||||||
|
|
||||||
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
||||||
vm.availableLineItems,
|
vm.availableLineItems,
|
||||||
thresholdToUse
|
thresholdToUse
|
||||||
);
|
);
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
} else {
|
} else {
|
||||||
// there ARE external parameters
|
// user came from an external source, however, the externalParms may have been reset on service-zip, property-questions, etc...
|
||||||
|
if (eval(store.getters.externalParameterQuote?.isInsurance)) {
|
||||||
if (store.getters.externalParameterQuote.isInsurance == true) {
|
|
||||||
// did user intentionally select insurance?
|
// did user intentionally select insurance?
|
||||||
vm.isInsuranceSelected = true;
|
vm.isInsuranceSelected = true;
|
||||||
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
|
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
|
|
||||||
if (isValid) {
|
|
||||||
vm.forwardButtonAction();
|
|
||||||
} else {
|
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// did user come from external source (LeadGen)?
|
|
||||||
let externalSource = store.getters.externalParameterSource
|
|
||||||
? store.getters.externalParameterSource
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Business logic to determine what "external" source is
|
if (
|
||||||
if (externalSource?.includes("LeadGen")) {
|
vm.servicePackage != null &&
|
||||||
const externalThreshold = experimentMixin.methods.getSettingValue(
|
isExternalParameter === externalParameterStatus.ACTIVE
|
||||||
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL
|
) {
|
||||||
);
|
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
|
||||||
if (externalThreshold) thresholdToUse = externalThreshold;
|
if (isValid) {
|
||||||
} else {
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
if (internalThreshold) thresholdToUse = internalThreshold;
|
vm.forwardButtonAction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
|
} else {
|
||||||
|
if (externalThreshold) thresholdToUse = externalThreshold;
|
||||||
|
|
||||||
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
||||||
vm.availableLineItems,
|
vm.availableLineItems,
|
||||||
thresholdToUse
|
thresholdToUse
|
||||||
|
|
@ -399,10 +419,7 @@ export default {
|
||||||
return Object.assign({}, this.lineItems);
|
return Object.assign({}, this.lineItems);
|
||||||
},
|
},
|
||||||
isRecalibrationOnOrder() {
|
isRecalibrationOnOrder() {
|
||||||
return containsLineItemWithPartType(
|
return store.getters.isRecalibrationOnOrder;
|
||||||
partTypeStrings.RECALIBRATION,
|
|
||||||
this?.availableLineItems
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
isServicePackageDiscountOnOrder() {
|
isServicePackageDiscountOnOrder() {
|
||||||
return containsLineItemWithPartType(
|
return containsLineItemWithPartType(
|
||||||
|
|
@ -417,10 +434,7 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
shouldHideRecalibration() {
|
shouldHideRecalibration() {
|
||||||
return (
|
return store.getters.shouldHideRecalibration;
|
||||||
this.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)?.toLowerCase() ===
|
|
||||||
"true" && this.isRecalibrationOnOrder
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
showAfterpayBanner() {
|
showAfterpayBanner() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -438,35 +452,21 @@ export default {
|
||||||
},
|
},
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
const payment = store.getters.order.payment;
|
const payment = store.getters.order.payment;
|
||||||
const log = getQuerystringParameter(queryStrings.LOG);
|
|
||||||
if (eval(log)) {
|
// prettier-ignore
|
||||||
console.log("quote.vue pagePrereqs:");
|
{
|
||||||
console.log(
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
new Date() +
|
if (eval(log)) {
|
||||||
" store.getters.order.serviceLocation.zipCode: " +
|
console.log("------------- quote.vue pagePrereqs start -----------------");
|
||||||
store.getters.order.serviceLocation?.zipCode
|
console.log(new Date() + " store.getters.order.serviceLocation.zipCode: " + store.getters.order.serviceLocation?.zipCode);
|
||||||
);
|
console.log(new Date() +" store.getters.order.serviceLocation.zipCodeCtu: " + store.getters.order.serviceLocation?.zipCodeCtu);
|
||||||
console.log(
|
console.log(new Date() + " store.getters.order.damage.isRepair: " + store.getters.order.damage?.isRepair);
|
||||||
new Date() +
|
console.log(new Date() + " store.getters.order.lineItems?.glassParts: " + JSON.stringify(store.getters.order.lineItems?.glassParts));
|
||||||
" store.getters.order.serviceLocation.zipCodeCtu: " +
|
console.log(new Date() + " store.getters.order.payment.insuranceCoverage?.isVerified: " + payment?.insuranceCoverage?.isVerified);
|
||||||
store.getters.order.serviceLocation?.zipCodeCtu
|
console.log("------------- quote.vue pagePrereqs end -----------------");
|
||||||
);
|
}
|
||||||
console.log(
|
|
||||||
new Date() +
|
|
||||||
" store.getters.order.damage.isRepair: " +
|
|
||||||
store.getters.order.damage?.isRepair
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
new Date() +
|
|
||||||
" store.getters.order.lineItems?.glassParts: " +
|
|
||||||
JSON.stringify(store.getters.order.lineItems?.glassParts)
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
new Date() +
|
|
||||||
" store.getters.order.payment.insuranceCoverage?.isVerified: " +
|
|
||||||
payment?.insuranceCoverage?.isVerified
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
store.getters.order.serviceLocation.zipCode &&
|
store.getters.order.serviceLocation.zipCode &&
|
||||||
store.getters.order.serviceLocation.zipCodeCtu &&
|
store.getters.order.serviceLocation.zipCodeCtu &&
|
||||||
|
|
@ -579,15 +579,14 @@ export default {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const availablePackageNames = this.$refs.servicePackage.servicePackageAnswers;
|
const availablePackageNames = this.$refs.servicePackage?.servicePackageAnswers;
|
||||||
var eventLabel = "";
|
var eventLabel = "";
|
||||||
availablePackageNames?.forEach((tier) => {
|
availablePackageNames?.forEach((tier) => {
|
||||||
if (tier) {
|
if (tier) {
|
||||||
let lineItemsToPrice = this.availableLineItems;
|
let lineItemsToPrice = this.availableLineItems;
|
||||||
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
||||||
lineItemsToPrice = lineItemsToPrice?.filter((item) => {
|
lineItemsToPrice =
|
||||||
return item.partType != partTypeStrings.RECALIBRATION;
|
baseMixin.methods.filterOutRecalibration(lineItemsToPrice);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (this.isServicePackageDiscountOnOrder) {
|
if (this.isServicePackageDiscountOnOrder) {
|
||||||
lineItemsToPrice = lineItemsToPrice?.filter((item) => {
|
lineItemsToPrice = lineItemsToPrice?.filter((item) => {
|
||||||
|
|
@ -611,12 +610,7 @@ export default {
|
||||||
});
|
});
|
||||||
eventLabel = eventLabel.slice(0, -1);
|
eventLabel = eventLabel.slice(0, -1);
|
||||||
|
|
||||||
this.pushEventToGA(
|
this.pushEventToGA("quote", this.GaActions.SERVICE_PACKAGE_PRICE, eventLabel, true);
|
||||||
"quote",
|
|
||||||
this.GaActions.SERVICE_PACKAGE_PRICE,
|
|
||||||
eventLabel,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -40,7 +40,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -48,7 +48,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -58,7 +58,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -67,7 +67,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -75,7 +75,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -85,7 +85,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -94,7 +94,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -102,7 +102,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -112,7 +112,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -121,7 +121,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -129,7 +129,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -139,7 +139,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -148,7 +148,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -156,7 +156,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -166,7 +166,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -175,7 +175,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -183,7 +183,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -193,7 +193,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -202,7 +202,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -210,7 +210,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement glass</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -220,7 +220,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -229,7 +229,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -237,7 +237,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -247,7 +247,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Economy service",
|
HeaderText: "Economy service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText:
|
FooterText:
|
||||||
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
"{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}",
|
||||||
|
|
@ -256,7 +256,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Standard service",
|
HeaderText: "Standard service",
|
||||||
SubheaderText: "MOST POPULAR",
|
SubheaderText: "MOST POPULAR",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
"<ul><li>New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierTwo}{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierTwo}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
@ -264,7 +264,7 @@ export const mockProcessedCmsContent = {
|
||||||
HeaderText: "Premium service",
|
HeaderText: "Premium service",
|
||||||
SubheaderText: "",
|
SubheaderText: "",
|
||||||
BodyText:
|
BodyText:
|
||||||
"<ul><li>{if:custom:badCustomValue}DO NOT SHOW{end}New replacement windshield</li><li>Expert installation{if:custom:isRecalibrationOnOrder} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
"<ul><li>{if:custom:badCustomValue}DO NOT SHOW{end}New replacement windshield</li><li>Expert installation{if:custom:showRecalInServicePackages} and {textLink:EstimateRecalModal,recalibration}{end}</li><li>Nationwide lifetime warranty</li><li>{if:custom:frontWipersApplicableForTierThree}{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateFrontWiperModal,front wiper blades}{else}New {textLink:EstimateFrontWiperModal,wiper blades}{end}{end}</li><li>{if:custom:rearWiperApplicableForTierThree}New {textLink:EstimateRearWiperModal,rear wiper blade}{end}</li><li>{if:custom:rainDefenseApplicableForTierThree}{textLink:EstimateRainDefenseModal,Rain Defense}™ treatment{end}</li></ul>",
|
||||||
Image: "",
|
Image: "",
|
||||||
FooterText: "",
|
FooterText: "",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import {
|
||||||
containsLineItemWithPartType,
|
containsLineItemWithPartType,
|
||||||
findLineItemsWithPartType,
|
findLineItemsWithPartType,
|
||||||
} from "@/helpers/service-package-helper";
|
} from "@/helpers/service-package-helper";
|
||||||
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
|
|
@ -19,6 +20,18 @@ jest.mock("@/store", () => ({
|
||||||
dispatch: jest.fn(),
|
dispatch: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const mockExperimentSettings = experimentSettings;
|
||||||
|
|
||||||
|
jest.mock("@/mixins/experiment-mixin.js", () => ({
|
||||||
|
methods: {
|
||||||
|
getSettingValue(settingName) {
|
||||||
|
if (settingName === mockExperimentSettings.PROMO_ON_PACKAGE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe("service-package-question.vue", () => {
|
describe("service-package-question.vue", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
processedCmsContent = inputQuestionWidgetAnswers;
|
processedCmsContent = inputQuestionWidgetAnswers;
|
||||||
|
|
@ -162,6 +175,19 @@ describe("service-package-question.vue", () => {
|
||||||
wrapper.vm.servicePackageAnswers[0].buttonAuxillaryCopy.includes("As little as")
|
wrapper.vm.servicePackageAnswers[0].buttonAuxillaryCopy.includes("As little as")
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
it("should show service package discount when insurance is not selected", () => {
|
||||||
|
// Arrange
|
||||||
|
mockProps.isInsuranceSelected = false;
|
||||||
|
const wrapper = setupMocks({});
|
||||||
|
// Act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(
|
||||||
|
wrapper.vm.servicePackageAnswers[0].additionalButtonData.Text.includes(
|
||||||
|
"Special: Save $"
|
||||||
|
)
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
it("should return [] from nullSafeAvailableLineItems and not error out if availableLineItems is null", () => {
|
it("should return [] from nullSafeAvailableLineItems and not error out if availableLineItems is null", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
mockProps.availableLineItems = null;
|
mockProps.availableLineItems = null;
|
||||||
|
|
@ -476,6 +502,8 @@ describe("service-package-question.vue, matching business rules for package disp
|
||||||
mockProps.availableLineItems.push(driverFrontWiperLineItem);
|
mockProps.availableLineItems.push(driverFrontWiperLineItem);
|
||||||
mockProps.availableLineItems.push(passengerFrontWiperLineItem);
|
mockProps.availableLineItems.push(passengerFrontWiperLineItem);
|
||||||
mockProps.isRecalibrationOnOrder = true;
|
mockProps.isRecalibrationOnOrder = true;
|
||||||
|
mockProps.shouldHideRecalibration = false;
|
||||||
|
mockProps.showRecalInServicePackages = true;
|
||||||
Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]);
|
Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]);
|
||||||
const wrapper = setupMocks({
|
const wrapper = setupMocks({
|
||||||
mountOptionsMockData: {
|
mountOptionsMockData: {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import {
|
||||||
containsLineItemWithPartType,
|
containsLineItemWithPartType,
|
||||||
findLineItemsWithPartType,
|
findLineItemsWithPartType,
|
||||||
getPackageNameByType,
|
getPackageNameByType,
|
||||||
|
getDiscountPackageName,
|
||||||
} from "@/helpers/service-package-helper";
|
} from "@/helpers/service-package-helper";
|
||||||
import {
|
import {
|
||||||
getPromosThatMatchLineItemsOnOrder,
|
getPromosThatMatchLineItemsOnOrder,
|
||||||
|
|
@ -35,6 +36,9 @@ import {
|
||||||
getPromosWithAddableVaps,
|
getPromosWithAddableVaps,
|
||||||
getLineItemsThatMatchPromos,
|
getLineItemsThatMatchPromos,
|
||||||
} from "@/helpers/promotions-helper";
|
} from "@/helpers/promotions-helper";
|
||||||
|
import { containsRecalParts, getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||||
|
import experimentMixin from "@/mixins/experiment-mixin.js";
|
||||||
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "servicePackageQuestion",
|
name: "servicePackageQuestion",
|
||||||
|
|
@ -128,16 +132,22 @@ export default {
|
||||||
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName),
|
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName),
|
||||||
buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName),
|
buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName),
|
||||||
//The package supports service-package-discount if it has the text value in CMS
|
//The package supports service-package-discount if it has the text value in CMS
|
||||||
buttonAuxillaryCopy: this.getDiscountedPackagePriceString(
|
buttonAuxillaryCopy: this.isInsuranceSelected
|
||||||
answer.Name,
|
? this.getDiscountedPackagePriceString(answer.Name, false)
|
||||||
this.isServicePackageDiscountOnOrder && answer.Text != ""
|
: this.getDiscountedPackagePriceString(
|
||||||
),
|
answer.Name,
|
||||||
|
this.isServicePackageDiscountOnOrder &&
|
||||||
|
this.discountPackageNames == answer.Name
|
||||||
|
),
|
||||||
buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
|
buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
|
||||||
additionalButtonData: {
|
additionalButtonData: {
|
||||||
strikeThroughPrice: this.getPackagePriceString(answer.Name),
|
strikeThroughPrice: this.getPackagePriceString(answer.Name),
|
||||||
servicePackageDiscount:
|
servicePackageDiscount:
|
||||||
this.isServicePackageDiscountOnOrder && answer.Text != "",
|
this.isServicePackageDiscountOnOrder &&
|
||||||
Text: answer.Text + this.getServicePackageDiscountPrice(),
|
this.discountPackageNames == answer.Name,
|
||||||
|
Text: this.isInsuranceSelected
|
||||||
|
? false
|
||||||
|
: "Special: Save $" + this.getServicePackageDiscountPrice(),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
return modifiedAnswers;
|
return modifiedAnswers;
|
||||||
|
|
@ -148,6 +158,12 @@ export default {
|
||||||
this.nullSafeAvailableLineItems
|
this.nullSafeAvailableLineItems
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
discountPackageNames() {
|
||||||
|
const discountServicePackage = experimentMixin.methods.getSettingValue(
|
||||||
|
experimentSettings.PROMO_ON_PACKAGE
|
||||||
|
);
|
||||||
|
return getDiscountPackageName(discountServicePackage);
|
||||||
|
},
|
||||||
frontWipersApplicableForTierTwo() {
|
frontWipersApplicableForTierTwo() {
|
||||||
return shouldFrontWipersBeAvailable(
|
return shouldFrontWipersBeAvailable(
|
||||||
this.glassToReplace,
|
this.glassToReplace,
|
||||||
|
|
@ -200,6 +216,9 @@ export default {
|
||||||
this.nullSafeAvailableLineItems
|
this.nullSafeAvailableLineItems
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
showRecalInServicePackages() {
|
||||||
|
return this.isRecalibrationOnOrder && !this.shouldHideRecalibration;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
processIfStatements,
|
processIfStatements,
|
||||||
|
|
@ -239,9 +258,7 @@ export default {
|
||||||
let lineItemsToPrice = [...this.nullSafeAvailableLineItems];
|
let lineItemsToPrice = [...this.nullSafeAvailableLineItems];
|
||||||
|
|
||||||
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
||||||
lineItemsToPrice = lineItemsToPrice.filter((item) => {
|
lineItemsToPrice = getItemsWithoutRecalParts(lineItemsToPrice);
|
||||||
return item.partType != partTypeStrings.RECALIBRATION;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove service package discount part
|
//remove service package discount part
|
||||||
|
|
@ -358,8 +375,8 @@ export default {
|
||||||
},
|
},
|
||||||
getCustomValueFromString(str) {
|
getCustomValueFromString(str) {
|
||||||
switch (str) {
|
switch (str) {
|
||||||
case "isRecalibrationOnOrder":
|
case "showRecalInServicePackages":
|
||||||
return this.isRecalibrationOnOrder;
|
return this.showRecalInServicePackages;
|
||||||
case "frontWipersApplicableForTierTwo":
|
case "frontWipersApplicableForTierTwo":
|
||||||
return this.frontWipersApplicableForTierTwo;
|
return this.frontWipersApplicableForTierTwo;
|
||||||
case "rearWiperApplicableForTierTwo":
|
case "rearWiperApplicableForTierTwo":
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
|
||||||
:class="[this.additionalButtonData.Text ? 'discount-text' : '']"
|
|
||||||
v-if="this.additionalButtonData.servicePackageDiscount"
|
|
||||||
v-html="this.additionalButtonData.Text"></div>
|
|
||||||
<baseInputButton v-bind="$props" @buttonClicked="handleAnswerChange" v-model="selectedValue">
|
<baseInputButton v-bind="$props" @buttonClicked="handleAnswerChange" v-model="selectedValue">
|
||||||
<div
|
<div
|
||||||
class="package-label"
|
class="package-label"
|
||||||
:class="[
|
:class="[this.buttonLabelSubCopy ? 'has-subheader' : '']"
|
||||||
this.buttonLabelSubCopy ? 'has-subheader' : '',
|
|
||||||
this.additionalButtonData.servicePackageDiscount ? 'has-text' : '',
|
|
||||||
]"
|
|
||||||
for="testradio">
|
for="testradio">
|
||||||
<div class="package-specs">
|
<div class="package-specs">
|
||||||
<div v-if="this.additionalButtonData.servicePackageDiscount" class="row">
|
<div v-if="this.additionalButtonData.servicePackageDiscount" class="row">
|
||||||
|
|
@ -78,10 +71,19 @@
|
||||||
</ul>
|
</ul>
|
||||||
<!-- End of body text parsing -->
|
<!-- End of body text parsing -->
|
||||||
<div
|
<div
|
||||||
class="package-footer fw-bold caption ms-n6"
|
class="package-footer fw-bold caption ms-n6 mt-4"
|
||||||
v-if="this.buttonFooterCopy"
|
v-if="this.buttonFooterCopy"
|
||||||
v-html="this.buttonFooterCopy"></div>
|
v-html="this.buttonFooterCopy"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
this.additionalButtonData.servicePackageDiscount &&
|
||||||
|
this.additionalButtonData.Text
|
||||||
|
"
|
||||||
|
class="special-save-box">
|
||||||
|
<span v-html="this.additionalButtonData.Text"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</baseInputButton>
|
</baseInputButton>
|
||||||
|
|
@ -138,25 +140,18 @@ export default {
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.package-main {
|
.package-main {
|
||||||
.package-wrapper {
|
.package-wrapper {
|
||||||
margin: 0.5rem 0;
|
margin: 1rem 0;
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
margin: 1rem 0.5rem;
|
margin: 1rem 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-self: flex-end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: block;
|
display: block;
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 336px;
|
height: 100%;
|
||||||
}
|
|
||||||
//Unique breakpoint for this page only to accommodate price spacing issues
|
|
||||||
//from use of position: absolute on .service-package-discount (per Design Team request)
|
|
||||||
@media only screen and (min-width: 860px) {
|
|
||||||
display: flex;
|
|
||||||
min-height: 276px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,19 +174,16 @@ export default {
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: 60px;
|
min-height: 60px;
|
||||||
max-height: 100px;
|
max-height: 126px;
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
|
padding-bottom: 3rem;
|
||||||
}
|
}
|
||||||
transition: max-height 0.25s ease-in;
|
transition: max-height 0.25s ease-in;
|
||||||
|
|
||||||
&.has-subheader {
|
&.has-subheader {
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
}
|
}
|
||||||
&.has-text {
|
|
||||||
border-radius: 0 0 0.5rem 0.5rem;
|
|
||||||
border: 1px solid $green;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: "";
|
content: "";
|
||||||
|
|
@ -245,6 +237,9 @@ export default {
|
||||||
background-color: $blue-100;
|
background-color: $blue-100;
|
||||||
border: 1px solid $blue;
|
border: 1px solid $blue;
|
||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
|
.special-save-box {
|
||||||
|
background-color: $green-200;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+ .package-label {
|
+ .package-label {
|
||||||
&:before {
|
&:before {
|
||||||
|
|
@ -294,8 +289,8 @@ export default {
|
||||||
bottom: 0.75rem;
|
bottom: 0.75rem;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
margin-left: 1.25rem;
|
||||||
font-size: 1.125rem;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
span.strikethrough-price {
|
span.strikethrough-price {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
|
|
@ -316,28 +311,32 @@ export default {
|
||||||
&.service-package-discount {
|
&.service-package-discount {
|
||||||
color: $green;
|
color: $green;
|
||||||
text-align: end;
|
text-align: end;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
font-size: 13px;
|
font-size: 0.875rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
div.strikethrough-discount-price {
|
div.strikethrough-discount-price {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
margin-right: 0;
|
margin-right: 0.5rem;
|
||||||
font-weight: 400;
|
font-weight: 600;
|
||||||
font-size: 0.875rem;
|
font-size: 0.75rem;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
color: $gray-500;
|
color: $gray-550;
|
||||||
padding-right: 2px;
|
@include media-breakpoint-up(md) {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
div.discount-price {
|
div.discount-price {
|
||||||
color: $green;
|
color: $green;
|
||||||
font-weight: 600;
|
|
||||||
font-size: 1.625rem;
|
|
||||||
}
|
}
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0.75rem;
|
bottom: 0.75rem;
|
||||||
left: 0;
|
left: 0.5rem;
|
||||||
width: 100%;
|
display: flex;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -388,6 +387,21 @@ export default {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: 0.75px;
|
letter-spacing: 0.75px;
|
||||||
}
|
}
|
||||||
|
.special-save-box {
|
||||||
|
background-color: $green-100;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: auto;
|
||||||
|
margin-left: -2rem;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
span {
|
||||||
|
color: $green;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ import timeSlotModalQuestion from "./time-slot-modal-question/time-slot-modal-qu
|
||||||
import textBlock from "@/digital-components/text-block/text-block";
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
|
@ -305,6 +307,22 @@ export default {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
const serviceLocation = store.getters.order.serviceLocation;
|
const serviceLocation = store.getters.order.serviceLocation;
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
{
|
||||||
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
|
if (eval(log)) {
|
||||||
|
console.log("------------- schedule.vue pagePrereqs start -----------------");
|
||||||
|
console.log(new Date() + " store.getters.order.serviceLocation.zipCode: " + serviceLocation.zipCode);
|
||||||
|
console.log(new Date() + " store.getters.order.serviceLocation.zipCodeCtu: " + serviceLocation.zipCodeCtu);
|
||||||
|
console.log(new Date() + " store.getters.order.serviceLocation.appointmentType: " + serviceLocation.appointmentType);
|
||||||
|
console.log(new Date() + " store.getters.order.serviceLocation.provider.providerNumber: " + serviceLocation.provider.providerNumber);
|
||||||
|
console.log(new Date() + " store.getters.payment.isInsurance: " + store.getters.payment?.isInsurance);
|
||||||
|
console.log(new Date() + " store.getters.order.damage.isRepair: " + store.getters.order.damage.isRepair);
|
||||||
|
console.log(new Date() + " store.getters.order.lineItems.glassParts: " + JSON.stringify(store.getters.order.lineItems?.glassParts));
|
||||||
|
console.log("------------- schedule.vue pagePrereqs end -------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const serviceLocationPreReqs =
|
const serviceLocationPreReqs =
|
||||||
serviceLocation.zipCode &&
|
serviceLocation.zipCode &&
|
||||||
serviceLocation.zipCodeCtu &&
|
serviceLocation.zipCodeCtu &&
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,15 @@
|
||||||
:aria-label="buttonLabel"
|
:aria-label="buttonLabel"
|
||||||
class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4">
|
class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4">
|
||||||
<div class="row-one">
|
<div class="row-one">
|
||||||
<span class="m-0 button-label-copy" :class="textPosition">{{
|
<span class="m-0 button-label-copy text-truncate" :class="textPosition">{{
|
||||||
buttonLabel
|
buttonLabel
|
||||||
}}</span>
|
}}</span>
|
||||||
<span class="m-0 caption ms-1" :class="textPosition">{{
|
<span class="m-0 caption mx-1 text-nowrap" :class="textPosition">{{
|
||||||
buttonLabelSubCopy
|
buttonLabelSubCopy
|
||||||
}}</span>
|
}}</span>
|
||||||
<div
|
<div
|
||||||
v-if="displayAvailabilityIndicators"
|
v-if="displayAvailabilityIndicators"
|
||||||
class="availability-indicator rounded-pill"
|
class="availability-indicator rounded-pill text-nowrap"
|
||||||
:class="availabilityRatingClass">
|
:class="availabilityRatingClass">
|
||||||
<div
|
<div
|
||||||
v-if="!isLoaderDisplayed"
|
v-if="!isLoaderDisplayed"
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,10 @@ export default {
|
||||||
if (logFirstShopsDisplayed) {
|
if (logFirstShopsDisplayed) {
|
||||||
gaAction = this.GaActions.SHOPS_FIRST_DISPLAYED;
|
gaAction = this.GaActions.SHOPS_FIRST_DISPLAYED;
|
||||||
}
|
}
|
||||||
if (this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP) {
|
if (
|
||||||
|
this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP ||
|
||||||
|
this.selectedAppointmentType === AppointmentTypeStrings.DROP_OFF
|
||||||
|
) {
|
||||||
var shops = mappedData.map((shop) => {
|
var shops = mappedData.map((shop) => {
|
||||||
if (shop.value.length > 5 && shop.value.startsWith("00")) {
|
if (shop.value.length > 5 && shop.value.startsWith("00")) {
|
||||||
return shop.value.substring(1);
|
return shop.value.substring(1);
|
||||||
|
|
@ -179,7 +182,7 @@ export default {
|
||||||
this.pushEventToGA(
|
this.pushEventToGA(
|
||||||
this.GaCategories.SERVICE_LOCATION,
|
this.GaCategories.SERVICE_LOCATION,
|
||||||
gaAction,
|
gaAction,
|
||||||
shops.join("/"),
|
shops.join(","),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,7 @@ function setupMocks({ customMountOptions, customZipQuery, customZipDataResponse
|
||||||
}),
|
}),
|
||||||
setCmsContent: jest.fn(),
|
setCmsContent: jest.fn(),
|
||||||
navigateForwardWithSingleCarMatch: jest.fn(),
|
navigateForwardWithSingleCarMatch: jest.fn(),
|
||||||
|
getAndSaveBillToAccountNumber: jest.fn(),
|
||||||
getZipCodeData: jest.fn().mockImplementation(() => {
|
getZipCodeData: jest.fn().mockImplementation(() => {
|
||||||
if (customZipDataResponse) {
|
if (customZipDataResponse) {
|
||||||
return customZipDataResponse;
|
return customZipDataResponse;
|
||||||
|
|
|
||||||
|
|
@ -132,11 +132,24 @@ export default {
|
||||||
|
|
||||||
next(async (vm) => {
|
next(async (vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
|
||||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||||
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
|
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
vm.forwardButtonAction();
|
vm.forwardButtonAction();
|
||||||
} else {
|
} else {
|
||||||
|
if (store.getters.externalParameterServiceZip.zipCode) {
|
||||||
|
await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
zipCode: store.getters.externalParameterServiceZip.zipCode,
|
||||||
|
state: null,
|
||||||
|
zipCodeCtu: null,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +198,7 @@ export default {
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
await this.getAndSaveBillToAccountNumber();
|
||||||
|
|
||||||
if (!zipCodeData.isValid) {
|
if (!zipCodeData.isValid) {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,17 @@ export default {
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
vm.forwardButtonAction();
|
vm.forwardButtonAction();
|
||||||
} else {
|
} else {
|
||||||
|
if (store.getters.externalParameterServiceZip.zipCode) {
|
||||||
|
await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
zipCode: store.getters.externalParameterServiceZip.zipCode,
|
||||||
|
state: null,
|
||||||
|
zipCodeCtu: null,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,9 @@ import store from "@/store";
|
||||||
import { storeActions } from "@/constants/store-actions.js";
|
import { storeActions } from "@/constants/store-actions.js";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
import { applicationConfig } from "../../constants/application-config";
|
||||||
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
|
|
||||||
//define validation rules
|
//define validation rules
|
||||||
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
|
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
|
||||||
|
|
@ -127,6 +130,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
|
if (eval(log)) {
|
||||||
|
console.log("----------------- applicationConfig start -----------------");
|
||||||
|
console.log(new Date() + JSON.stringify(applicationConfig));
|
||||||
|
console.log("----------------- applicationConfig end -----------------");
|
||||||
|
}
|
||||||
// Call APIs
|
// Call APIs
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
const experimentForLogging = store.getters.applicationUser.experiments.find(
|
const experimentForLogging = store.getters.applicationUser.experiments.find(
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,7 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await this.getAndSaveBillToAccountNumber();
|
||||||
return await this.navigateForward();
|
return await this.navigateForward();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -446,6 +446,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pushToDataLayerIfDefined({
|
pushToDataLayerIfDefined({
|
||||||
|
event: "productArray",
|
||||||
productArray: {
|
productArray: {
|
||||||
coupon: coupon,
|
coupon: coupon,
|
||||||
discount: discount.toFixed(2),
|
discount: discount.toFixed(2),
|
||||||
|
|
@ -544,7 +545,11 @@ export default {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pushToDataLayerIfDefined({
|
pushToDataLayerIfDefined({
|
||||||
eCommerceCart: { products: combinedLineItems, subTotal: parseInt(subtotal) },
|
event: "eCommerceCart",
|
||||||
|
eCommerceCart: {
|
||||||
|
products: combinedLineItems,
|
||||||
|
subTotal: parseInt(subtotal),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -632,6 +637,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pushToDataLayerIfDefined({
|
pushToDataLayerIfDefined({
|
||||||
|
event: "commissionJunctionGtmData",
|
||||||
commissionJunctionGtmData: {
|
commissionJunctionGtmData: {
|
||||||
cj_commission_junction_event: cjEvent,
|
cj_commission_junction_event: cjEvent,
|
||||||
cj_referral_sequence_number: refSequenceNum,
|
cj_referral_sequence_number: refSequenceNum,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { queryStrings } from "@/constants/query-strings";
|
||||||
import { dynamicStrings } from "@/constants/dynamic-strings";
|
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||||
import { partTypeStrings } from "../constants/part-type-strings";
|
import { partTypeStrings } from "../constants/part-type-strings";
|
||||||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||||
|
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -82,7 +83,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getTierOnePackagePrice(lineItems) {
|
getTierOnePackagePrice(lineItems) {
|
||||||
let lineItemsToPrice = lineItems.filter((lineItem) => {
|
let lineItemsToPrice = lineItems?.filter((lineItem) => {
|
||||||
return (
|
return (
|
||||||
lineItem.partType != partTypeStrings.FRONT_WIPER &&
|
lineItem.partType != partTypeStrings.FRONT_WIPER &&
|
||||||
lineItem.partType != partTypeStrings.REAR_WIPER &&
|
lineItem.partType != partTypeStrings.REAR_WIPER &&
|
||||||
|
|
@ -94,23 +95,20 @@ export default {
|
||||||
return totalPrice;
|
return totalPrice;
|
||||||
},
|
},
|
||||||
filterOutFees(lineItems) {
|
filterOutFees(lineItems) {
|
||||||
const filteredLineItems = lineItems.filter((item) => {
|
const filteredLineItems = lineItems?.filter((item) => {
|
||||||
return (
|
return (
|
||||||
(!item.partType.includes("FEE") && !item.partType.includes("EARLY BIRD")) ||
|
(!item?.partType?.includes("FEE") && !item?.partType?.includes("EARLY BIRD")) ||
|
||||||
(item.partType === "REPAIR FEE" && item.partNumber != "SUPPLIES-REPAIR")
|
(item?.partType === "REPAIR FEE" && item?.partNumber != "SUPPLIES-REPAIR")
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return filteredLineItems;
|
return filteredLineItems;
|
||||||
},
|
},
|
||||||
filterOutRecalibration(lineItems) {
|
filterOutRecalibration(lineItems) {
|
||||||
const filteredLineItems = lineItems.filter((item) => {
|
return getItemsWithoutRecalParts(lineItems);
|
||||||
return !item.partType.includes(partTypeStrings.RECALIBRATION);
|
|
||||||
});
|
|
||||||
return filteredLineItems;
|
|
||||||
},
|
},
|
||||||
getTotalPriceOfAllLineItemsAndChildParts(lineItems, includeTax) {
|
getTotalPriceOfAllLineItemsAndChildParts(lineItems, includeTax) {
|
||||||
let totalPrice = 0;
|
let totalPrice = 0;
|
||||||
lineItems.forEach((lineItem) => {
|
lineItems?.forEach((lineItem) => {
|
||||||
totalPrice += this.getTotalLineItemPrice(lineItem, includeTax);
|
totalPrice += this.getTotalLineItemPrice(lineItem, includeTax);
|
||||||
if (lineItem.childParts) {
|
if (lineItem.childParts) {
|
||||||
totalPrice += this.getTotalPriceOfAllLineItemsAndChildParts(
|
totalPrice += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
|
|
@ -141,41 +139,43 @@ export default {
|
||||||
},
|
},
|
||||||
getAmountDue(lineItems, includeTax = true) {
|
getAmountDue(lineItems, includeTax = true) {
|
||||||
var amountDue = 0;
|
var amountDue = 0;
|
||||||
if (lineItems.glassParts) {
|
if (lineItems?.glassParts) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.glassParts,
|
lineItems.glassParts,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (lineItems.supportingItems) {
|
|
||||||
|
if (lineItems?.supportingItems) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.supportingItems,
|
lineItems.supportingItems,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (lineItems.vaps) {
|
|
||||||
|
const order = this.hasSubmittedOrder() ? this.getSubmittedOrder() : store.getters.order;
|
||||||
|
if (
|
||||||
|
store.getters.coverageIsVerified &&
|
||||||
|
!order.policy.isNoComp &&
|
||||||
|
!order.policy.isItac
|
||||||
|
) {
|
||||||
|
amountDue = order.policy.currentDeductible;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineItems?.vaps) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.vaps,
|
lineItems.vaps,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (lineItems.promos) {
|
|
||||||
|
if (lineItems?.promos) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.promos,
|
lineItems.promos,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const order = this.hasSubmittedOrder() ? this.getSubmittedOrder() : store.getters.order;
|
|
||||||
|
|
||||||
if (
|
|
||||||
order.payment.insuranceCoverage.isVerified &&
|
|
||||||
!order.policy.isNoComp &&
|
|
||||||
!order.policy.isItac
|
|
||||||
) {
|
|
||||||
amountDue += order.policy.currentDeductible;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((amountDue * 100) / 100).toFixed(2);
|
return ((amountDue * 100) / 100).toFixed(2);
|
||||||
},
|
},
|
||||||
getSubTotal(lineItems) {
|
getSubTotal(lineItems) {
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ describe("baseMixin.js", () => {
|
||||||
promos: [],
|
promos: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const payment = { insuranceCoverage: { isVerified: true } };
|
const payment = { insuranceCoverage: { isVerified: false } };
|
||||||
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
||||||
|
|
||||||
store.getters = {
|
store.getters = {
|
||||||
|
|
@ -190,7 +190,7 @@ describe("baseMixin.js", () => {
|
||||||
|
|
||||||
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
||||||
|
|
||||||
expect(amtDue).toEqual("303.00");
|
expect(amtDue).toEqual("53.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getAmountDue should function with a submitted order", () => {
|
test("getAmountDue should function with a submitted order", () => {
|
||||||
|
|
@ -223,7 +223,7 @@ describe("baseMixin.js", () => {
|
||||||
promos: [],
|
promos: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const payment = { insuranceCoverage: { isVerified: true } };
|
const payment = { insuranceCoverage: { isVerified: false } };
|
||||||
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
||||||
|
|
||||||
mixIn.methods.hasSubmittedOrder = jest.fn().mockReturnValue(true);
|
mixIn.methods.hasSubmittedOrder = jest.fn().mockReturnValue(true);
|
||||||
|
|
@ -240,7 +240,7 @@ describe("baseMixin.js", () => {
|
||||||
|
|
||||||
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
||||||
|
|
||||||
expect(amtDue).toEqual("303.00");
|
expect(amtDue).toEqual("53.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getAmountDue for cash should sum lineitems", () => {
|
test("getAmountDue for cash should sum lineitems", () => {
|
||||||
|
|
|
||||||
|
|
@ -450,7 +450,17 @@ export default {
|
||||||
const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);
|
const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);
|
||||||
|
|
||||||
// save to store lineItems.glassParts
|
// save to store lineItems.glassParts
|
||||||
self.dispatchStoreAction(storeActions.SAVE_GLASS_PARTS, collectedGlassParts, false);
|
await self.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_GLASS_PARTS,
|
||||||
|
collectedGlassParts,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
await self.dispatchStoreActionWithLogging(
|
||||||
|
storeActions.GET_RECAL_PARTS_AND_SAVE_TO_LINE_ITEMS,
|
||||||
|
null,
|
||||||
|
currentPage
|
||||||
|
);
|
||||||
|
|
||||||
const payment = store.getters.payment;
|
const payment = store.getters.payment;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,5 +42,19 @@ export default {
|
||||||
};
|
};
|
||||||
return vinLookupMethods[vinSelection] || null;
|
return vinLookupMethods[vinSelection] || null;
|
||||||
},
|
},
|
||||||
|
async getAndSaveBillToAccountNumber() {
|
||||||
|
const pageName = this.$options?.name;
|
||||||
|
const billToAccountNumber = await this.dispatchStoreActionWithLogging(
|
||||||
|
storeActions.GET_BILL_TO_ACCOUNT_NUMBER,
|
||||||
|
{},
|
||||||
|
pageName,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
await this.dispatchStoreAction(
|
||||||
|
this.storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
||||||
|
billToAccountNumber,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
|
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||||
import { fmgPageValues, funnelStartPageName } from "@/router/router-constants/fmgPage-values";
|
import { fmgPageValues, funnelStartPageName } from "@/router/router-constants/fmgPage-values";
|
||||||
|
import { externalParameterStatus } from "@/constants/external-parameters";
|
||||||
|
|
||||||
// Heritage integration
|
// Heritage integration
|
||||||
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
|
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
|
||||||
|
|
@ -96,8 +97,6 @@ const routes = [
|
||||||
);
|
);
|
||||||
updateOrCreateFunnelCookie();
|
updateOrCreateFunnelCookie();
|
||||||
}
|
}
|
||||||
//Update external parameter state
|
|
||||||
updateExternalParameterState();
|
|
||||||
|
|
||||||
//Affiliate Cookies
|
//Affiliate Cookies
|
||||||
const affiliateCookies = getAffiliateCookies();
|
const affiliateCookies = getAffiliateCookies();
|
||||||
|
|
@ -114,6 +113,17 @@ const routes = [
|
||||||
to.query.fmgPage
|
to.query.fmgPage
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Update external parameter state
|
||||||
|
updateExternalParameterState();
|
||||||
|
|
||||||
|
// clear part related state because heritage selected a new vehicle
|
||||||
|
if (
|
||||||
|
to.query.fmgPage === fmgPageValues.VEHICLE &&
|
||||||
|
eval(getFunnelCookie()?.HasDelayedClaimRegistration)
|
||||||
|
) {
|
||||||
|
store.commit(storeMutations.RESET_GLASS_PARTS_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
const pageToRedirectTo = await getPageToRouteExistingOrderTo(to);
|
const pageToRedirectTo = await getPageToRouteExistingOrderTo(to);
|
||||||
|
|
||||||
// This logic may determine that the user should be sent to heritage -- if so, do that here.
|
// This logic may determine that the user should be sent to heritage -- if so, do that here.
|
||||||
|
|
@ -264,7 +274,10 @@ router.beforeEach(async (to, from, next) => {
|
||||||
);
|
);
|
||||||
// If alert event is on the bus, then display the alert
|
// If alert event is on the bus, then display the alert
|
||||||
if (alertEvent !== undefined || unknownAlertEvent !== undefined) {
|
if (alertEvent !== undefined || unknownAlertEvent !== undefined) {
|
||||||
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, false);
|
store.commit(
|
||||||
|
storeMutations.UPDATE_IS_EXTERNAL_PARAMETER,
|
||||||
|
externalParameterStatus.INACTIVE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fromPaymentToConfirmation workaround for navigating from an iframe but
|
// fromPaymentToConfirmation workaround for navigating from an iframe but
|
||||||
|
|
@ -315,12 +328,12 @@ router.afterEach(async (to, from) => {
|
||||||
analyticsMixin.methods.pushOrderToDataLayer();
|
analyticsMixin.methods.pushOrderToDataLayer();
|
||||||
|
|
||||||
if (to.query.fmgPage == fmgPageValues.CONFIRMATION) {
|
if (to.query.fmgPage == fmgPageValues.CONFIRMATION) {
|
||||||
//Push Product Array to Data Layer
|
|
||||||
analyticsMixin.methods.pushProductArrayToDataLayer();
|
|
||||||
|
|
||||||
//Push Ecommerce Cart to Data Layer
|
//Push Ecommerce Cart to Data Layer
|
||||||
analyticsMixin.methods.pushECommerceCartToDataLayer();
|
analyticsMixin.methods.pushECommerceCartToDataLayer();
|
||||||
|
|
||||||
|
//Push Product Array to Data Layer
|
||||||
|
analyticsMixin.methods.pushProductArrayToDataLayer();
|
||||||
|
|
||||||
//Push Commission Junction Gtm Data To Data Layer
|
//Push Commission Junction Gtm Data To Data Layer
|
||||||
analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer();
|
analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer();
|
||||||
}
|
}
|
||||||
|
|
@ -540,7 +553,7 @@ async function DisplayPageError() {
|
||||||
type: globalEventTypes.Danger,
|
type: globalEventTypes.Danger,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, false);
|
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.INACTIVE);
|
||||||
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||||
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
|
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
|
||||||
|
|
||||||
|
|
@ -621,6 +634,22 @@ function getRedirectedStartPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateExternalParameterState() {
|
function updateExternalParameterState() {
|
||||||
|
// if there is an existing external parameter state then they have already been through from an external source(LeadGen) and
|
||||||
|
// are returning. clear out prior related things that need to be selected again like parts and damage type.
|
||||||
|
if (
|
||||||
|
store.getters.externalParameterState?.isExternalParameter ==
|
||||||
|
externalParameterStatus.INACTIVE
|
||||||
|
) {
|
||||||
|
store.dispatch(storeActions.RESET_VEHICLE_STATE_AND_DEPENDENCIES);
|
||||||
|
store.dispatch(storeActions.SAVE_SERVICE_ZIP_CODE_INFO, {
|
||||||
|
state: null,
|
||||||
|
zipCode: null,
|
||||||
|
zipCodeCtu: null,
|
||||||
|
});
|
||||||
|
store.dispatch(storeActions.SAVE_EMAIL, null);
|
||||||
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
|
}
|
||||||
|
|
||||||
const externalParameterYear = getQuerystringParameter(queryStrings.VEHICLE_YEAR);
|
const externalParameterYear = getQuerystringParameter(queryStrings.VEHICLE_YEAR);
|
||||||
const externalParameterMake = getQuerystringParameter(queryStrings.VEHICLE_MAKE);
|
const externalParameterMake = getQuerystringParameter(queryStrings.VEHICLE_MAKE);
|
||||||
const externalParameterModel = getQuerystringParameter(queryStrings.VEHICLE_MODEL);
|
const externalParameterModel = getQuerystringParameter(queryStrings.VEHICLE_MODEL);
|
||||||
|
|
@ -639,7 +668,7 @@ function updateExternalParameterState() {
|
||||||
externalParameterModel &&
|
externalParameterModel &&
|
||||||
externalParameterStyle
|
externalParameterStyle
|
||||||
) {
|
) {
|
||||||
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, true);
|
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.ACTIVE);
|
||||||
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_YEAR, externalParameterYear);
|
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_YEAR, externalParameterYear);
|
||||||
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MAKE, externalParameterMake);
|
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MAKE, externalParameterMake);
|
||||||
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MODEL, externalParameterModel);
|
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MODEL, externalParameterModel);
|
||||||
|
|
@ -662,8 +691,10 @@ function updateExternalParameterState() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (externalParameterZipCode && externalParameterEmail) {
|
if (externalParameterZipCode) {
|
||||||
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode);
|
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode);
|
||||||
|
}
|
||||||
|
if (externalParameterEmail) {
|
||||||
store.commit(
|
store.commit(
|
||||||
storeMutations.UPDATE_EXTERNAL_PARAMETER_EMAIL_ADDRESS,
|
storeMutations.UPDATE_EXTERNAL_PARAMETER_EMAIL_ADDRESS,
|
||||||
externalParameterEmail
|
externalParameterEmail
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,15 @@ import sharedMutations from "./vuex-shared-mutations/vuexSharedMutations";
|
||||||
import {
|
import {
|
||||||
coverageStatus,
|
coverageStatus,
|
||||||
coverageStatusValue,
|
coverageStatusValue,
|
||||||
|
coverageStatusEnum,
|
||||||
coverageType,
|
coverageType,
|
||||||
coverageTypeValue,
|
coverageTypeValue,
|
||||||
|
coverageTypeEnum,
|
||||||
} from "@/constants/insurance";
|
} from "@/constants/insurance";
|
||||||
|
import { containsRecalParts, getTopLevelPartsWithRecal } from "@/helpers/recal-helper";
|
||||||
|
import { externalParameterStatus } from "@/constants/external-parameters";
|
||||||
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
|
import experimentMixin from "@/mixins/experiment-mixin.js";
|
||||||
|
|
||||||
// Export State
|
// Export State
|
||||||
const getDefaultState = () => {
|
const getDefaultState = () => {
|
||||||
|
|
@ -473,10 +479,6 @@ export const mutations = {
|
||||||
externalParameterState.quote.servicePackage = servicePackage;
|
externalParameterState.quote.servicePackage = servicePackage;
|
||||||
saveExternalParameterState(externalParameterState);
|
saveExternalParameterState(externalParameterState);
|
||||||
},
|
},
|
||||||
updateExternalParameterSource(state, source) {
|
|
||||||
externalParameterState.source = source;
|
|
||||||
saveExternalParameterState(externalParameterState);
|
|
||||||
},
|
|
||||||
//RESET ExternalParameter MUTATIONS
|
//RESET ExternalParameter MUTATIONS
|
||||||
resetExternalParameterVehicleState(state) {
|
resetExternalParameterVehicleState(state) {
|
||||||
externalParameterState.vehicle.year = null;
|
externalParameterState.vehicle.year = null;
|
||||||
|
|
@ -503,16 +505,11 @@ export const mutations = {
|
||||||
saveExternalParameterState(externalParameterState);
|
saveExternalParameterState(externalParameterState);
|
||||||
},
|
},
|
||||||
resetExternalParameterQuoteState(state) {
|
resetExternalParameterQuoteState(state) {
|
||||||
externalParameterState.quote.isInsurance = null;
|
|
||||||
externalParameterState.quote.servicePackage = null;
|
externalParameterState.quote.servicePackage = null;
|
||||||
saveExternalParameterState(externalParameterState);
|
saveExternalParameterState(externalParameterState);
|
||||||
},
|
},
|
||||||
resetExternalParameterSourceState(state) {
|
|
||||||
externalParameterState.source = null;
|
|
||||||
saveExternalParameterState(externalParameterState);
|
|
||||||
},
|
|
||||||
resetIsExternalParameter(state) {
|
resetIsExternalParameter(state) {
|
||||||
externalParameterState.isExternalParameter = null;
|
externalParameterState.isExternalParameter = externalParameterStatus.INACTIVE;
|
||||||
saveExternalParameterState(externalParameterState);
|
saveExternalParameterState(externalParameterState);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -682,7 +679,17 @@ export const mutations = {
|
||||||
sessionInformation.order.serviceLocation.provider?.address?.zipCodeCtu;
|
sessionInformation.order.serviceLocation.provider?.address?.zipCodeCtu;
|
||||||
state.order.serviceLocation.techNotes = sessionInformation.order.serviceLocation.techNotes;
|
state.order.serviceLocation.techNotes = sessionInformation.order.serviceLocation.techNotes;
|
||||||
|
|
||||||
state.order.payment.isInsurance = sessionInformation.order.payment.isInsurance;
|
// if we're loading a session and we do not have a provider number yet, then set isInsurance to null so that
|
||||||
|
// a service package is not selected by default on the quote page.
|
||||||
|
if (
|
||||||
|
!sessionInformation.order.payment.isInsurance &&
|
||||||
|
!sessionInformation.order.serviceLocation.provider?.providerNumber
|
||||||
|
) {
|
||||||
|
state.order.payment.isInsurance = null;
|
||||||
|
} else {
|
||||||
|
state.order.payment.isInsurance = sessionInformation.order.payment.isInsurance;
|
||||||
|
}
|
||||||
|
|
||||||
state.order.payment.insuranceCoverage.isVerified =
|
state.order.payment.insuranceCoverage.isVerified =
|
||||||
coverageStatusValue(sessionInformation?.order.insuranceCoverage.coverageStatus) ===
|
coverageStatusValue(sessionInformation?.order.insuranceCoverage.coverageStatus) ===
|
||||||
coverageStatus.VERIFIED
|
coverageStatus.VERIFIED
|
||||||
|
|
@ -772,6 +779,24 @@ export const getters = {
|
||||||
);
|
);
|
||||||
return !!nonWindshieldItems?.length;
|
return !!nonWindshieldItems?.length;
|
||||||
},
|
},
|
||||||
|
coverageIsVerified: (state) => {
|
||||||
|
let order;
|
||||||
|
if (window.sessionStorage.getItem("submittedOrder") !== null) {
|
||||||
|
order = JSON.parse(window.sessionStorage.getItem("submittedOrder"));
|
||||||
|
} else {
|
||||||
|
order = state.order;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
order.payment?.insuranceCoverage?.isVerified &&
|
||||||
|
order.policy?.currentDeductible != 9999 &&
|
||||||
|
order.policy?.currentDeductible != 7777
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
isMobileAppointment: (state) => {
|
isMobileAppointment: (state) => {
|
||||||
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
||||||
},
|
},
|
||||||
|
|
@ -793,6 +818,13 @@ export const getters = {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
shouldHideRecalibration: (state) => {
|
||||||
|
return (
|
||||||
|
experimentMixin.methods
|
||||||
|
.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)
|
||||||
|
?.toLowerCase() === "true" && getters.isRecalibrationOnOrder
|
||||||
|
);
|
||||||
|
},
|
||||||
areRearWipersOnOrder: (state) => {
|
areRearWipersOnOrder: (state) => {
|
||||||
return !!state.order.lineItems.vaps?.some(
|
return !!state.order.lineItems.vaps?.some(
|
||||||
(vap) => vap.partType.toUpperCase() === partTypeStrings.REAR_WIPER.toUpperCase()
|
(vap) => vap.partType.toUpperCase() === partTypeStrings.REAR_WIPER.toUpperCase()
|
||||||
|
|
@ -894,12 +926,12 @@ export const getters = {
|
||||||
.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), {}) ?? {},
|
||||||
|
|
||||||
isVerifiedAndDeductibleZeroConfirmed: (state) => {
|
isVerifiedAndDeductibleZeroConfirmed: (state) => {
|
||||||
// used as a CMS variable on /payment-method, needed for FunnelSubHeaderWidget on cart pages
|
// used as a CMS variable on /payment-method, needed for FunnelSubHeaderWidget on cart pages
|
||||||
if (
|
if (
|
||||||
(state.order.policy.currentDeductible === 0 ||
|
state.order.policy.currentDeductible === 0 &&
|
||||||
state.order.policy.currentDeductible > 0) &&
|
getters.coverageIsVerified(state) &&
|
||||||
state.order.payment.insuranceCoverage.coverageStatus === coverageStatus.VERIFIED &&
|
|
||||||
!state.order.policy.isNoComp
|
!state.order.policy.isNoComp
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -915,7 +947,7 @@ export const getters = {
|
||||||
externalParameterQuote: (state) => externalParameterState?.quote,
|
externalParameterQuote: (state) => externalParameterState?.quote,
|
||||||
externalParameterServiceZip: (state) => externalParameterState?.serviceZip,
|
externalParameterServiceZip: (state) => externalParameterState?.serviceZip,
|
||||||
externalParameterEstimate: (state) => externalParameterState?.estimate,
|
externalParameterEstimate: (state) => externalParameterState?.estimate,
|
||||||
externalParameterSource: (state) => externalParameterState?.source,
|
isExternalParameter: (state) => externalParameterState?.isExternalParameter,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
|
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
|
||||||
|
|
@ -1121,6 +1153,12 @@ export const actions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Dependency Actions
|
// Dependency Actions
|
||||||
|
resetVehicleStateAndDependencies(context) {
|
||||||
|
context.commit(storeMutations.RESET_VEHICLE_STATE);
|
||||||
|
|
||||||
|
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
|
},
|
||||||
|
|
||||||
resetDamageAndDependencies(context) {
|
resetDamageAndDependencies(context) {
|
||||||
context.commit(storeMutations.RESET_DAMAGE_STATE);
|
context.commit(storeMutations.RESET_DAMAGE_STATE);
|
||||||
|
|
||||||
|
|
@ -1531,15 +1569,38 @@ export const actions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getMobileFeePart(context, { pageNameToLog }) {
|
getMobileFeePart(context, { pageNameToLog }) {
|
||||||
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
|
const serviceType = context.getters.damage.isRepair ? "Repair" : "Install";
|
||||||
|
const facilityType = "Mobile";
|
||||||
const parentAccountNumber = context.getters.payment.parentAccountNumber;
|
const parentAccountNumber = context.getters.payment.parentAccountNumber;
|
||||||
const billToAccountNumber = context.getters.payment.billToAccountNumber
|
const billToAccountNumber = context.getters.payment.billToAccountNumber
|
||||||
? context.getters.payment.billToAccountNumber
|
? context.getters.payment.billToAccountNumber
|
||||||
: applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER;
|
: applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER;
|
||||||
|
|
||||||
|
const order = context.getters.order;
|
||||||
|
const coverageStatus = coverageStatusEnum(order.payment?.insuranceCoverage?.coverageStatus);
|
||||||
|
const coverageType = coverageTypeEnum(order.payment?.insuranceCoverage?.coverageType);
|
||||||
|
const isItacOptimized = order.policy?.isItac ?? false;
|
||||||
|
const zipCode =
|
||||||
|
order.serviceLocation?.provider?.address?.zipCode ?? order.serviceLocation?.zipCode;
|
||||||
|
|
||||||
|
var providerNumber =
|
||||||
|
order.serviceLocation?.provider?.providerNumber ?? order.serviceLocation?.zipCodeCtu;
|
||||||
|
if (providerNumber.startsWith("00") && providerNumber.length > 5) {
|
||||||
|
providerNumber = providerNumber.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var endPoint = `${endpoints.GetMobileFeePart.url}/?serviceType=${serviceType}&facilityType=${facilityType}&parentAccountNumber=${parentAccountNumber}&billToAccountNumber=${billToAccountNumber}&providerNumber=${providerNumber}&isItacOptimized=${isItacOptimized}&zipCode=${zipCode}`;
|
||||||
|
if (coverageStatus) {
|
||||||
|
endPoint = `${endPoint}&coverageStatus=${coverageStatus}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coverageType) {
|
||||||
|
endPoint = `${endPoint}&coverageType=${coverageType}`;
|
||||||
|
}
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetMobileFeePart.method,
|
method: endpoints.GetMobileFeePart.method,
|
||||||
endpoint: `${endpoints.GetMobileFeePart.url}/${damageType}/${parentAccountNumber}/${billToAccountNumber}`,
|
endpoint: endPoint,
|
||||||
logApiCall: true,
|
logApiCall: true,
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
});
|
});
|
||||||
|
|
@ -1566,16 +1627,21 @@ export const actions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getServiceabilityDetails(context, { payload: { serviceZipCode }, pageNameToLog }) {
|
getServiceabilityDetails(context, { payload: { serviceZipCode }, pageNameToLog }) {
|
||||||
const lineItemsWithOnlyPartNumbers = context.getters.order.lineItems.supportingItems?.map(
|
const escapeRecalibrationType = (rt) => rt.split("&").join("%26");
|
||||||
|
|
||||||
|
const partialLineItemsObjects = context.getters.order.lineItems.glassParts?.map(
|
||||||
(lineItem) => ({
|
(lineItem) => ({
|
||||||
partNumber: lineItem.partNumber,
|
partNumber: lineItem.partNumber,
|
||||||
|
recalibrationType: lineItem.recalibrationType
|
||||||
|
? escapeRecalibrationType(lineItem.recalibrationType)
|
||||||
|
: undefined,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
var lineItems = null;
|
var lineItems = null;
|
||||||
if (lineItemsWithOnlyPartNumbers) {
|
if (partialLineItemsObjects) {
|
||||||
lineItems = buildQueryStringParameterFromArrayOfComplexObjects(
|
lineItems = buildQueryStringParameterFromArrayOfComplexObjects(
|
||||||
lineItemsWithOnlyPartNumbers,
|
partialLineItemsObjects,
|
||||||
"lineItems"
|
"lineItems"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1590,7 +1656,12 @@ export const actions = {
|
||||||
"glassPieces"
|
"glassPieces"
|
||||||
);
|
);
|
||||||
|
|
||||||
var endPoint = `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}`;
|
const parentAccountNumber =
|
||||||
|
context.getters.order.payment.parentAccountNumber ??
|
||||||
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER;
|
||||||
|
const referralSequenceNumber = context.getters.order.referralSequenceNumber;
|
||||||
|
|
||||||
|
var endPoint = `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&parentAccountNumber=${parentAccountNumber}&referralSequenceNumber=${referralSequenceNumber}&applicationName=${applicationConfig.ANALYTICS_APPLICATION_NAME}`;
|
||||||
if (lineItems) {
|
if (lineItems) {
|
||||||
endPoint += `&${lineItems}`;
|
endPoint += `&${lineItems}`;
|
||||||
}
|
}
|
||||||
|
|
@ -1609,11 +1680,26 @@ export const actions = {
|
||||||
|
|
||||||
getProviders(context, { payload: { serviceZipCode }, pageNameToLog }) {
|
getProviders(context, { payload: { serviceZipCode }, pageNameToLog }) {
|
||||||
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
|
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
|
||||||
|
const accountNumber =
|
||||||
|
context.getters.order.payment.parentAccountNumber ??
|
||||||
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER;
|
||||||
|
const carId = context.getters.order.vehicle.carId;
|
||||||
|
const partsWithRecal = getTopLevelPartsWithRecal(
|
||||||
|
context.getters.order.lineItems.glassParts
|
||||||
|
);
|
||||||
|
const windshieldPartWithRecal = partsWithRecal?.length > 0 ? partsWithRecal[0] : null;
|
||||||
|
|
||||||
const shopRadiusInMiles = 100;
|
const shopRadiusInMiles = 100;
|
||||||
|
|
||||||
|
let url = `${endpoints.GetProviders.url}/${serviceZipCode}/${damageType}/${shopRadiusInMiles}/${accountNumber}/true/${carId}`;
|
||||||
|
|
||||||
|
if (windshieldPartWithRecal) {
|
||||||
|
url += `/${windshieldPartWithRecal.partNumber}`;
|
||||||
|
}
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetProviders.method,
|
method: endpoints.GetProviders.method,
|
||||||
endpoint: `${endpoints.GetProviders.url}/${serviceZipCode}/${damageType}/${shopRadiusInMiles}`,
|
endpoint: url,
|
||||||
logApiCall: true,
|
logApiCall: true,
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
});
|
});
|
||||||
|
|
@ -2579,9 +2665,10 @@ export const actions = {
|
||||||
carId: order.vehicle.carId,
|
carId: order.vehicle.carId,
|
||||||
correlationId: order.referralCorrelationId,
|
correlationId: order.referralCorrelationId,
|
||||||
eon: order.eon,
|
eon: order.eon,
|
||||||
|
isInsurance: order.payment.isInsurance,
|
||||||
isRepair: order.damage.isRepair,
|
isRepair: order.damage.isRepair,
|
||||||
glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace),
|
glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace),
|
||||||
lineItemsOnOrder: getArrayOfAllLineItems(lineItemsToUse),
|
lineItemsOnOrder: getArrayOfAllLineItemsAndChildParts(lineItemsToUse),
|
||||||
parentAccountNumber: useDefaultCashParentAccount
|
parentAccountNumber: useDefaultCashParentAccount
|
||||||
? applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
|
? applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
|
||||||
: order.payment.parentAccountNumber,
|
: order.payment.parentAccountNumber,
|
||||||
|
|
@ -2651,9 +2738,10 @@ export const actions = {
|
||||||
carId: order.vehicle.carId,
|
carId: order.vehicle.carId,
|
||||||
correlationId: order.referralCorrelationId,
|
correlationId: order.referralCorrelationId,
|
||||||
eon: order.eon,
|
eon: order.eon,
|
||||||
|
isInsurance: order.payment.isInsurance,
|
||||||
isRepair: order.damage.isRepair,
|
isRepair: order.damage.isRepair,
|
||||||
glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace),
|
glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace),
|
||||||
lineItemsOnOrder: getArrayOfAllLineItems(lineItemsToUse),
|
lineItemsOnOrder: getArrayOfAllLineItemsAndChildParts(lineItemsToUse),
|
||||||
parentAccountNumber: useDefaultCashParentAccount
|
parentAccountNumber: useDefaultCashParentAccount
|
||||||
? applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
|
? applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
|
||||||
: order.payment.parentAccountNumber,
|
: order.payment.parentAccountNumber,
|
||||||
|
|
@ -2721,10 +2809,8 @@ export const actions = {
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
// Cash orders default to 87291 - update if/when more detailed
|
if (!parentAccountNumber) {
|
||||||
// billToAccountNumbers are needed for cash
|
parentAccountNumber = applicationConfig.CASH_PARENT_ACCOUNT_NUMBER;
|
||||||
if (parentAccountNumber == applicationConfig.CASH_PARENT_ACCOUNT_NUMBER) {
|
|
||||||
return applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER;
|
|
||||||
}
|
}
|
||||||
const queryString =
|
const queryString =
|
||||||
`ParentAccountNumber=${parentAccountNumber}` +
|
`ParentAccountNumber=${parentAccountNumber}` +
|
||||||
|
|
@ -2885,7 +2971,6 @@ export const actions = {
|
||||||
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_ESTIMATE_STATE);
|
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_ESTIMATE_STATE);
|
||||||
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_SERVICEZIP_STATE);
|
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_SERVICEZIP_STATE);
|
||||||
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_QUOTE_STATE);
|
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_QUOTE_STATE);
|
||||||
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_SOURCE_STATE);
|
|
||||||
context.commit(storeMutations.RESET_IS_EXTERNAL_PARAMETER);
|
context.commit(storeMutations.RESET_IS_EXTERNAL_PARAMETER);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -2903,6 +2988,49 @@ export const actions = {
|
||||||
externalParameterMMS.externalParameterStyle
|
externalParameterMMS.externalParameterStyle
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async getRecalPartsAndSaveToLineItems(context, { pageNameToLog }) {
|
||||||
|
// identify each part that needs recal
|
||||||
|
const glassParts = context.state.order?.lineItems?.glassParts
|
||||||
|
? deepClone(context.state.order.lineItems.glassParts)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
for (let i = 0; i < glassParts.length; i++) {
|
||||||
|
// does this part need recal?
|
||||||
|
const needsRecal =
|
||||||
|
!!glassParts[i].requiresRecalibration && !!glassParts[i].recalibrationType;
|
||||||
|
|
||||||
|
if (needsRecal) {
|
||||||
|
const recalType = glassParts[i].recalibrationType;
|
||||||
|
const parentAccountNumber =
|
||||||
|
context.state.order.payment.parentAccountNumber ??
|
||||||
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER;
|
||||||
|
|
||||||
|
// Get part from API
|
||||||
|
const urlExtension = `${context.state.order.vehicle.carId}/${glassParts[i].partNumber}/${recalType}/${parentAccountNumber}/${context.state.order.serviceLocation.zipCode}/${applicationConfig.ANALYTICS_APPLICATION_NAME}/${context.state.order.referralSequenceNumber}`;
|
||||||
|
|
||||||
|
const recalPartResponse = await globalMethods.callHttpClient({
|
||||||
|
method: endpoints.GetRecalPart.method,
|
||||||
|
endpoint: `${endpoints.GetRecalPart.url}/${urlExtension}`,
|
||||||
|
payload: {},
|
||||||
|
pageNameToLog: pageNameToLog,
|
||||||
|
});
|
||||||
|
|
||||||
|
// If any parts retrieved, add as children to the glass part.
|
||||||
|
if (
|
||||||
|
recalPartResponse.status === 200 &&
|
||||||
|
recalPartResponse.data.recalibrationParts?.length > 0
|
||||||
|
) {
|
||||||
|
if (!glassParts[i].childParts) {
|
||||||
|
glassParts[i].childParts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
glassParts[i].childParts.push(...recalPartResponse.data.recalibrationParts);
|
||||||
|
context.dispatch(storeActions.SAVE_GLASS_PARTS, glassParts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default createStore({
|
export default createStore({
|
||||||
|
|
@ -2925,34 +3053,7 @@ export default createStore({
|
||||||
// Private Functions
|
// Private Functions
|
||||||
|
|
||||||
function getHasRecalibrationPart(state) {
|
function getHasRecalibrationPart(state) {
|
||||||
var hasRequiresRecalibration =
|
return containsRecalParts(state.order.lineItems);
|
||||||
getNonFalseValuesOfPropertyInArrayOfObjects(
|
|
||||||
state.order.lineItems.glassParts,
|
|
||||||
"requiresRecalibration"
|
|
||||||
)?.length > 0;
|
|
||||||
var hasRecalibrationType =
|
|
||||||
getNonFalseValuesOfPropertyInArrayOfObjects(
|
|
||||||
state.order.lineItems.glassParts,
|
|
||||||
"recalibrationType"
|
|
||||||
)?.length > 0;
|
|
||||||
|
|
||||||
if (hasRequiresRecalibration) {
|
|
||||||
if (hasRecalibrationType) {
|
|
||||||
// Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType'
|
|
||||||
return (
|
|
||||||
getNonFalseValuesOfPropertyInArrayOfObjects(
|
|
||||||
state.order.lineItems.glassParts,
|
|
||||||
"recalibrationType"
|
|
||||||
)[0].toLowerCase() != "unknown"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Has 'requiresRecalibration' but no 'recalibrationType' at all
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Does not have 'requiresRecalibration'
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
||||||
|
|
@ -3120,32 +3221,46 @@ export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItem
|
||||||
return lineItems;
|
return lineItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getArrayOfAllLineItems(lineItems) {
|
export function getArrayOfAllLineItemsAndChildParts(lineItems) {
|
||||||
let consolidatedLineItemsArray = [];
|
let consolidatedLineItemsArray = [];
|
||||||
|
|
||||||
if (lineItems.glassParts != null)
|
if (lineItems.glassParts != null)
|
||||||
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.glassParts];
|
consolidatedLineItemsArray = [
|
||||||
|
...consolidatedLineItemsArray,
|
||||||
|
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.glassParts),
|
||||||
|
];
|
||||||
|
|
||||||
if (lineItems.supportingItems != null)
|
if (lineItems.supportingItems != null)
|
||||||
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.supportingItems];
|
consolidatedLineItemsArray = [
|
||||||
|
...consolidatedLineItemsArray,
|
||||||
|
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.supportingItems),
|
||||||
|
];
|
||||||
|
|
||||||
if (lineItems.vaps != null)
|
if (lineItems.vaps != null)
|
||||||
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.vaps];
|
consolidatedLineItemsArray = [
|
||||||
|
...consolidatedLineItemsArray,
|
||||||
|
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.vaps),
|
||||||
|
];
|
||||||
|
|
||||||
if (lineItems.promos != null)
|
if (lineItems.promos != null)
|
||||||
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.promos];
|
consolidatedLineItemsArray = [
|
||||||
|
...consolidatedLineItemsArray,
|
||||||
|
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.promos),
|
||||||
|
];
|
||||||
|
|
||||||
return consolidatedLineItemsArray;
|
return consolidatedLineItemsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFlattenedArrayOfLineItemsWithChildParts(lineItems) {
|
function getFlattenedArrayOfLineItemsWithChildParts(lineItems, childPartRecursiveCall = false) {
|
||||||
let flattenedArray = [];
|
let flattenedArray = [];
|
||||||
lineItems?.forEach((lineItem) => {
|
lineItems?.forEach((lineItem) => {
|
||||||
|
// this assumes childparts will never be a glass part
|
||||||
|
lineItem.isChildPart = childPartRecursiveCall;
|
||||||
flattenedArray.push(lineItem);
|
flattenedArray.push(lineItem);
|
||||||
if (lineItem.childParts) {
|
if (lineItem.childParts) {
|
||||||
flattenedArray = [
|
flattenedArray = [
|
||||||
...flattenedArray,
|
...flattenedArray,
|
||||||
...getFlattenedArrayOfLineItemsWithChildParts(lineItem.childParts),
|
...getFlattenedArrayOfLineItemsWithChildParts(lineItem.childParts, true),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -3168,7 +3283,7 @@ function getFlattenedLineItemsWithGlassPartTag(lineItems) {
|
||||||
return {
|
return {
|
||||||
partNumber: lineItem.partNumber,
|
partNumber: lineItem.partNumber,
|
||||||
partType: lineItem.partType,
|
partType: lineItem.partType,
|
||||||
isGlassPart: true,
|
isGlassPart: lineItem.isChildPart ? false : true,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -3212,6 +3327,9 @@ function addGuidToLineItemsIfNotAlreadyThere(lineItems) {
|
||||||
if (!lineItem.id) {
|
if (!lineItem.id) {
|
||||||
lineItem.id = crypto.randomUUID();
|
lineItem.id = crypto.randomUUID();
|
||||||
}
|
}
|
||||||
|
if (lineItem.childParts) {
|
||||||
|
addGuidToLineItemsIfNotAlreadyThere(lineItem.childParts);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3393,7 +3511,7 @@ async function resetScheduleIfUnavailable(context, order, pageNameToLog) {
|
||||||
function createExternalParameterDefaultState() {
|
function createExternalParameterDefaultState() {
|
||||||
// create default externalParameter state
|
// create default externalParameter state
|
||||||
const externalParameterDefaultState = {
|
const externalParameterDefaultState = {
|
||||||
isExternalParameter: null,
|
isExternalParameter: externalParameterStatus.NOT_SET,
|
||||||
vehicle: {
|
vehicle: {
|
||||||
year: null,
|
year: null,
|
||||||
make: null,
|
make: null,
|
||||||
|
|
@ -3416,7 +3534,6 @@ function createExternalParameterDefaultState() {
|
||||||
isInsurance: null,
|
isInsurance: null,
|
||||||
servicePackage: null,
|
servicePackage: null,
|
||||||
},
|
},
|
||||||
source: null,
|
|
||||||
};
|
};
|
||||||
// set to session storage
|
// set to session storage
|
||||||
saveExternalParameterState(externalParameterDefaultState);
|
saveExternalParameterState(externalParameterDefaultState);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import { storeActions } from "@/constants/store-actions";
|
||||||
import { experimentTriggers } from "@/constants/experiments";
|
import { experimentTriggers } from "@/constants/experiments";
|
||||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||||
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||||
import { coverageStatus } from "../constants/insurance";
|
|
||||||
|
|
||||||
// Mock global method
|
// Mock global method
|
||||||
globalMethods.callHttpClient = jest.fn();
|
globalMethods.callHttpClient = jest.fn();
|
||||||
|
|
@ -2935,7 +2934,10 @@ describe("Actions", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const context = state;
|
const context = state;
|
||||||
const promoCode = "testPromo";
|
const promoCode = "testPromo";
|
||||||
const lineItemsToUse = { vaps: [{ partNumber: 1 }], promos: [2] };
|
const lineItemsToUse = {
|
||||||
|
vaps: [{ partNumber: 1 }],
|
||||||
|
promos: [{ promoCode: "1wiper0" }],
|
||||||
|
};
|
||||||
const addableVaps = [{ partNumber: "addableVap" }];
|
const addableVaps = [{ partNumber: "addableVap" }];
|
||||||
|
|
||||||
context["getters"] = {
|
context["getters"] = {
|
||||||
|
|
@ -2999,7 +3001,7 @@ describe("Actions", () => {
|
||||||
{ partNumber: "SBB22", id: "GUID1" },
|
{ partNumber: "SBB22", id: "GUID1" },
|
||||||
{ partNumber: "SBB22", id: "GUID2" },
|
{ partNumber: "SBB22", id: "GUID2" },
|
||||||
],
|
],
|
||||||
promos: [2],
|
promos: [{ promoCode: "1wiper0" }],
|
||||||
};
|
};
|
||||||
const addableVaps = [{ partNumber: "SBB22" }, { partNumber: "SBB22" }];
|
const addableVaps = [{ partNumber: "SBB22" }, { partNumber: "SBB22" }];
|
||||||
|
|
||||||
|
|
@ -3059,7 +3061,10 @@ describe("Actions", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const context = state;
|
const context = state;
|
||||||
const promoCode = "testPromo";
|
const promoCode = "testPromo";
|
||||||
const lineItemsToUse = { vaps: [{ partNumber: 1 }], promos: [2] };
|
const lineItemsToUse = {
|
||||||
|
vaps: [{ partNumber: 1 }],
|
||||||
|
promos: [{ promoCode: "1wiper0" }],
|
||||||
|
};
|
||||||
const addableVaps = [{ partNumber: "addableVap" }];
|
const addableVaps = [{ partNumber: "addableVap" }];
|
||||||
|
|
||||||
context["getters"] = {
|
context["getters"] = {
|
||||||
|
|
@ -3140,7 +3145,7 @@ describe("Actions", () => {
|
||||||
referralSequenceNumber: "test",
|
referralSequenceNumber: "test",
|
||||||
lineItems: {
|
lineItems: {
|
||||||
vaps: [{ partNumber: 1 }],
|
vaps: [{ partNumber: 1 }],
|
||||||
promos: [2],
|
promos: [{ promoCode: "1wiper0" }],
|
||||||
serverData: "test",
|
serverData: "test",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -3152,7 +3157,10 @@ describe("Actions", () => {
|
||||||
|
|
||||||
crypto.randomUUID = jest.fn(() => "GUID");
|
crypto.randomUUID = jest.fn(() => "GUID");
|
||||||
|
|
||||||
const expectedLineItemsOnOrder = [{ partNumber: 1, id: "GUID" }, 2];
|
const expectedLineItemsOnOrder = [
|
||||||
|
{ partNumber: 1, isChildPart: false, id: "GUID" },
|
||||||
|
{ promoCode: "1wiper0", isChildPart: false },
|
||||||
|
];
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
actions.validateOrderPromoAndSaveServerData(context, {
|
actions.validateOrderPromoAndSaveServerData(context, {
|
||||||
|
|
@ -3200,7 +3208,7 @@ describe("Actions", () => {
|
||||||
referralSequenceNumber: "test",
|
referralSequenceNumber: "test",
|
||||||
lineItems: {
|
lineItems: {
|
||||||
vaps: [{ partNumber: 1 }],
|
vaps: [{ partNumber: 1 }],
|
||||||
promos: [2],
|
promos: [{ promoCode: "1wiper0" }],
|
||||||
serverData: "test",
|
serverData: "test",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -3258,7 +3266,7 @@ describe("Actions", () => {
|
||||||
referralSequenceNumber: "test",
|
referralSequenceNumber: "test",
|
||||||
lineItems: {
|
lineItems: {
|
||||||
vaps: [{ partNumber: 1 }],
|
vaps: [{ partNumber: 1 }],
|
||||||
promos: [2],
|
promos: [{ promoCode: "1wiper0" }],
|
||||||
serverData: "test",
|
serverData: "test",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -3350,9 +3358,9 @@ describe("Actions", () => {
|
||||||
const context = state;
|
const context = state;
|
||||||
context.commit = jest.fn(() => {});
|
context.commit = jest.fn(() => {});
|
||||||
|
|
||||||
const activePromosToUse = [{ promoCode: "providedPromo" }];
|
const activePromosToUse = [{ promoCode: "providedPromo", isChildPart: false }];
|
||||||
const inactivePromosToUse = ["providedInactivePromo"];
|
const inactivePromosToUse = ["providedInactivePromo"];
|
||||||
const vapsProvided = [{ id: 123 }];
|
const vapsProvided = [{ id: 123, isChildPart: false }];
|
||||||
const lineItemsToUse = { vaps: vapsProvided };
|
const lineItemsToUse = { vaps: vapsProvided };
|
||||||
|
|
||||||
context["getters"] = {
|
context["getters"] = {
|
||||||
|
|
@ -3440,8 +3448,8 @@ describe("Actions", () => {
|
||||||
referralSequenceNumber: "test",
|
referralSequenceNumber: "test",
|
||||||
lineItems: {
|
lineItems: {
|
||||||
serverData: "test",
|
serverData: "test",
|
||||||
promos: [{ promoCode: "test" }],
|
promos: [{ promoCode: "test", isChildPart: false }],
|
||||||
vaps: [{ partNumber: "testVap", id: "providedId" }],
|
vaps: [{ partNumber: "testVap", isChildPart: false, id: "providedId" }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -3950,6 +3958,111 @@ describe("Getters", () => {
|
||||||
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
mutations.updateGlassToReplace(storeState, mockStateValues.glassToReplace);
|
mutations.updateGlassToReplace(storeState, mockStateValues.glassToReplace);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(getters.experimentOrder(storeState)).toEqual({
|
||||||
|
funnelVehicleYear: mockStateValues.vehicleYear,
|
||||||
|
funnelVehicleMake: mockStateValues.vehicleMake,
|
||||||
|
funnelVehicleModel: mockStateValues.vehicleModel,
|
||||||
|
funnelVehicleStyle: mockStateValues.vehicleStyle,
|
||||||
|
funnelIsRepair: mockStateValues.isRepair,
|
||||||
|
funnelNumberOfChips: mockStateValues.numberOfChips,
|
||||||
|
funnelCarId: mockStateValues.carId,
|
||||||
|
funnelServiceCity: mockStateValues.serviceCity,
|
||||||
|
funnelServiceState: mockStateValues.serviceState,
|
||||||
|
funnelServiceZipCode: mockStateValues.serviceZipCode,
|
||||||
|
funnelParentAccountNumber: mockStateValues.parentAccountNumber,
|
||||||
|
funnelIsCoverageVerified: mockStateValues.isCoverageVerified,
|
||||||
|
funnelOrderPartNumbers: ["WINDSHIELDPARTNUMBER"],
|
||||||
|
funnelOrderPartTypes: ["ADAS, maybe"],
|
||||||
|
funnelHasRecalibrationPart: false,
|
||||||
|
funnelSelectedMultiGlass: false,
|
||||||
|
funnelSelectedWindshieldGlass: true,
|
||||||
|
funnelSelectedBackGlass: false,
|
||||||
|
funnelSelectedDriverSideGlass: false,
|
||||||
|
funnelSelectedPassengerSideGlass: false,
|
||||||
|
funnelProviderNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
funnelReferralType: mockStateValues.funnelReferralType,
|
||||||
|
funnelServiceZipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Single windshield with recalibration child part > return correct experimentOrder values", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
const mockStateValues = {
|
||||||
|
vehicleYear: 1000,
|
||||||
|
vehicleMake: "CarMake",
|
||||||
|
vehicleModel: "CarModel",
|
||||||
|
vehicleStyle: "SuperCoolStyle",
|
||||||
|
isRepair: false,
|
||||||
|
numberOfChips: 0,
|
||||||
|
carId: "Gibberish",
|
||||||
|
serviceCity: "Columbus",
|
||||||
|
serviceState: "OH-IO",
|
||||||
|
serviceZipCode: 43215,
|
||||||
|
parentAccountNumber: "999999",
|
||||||
|
isCoverageVerified: false,
|
||||||
|
glassParts: [
|
||||||
|
{
|
||||||
|
partNumber: "WINDSHIELDPARTNUMBER",
|
||||||
|
description: "This is a windshield",
|
||||||
|
recalibrationType: "ADAS, maybe",
|
||||||
|
requiresRecalibration: true,
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
childParts: [
|
||||||
|
{
|
||||||
|
partNumber: "THIRD RECAL",
|
||||||
|
description: "Additional Static Recal",
|
||||||
|
recalibrationType:
|
||||||
|
"DUAL & RECAL THIRD & HC FUNCTION TEST & RL SENSOR",
|
||||||
|
ribCode: "RL",
|
||||||
|
safelitePartNumber: "THIRD RECAL",
|
||||||
|
status: "ACTIVE",
|
||||||
|
partType: "ADAS RECALIBRATION",
|
||||||
|
childParts: [],
|
||||||
|
recalibrationFees: [],
|
||||||
|
salesTax: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
otherParts: [],
|
||||||
|
glassToReplace: [
|
||||||
|
{
|
||||||
|
glassLocation: "Windshield",
|
||||||
|
glassName: "Single",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
funnelProviderNumber: "1",
|
||||||
|
funnelReferralType: "CASH QUOTE",
|
||||||
|
funnelServiceZipCodeCtu: "11111",
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mutations.updateYear(storeState, mockStateValues.vehicleYear);
|
||||||
|
mutations.updateMake(storeState, mockStateValues.vehicleMake);
|
||||||
|
mutations.updateModel(storeState, mockStateValues.vehicleModel);
|
||||||
|
mutations.updateStyle(storeState, mockStateValues.vehicleStyle);
|
||||||
|
mutations.updateIsRepair(storeState, mockStateValues.isRepair);
|
||||||
|
mutations.updateNumberOfChips(storeState, mockStateValues.numberOfChips);
|
||||||
|
mutations.updateCarId(storeState, mockStateValues.carId);
|
||||||
|
mutations.updateServiceLocation(storeState, {
|
||||||
|
city: mockStateValues.serviceCity,
|
||||||
|
state: mockStateValues.serviceState,
|
||||||
|
zipCode: mockStateValues.serviceZipCode,
|
||||||
|
zipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
provider: {
|
||||||
|
providerNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
mutations.updateParentAcctNumber(storeState, mockStateValues.parentAccountNumber);
|
||||||
|
mutations.updateInsuranceVerifiedStatus(storeState, mockStateValues.isCoverageVerified);
|
||||||
|
mutations.updateIsInsurance(storeState, false);
|
||||||
|
mutations.updateGlassParts(storeState, mockStateValues.glassParts);
|
||||||
|
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
||||||
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
|
mutations.updateGlassToReplace(storeState, mockStateValues.glassToReplace);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(getters.experimentOrder(storeState)).toEqual({
|
expect(getters.experimentOrder(storeState)).toEqual({
|
||||||
funnelVehicleYear: mockStateValues.vehicleYear,
|
funnelVehicleYear: mockStateValues.vehicleYear,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ process.env.VUE_APP_CURRENT_ENVIRONMENT = "Localhost";
|
||||||
process.env.VUE_APP_MY_ACCOUNT = "https://myaccountdev.safelite.com/";
|
process.env.VUE_APP_MY_ACCOUNT = "https://myaccountdev.safelite.com/";
|
||||||
|
|
||||||
//process.env.VUE_APP_SAFELITE_HOP = "http://localhost:60966/fmgCheckoutShared.aspx";
|
//process.env.VUE_APP_SAFELITE_HOP = "http://localhost:60966/fmgCheckoutShared.aspx";
|
||||||
process.env.VUE_APP_SAFELITE_HOP = "https://sv2-safelitehop-sys.safelite.com/fmgCheckoutShared.aspx";
|
process.env.VUE_APP_SAFELITE_HOP = "https://sv2-safelitehop-dev.safelite.com/fmgCheckoutShared.aspx";
|
||||||
|
|
||||||
// GA & GTM
|
// GA & GTM
|
||||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue