Merge remote-tracking branch 'origin/develop' into feature/CSR-1971
This commit is contained in:
commit
8f2fda3995
34 changed files with 736 additions and 121 deletions
|
|
@ -24,12 +24,13 @@ module.exports = {
|
||||||
"!src/layouts/review/*.vue", // Temp test exclusion while in development
|
"!src/layouts/review/*.vue", // Temp test exclusion while in development
|
||||||
"!src/layouts/payment/*.vue", // Temp test exclusion while in development
|
"!src/layouts/payment/*.vue", // Temp test exclusion while in development
|
||||||
"!src/layouts/payment-pia-return/*.vue", // Temp test exclusion while in development
|
"!src/layouts/payment-pia-return/*.vue", // Temp test exclusion while in development
|
||||||
|
"!src/layouts/insurance/*.vue", // Temp test exclusion while in development
|
||||||
// END
|
// END
|
||||||
], // ! means exclude from coverage.
|
], // ! means exclude from coverage.
|
||||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
global: {
|
global: {
|
||||||
statements: 78,
|
statements: 77,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
|
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ const applicationConfig = {
|
||||||
PAGE_QUERYSTRING: "fmgPage",
|
PAGE_QUERYSTRING: "fmgPage",
|
||||||
SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass",
|
SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass",
|
||||||
CASH_PARENT_ACCOUNT_NUMBER: 167132,
|
CASH_PARENT_ACCOUNT_NUMBER: 167132,
|
||||||
|
CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER: "87291",
|
||||||
MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT,
|
MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT,
|
||||||
PIA_RESPONSE_URL:
|
PIA_RESPONSE_URL:
|
||||||
location.protocol +
|
location.protocol +
|
||||||
|
|
|
||||||
18
src/constants/coverage-status.js
Normal file
18
src/constants/coverage-status.js
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
const coverageStatus = {
|
||||||
|
PENDING: "Pending",
|
||||||
|
NOCOMP: "NoComp",
|
||||||
|
VERIFIED: "Verified",
|
||||||
|
};
|
||||||
|
|
||||||
|
export function coverageStatusValue(intCoverageStatus) {
|
||||||
|
switch (intCoverageStatus) {
|
||||||
|
case 0:
|
||||||
|
return coverageStatus.PENDING;
|
||||||
|
case 1:
|
||||||
|
return coverageStatus.NOCOMP;
|
||||||
|
case 2:
|
||||||
|
return coverageStatus.VERIFIED;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,7 @@ const queryStrings = {
|
||||||
TRANS_REFERENCE_NUMBER: "auth_trans_ref_no",
|
TRANS_REFERENCE_NUMBER: "auth_trans_ref_no",
|
||||||
LAST_FOUR: "last_four",
|
LAST_FOUR: "last_four",
|
||||||
DISPLAY_PIA_ALERT: "displayPiaAlert",
|
DISPLAY_PIA_ALERT: "displayPiaAlert",
|
||||||
|
PAGE_ERROR: "pageerror",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { queryStrings };
|
export { queryStrings };
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ const storeActions = {
|
||||||
SAVE_PAYMENT_TYPE: "savePaymentType",
|
SAVE_PAYMENT_TYPE: "savePaymentType",
|
||||||
SAVE_PAYMENT_METHOD_CHOICE: "savePaymentMethodChoice",
|
SAVE_PAYMENT_METHOD_CHOICE: "savePaymentMethodChoice",
|
||||||
SAVE_PARENT_ACCOUNT_NUMBER: "saveParentAccountNumber",
|
SAVE_PARENT_ACCOUNT_NUMBER: "saveParentAccountNumber",
|
||||||
|
SAVE_BILL_TO_ACCOUNT_NUMBER: "saveBillToAccountNumber",
|
||||||
SAVE_SUPPORTING_ITEMS: "saveSupportingItems",
|
SAVE_SUPPORTING_ITEMS: "saveSupportingItems",
|
||||||
SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING:
|
SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING:
|
||||||
"saveSupportingItemsSuppressingStateResetting",
|
"saveSupportingItemsSuppressingStateResetting",
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ const storeMutations = {
|
||||||
UPDATE_REFERRAL_DATE: "updateReferralDate",
|
UPDATE_REFERRAL_DATE: "updateReferralDate",
|
||||||
UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId",
|
UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId",
|
||||||
UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber",
|
UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber",
|
||||||
|
UPDATE_BILL_TO_ACCT_NUMBER: "updateBillToAcctNumber",
|
||||||
UPDATE_EON: "updateEON",
|
UPDATE_EON: "updateEON",
|
||||||
UPDATE_IS_INSURANCE: "updateIsInsurance",
|
UPDATE_IS_INSURANCE: "updateIsInsurance",
|
||||||
UPDATE_SAVED_SESSION_ID: "updateSavedSessionId",
|
UPDATE_SAVED_SESSION_ID: "updateSavedSessionId",
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,11 @@
|
||||||
:maxlength="maxLength ? maxLength : '999'"
|
:maxlength="maxLength ? maxLength : '999'"
|
||||||
@focus="$emit('focus', $event.target.value)"
|
@focus="$emit('focus', $event.target.value)"
|
||||||
@keydown="keyDownHandler" />
|
@keydown="keyDownHandler" />
|
||||||
<button v-if="includeSearchIcon" type="submit" aria-label="Search button" />
|
<button
|
||||||
|
v-if="includeSearchIcon"
|
||||||
|
type="submit"
|
||||||
|
aria-label="Search button"
|
||||||
|
@click="focusSearchInput" />
|
||||||
<template v-if="includeImageQuestion">
|
<template v-if="includeImageQuestion">
|
||||||
<template v-if="!isDisabled">
|
<template v-if="!isDisabled">
|
||||||
<label class="camera-icon-input" v-show="!isImageProcessing">
|
<label class="camera-icon-input" v-show="!isImageProcessing">
|
||||||
|
|
@ -169,6 +173,11 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
focusSearchInput() {
|
||||||
|
//Focus cursor in input when search icon is clicked
|
||||||
|
const field = document.querySelector("input");
|
||||||
|
field.focus();
|
||||||
|
},
|
||||||
async imageChanged(e) {
|
async imageChanged(e) {
|
||||||
let file = e.target.files[0];
|
let file = e.target.files[0];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
ref="promoModalQuestion"
|
ref="promoModalQuestion"
|
||||||
class="small mt-4"
|
class="small mt-4"
|
||||||
v-model="lineItems"
|
v-model="lineItems"
|
||||||
@addedPromo="handleAddedPromo"
|
emitToGrandparent="true"
|
||||||
:availableVaps="availableVaps"
|
:availableVaps="availableVaps"
|
||||||
modalWidgetName="PromoModalWidget" />
|
modalWidgetName="PromoModalWidget" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -245,10 +245,6 @@ export default {
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
handleAddedPromo(lineItems) {
|
|
||||||
// NOTE: these lineItems are passed from promo-modal-question
|
|
||||||
this.$emit("update:modelValue", lineItems);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
screenReaderTotalAmountDueText() {
|
screenReaderTotalAmountDueText() {
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ export default {
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.menu-modal-container {
|
.menu-modal-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 1.47rem 1rem 1.47rem 1.47rem;
|
padding: 1.47rem 0 1.47rem 1.47rem;
|
||||||
right: 0;
|
right: 0;
|
||||||
button {
|
button {
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -186,7 +186,7 @@ export default {
|
||||||
}
|
}
|
||||||
.menu-modal-container {
|
.menu-modal-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 1.47rem 1rem 1.47rem 1.47rem;
|
padding: 1.47rem 0 1.47rem 1.47rem;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: -5rem;
|
top: -5rem;
|
||||||
button {
|
button {
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
emitToGrandparent: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
promoLinkText() {
|
promoLinkText() {
|
||||||
|
|
@ -175,6 +180,7 @@ export default {
|
||||||
},
|
},
|
||||||
onModalClosed() {
|
onModalClosed() {
|
||||||
this.resetAlerts();
|
this.resetAlerts();
|
||||||
|
if (this.emitToGrandparent) this.$parent.$emit("update:modelValue", this.lineItems);
|
||||||
this.$emit("update:modelValue", this.lineItems);
|
this.$emit("update:modelValue", this.lineItems);
|
||||||
this.promoCode = "";
|
this.promoCode = "";
|
||||||
this.modal.resetForm();
|
this.modal.resetForm();
|
||||||
|
|
@ -261,7 +267,6 @@ export default {
|
||||||
this.availableVaps,
|
this.availableVaps,
|
||||||
this.pageName
|
this.pageName
|
||||||
);
|
);
|
||||||
|
|
||||||
if (promoCodeData.isValid) {
|
if (promoCodeData.isValid) {
|
||||||
if (this.taxPromos) {
|
if (this.taxPromos) {
|
||||||
const pricedLineItemsToTax = [];
|
const pricedLineItemsToTax = [];
|
||||||
|
|
@ -305,7 +310,6 @@ export default {
|
||||||
this.lineItems.vaps?.push(...getVaps);
|
this.lineItems.vaps?.push(...getVaps);
|
||||||
}
|
}
|
||||||
this.lineItems?.promos.push(...promoCodeData.promoCode);
|
this.lineItems?.promos.push(...promoCodeData.promoCode);
|
||||||
this.$emit("added-promo", this.lineItems);
|
|
||||||
this.closeModal();
|
this.closeModal();
|
||||||
} else {
|
} else {
|
||||||
this.getErrorMessage(promoCodeData.errorCode, promoCodeData.additionalInfo);
|
this.getErrorMessage(promoCodeData.errorCode, promoCodeData.additionalInfo);
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,11 @@ export default {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//router.navigateError();
|
// do not route to error logic when no wipers found or no promo found (404s)
|
||||||
|
if (error.response.status != "404") {
|
||||||
|
router.navigateError();
|
||||||
|
}
|
||||||
|
|
||||||
return reject(error.response);
|
return reject(error.response);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import globalMethods from "@/global-methods";
|
import globalMethods from "@/global-methods";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import analyticsMixIn from "@/mixins/analytics-mixin";
|
import analyticsMixIn from "@/mixins/analytics-mixin";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
//Mock external dependencies
|
//Mock external dependencies
|
||||||
jest.mock("axios");
|
jest.mock("axios");
|
||||||
|
|
@ -29,6 +30,7 @@ it("Global Methods - Call Http Client - Should Reject Promise", () => {
|
||||||
isError: true,
|
isError: true,
|
||||||
});
|
});
|
||||||
analyticsMixIn.methods.pushEventToGA = jest.fn();
|
analyticsMixIn.methods.pushEventToGA = jest.fn();
|
||||||
|
router.navigateError = jest.fn();
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
globalMethods.callHttpClient(httpArgs).catch((err) => {
|
globalMethods.callHttpClient(httpArgs).catch((err) => {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ export function updateOrCreateFunnelCookie() {
|
||||||
ReferralNumber: store.getters.order.referralNumber,
|
ReferralNumber: store.getters.order.referralNumber,
|
||||||
ReferralDate: store.getters.order.referralDate,
|
ReferralDate: store.getters.order.referralDate,
|
||||||
ReferralCorrelationId: store.getters.order.referralCorrelationId,
|
ReferralCorrelationId: store.getters.order.referralCorrelationId,
|
||||||
ReferralParentAccountNumber: store.getters.order.accountNumber,
|
ReferralParentAccountNumber: store.getters.order.payment.parentAccountNumber,
|
||||||
HasDelayedClaimRegistration: wasClaimRegistrationDelayed,
|
HasDelayedClaimRegistration: wasClaimRegistrationDelayed,
|
||||||
SuppressConceptFunnel: shouldSuppressConceptFunnel,
|
SuppressConceptFunnel: shouldSuppressConceptFunnel,
|
||||||
SavedSessionId: store.getters.applicationUser.savedSessionId,
|
SavedSessionId: store.getters.applicationUser.savedSessionId,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,16 @@ import router from "@/router";
|
||||||
the user has an existing order and they come back in from the Safelite.com CTA.
|
the user has an existing order and they come back in from the Safelite.com CTA.
|
||||||
*/
|
*/
|
||||||
export async function getPageToRouteExistingOrderTo(toRoute = {}) {
|
export async function getPageToRouteExistingOrderTo(toRoute = {}) {
|
||||||
|
const fmgPage = getQuerystringParameter(queryStrings.FMG_PAGE.toLowerCase());
|
||||||
|
if (fmgPage && fmgPage === fmgPageValues.SERVICE_LOCATION) {
|
||||||
|
const serviceLocationComponent = await getLazyLoadedComponent(
|
||||||
|
fmgPageValues.SERVICE_LOCATION
|
||||||
|
);
|
||||||
|
if (serviceLocationComponent.methods.arePagePrerequisitesValid()) {
|
||||||
|
return fmgPageValues.SERVICE_LOCATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the user is coming in via the Safelite.Com CTA
|
// If the user is coming in via the Safelite.Com CTA
|
||||||
if (toRoute.query[queryStrings.START_TYPE] === "fmg") {
|
if (toRoute.query[queryStrings.START_TYPE] === "fmg") {
|
||||||
const latestPageRoute = await getLatestPageForRedirection();
|
const latestPageRoute = await getLatestPageForRedirection();
|
||||||
|
|
@ -26,12 +36,7 @@ export async function getPageToRouteExistingOrderTo(toRoute = {}) {
|
||||||
|
|
||||||
// If navigating to a specific page, and that page is not part of the vin pages.
|
// If navigating to a specific page, and that page is not part of the vin pages.
|
||||||
// Return that page, so that it can navigate like normal.
|
// Return that page, so that it can navigate like normal.
|
||||||
if (
|
if (toRoute.query[queryStrings.FMG_PAGE] !== undefined && !isVinRelatedPage(toRoute)) {
|
||||||
toRoute.query[queryStrings.FMG_PAGE] !== undefined &&
|
|
||||||
toRoute.query[queryStrings.FMG_PAGE] !== fmgPageValues.SERVICE_LOCATION &&
|
|
||||||
toRoute.query[queryStrings.FMG_PAGE] !== fmgPageValues.SCHEDULE &&
|
|
||||||
!isVinRelatedPage(toRoute)
|
|
||||||
) {
|
|
||||||
return overrideYmmsDirectionIfNeeded(toRoute);
|
return overrideYmmsDirectionIfNeeded(toRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
48
src/layouts/bailout/bailout.spec.js
Normal file
48
src/layouts/bailout/bailout.spec.js
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Components
|
||||||
|
import bailout from "@/layouts/bailout/bailout.vue";
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
|
||||||
|
// Mock our module for promises.
|
||||||
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
|
settleAllPromises: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Mock fetchCmsContentForPage
|
||||||
|
jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
|
fetchCmsContentForPage: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe("bailout.vue", () => {
|
||||||
|
test("arePagePrerequisitesValid should be true ", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
|
||||||
|
//Act
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupMocks() {
|
||||||
|
const mountOptions = getMountOptions({});
|
||||||
|
|
||||||
|
//Mock props
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mountOptions.mixins = [mockMixin];
|
||||||
|
const wrapper = shallowMount(bailout, mountOptions);
|
||||||
|
|
||||||
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
|
wrapper.vm.backButtonAction = jest.fn();
|
||||||
|
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
79
src/layouts/bailout/bailout.vue
Normal file
79
src/layouts/bailout/bailout.vue
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
<template>
|
||||||
|
<Form>
|
||||||
|
<loadingModal ref="loadingModal" />
|
||||||
|
<div class="container-fluid page-container-grouped-styles">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<vehicleBanner
|
||||||
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
||||||
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
isForwardActionDisabled="true"
|
||||||
|
isSubmitHidden="true"
|
||||||
|
@back-clicked="backButtonAction" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Components
|
||||||
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
|
|
||||||
|
// Supporting files
|
||||||
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "bailout",
|
||||||
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
// Call APIs
|
||||||
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [
|
||||||
|
{
|
||||||
|
resultKey: "cmsContent",
|
||||||
|
promise: cmsContentPromise,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
|
// Call the "next" function to complete the transition to this page.
|
||||||
|
next((vm) => {
|
||||||
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
backButtonAction() {
|
||||||
|
this.$router.go(-1);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
funnelHeader,
|
||||||
|
navbar,
|
||||||
|
vehicleBanner,
|
||||||
|
funnelSubHeader,
|
||||||
|
loadingModal,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
3
src/layouts/insurance/insurance.spec.js
Normal file
3
src/layouts/insurance/insurance.spec.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
describe("insurance", () => {
|
||||||
|
it.todo("Should render a normal string");
|
||||||
|
});
|
||||||
326
src/layouts/insurance/insurance.vue
Normal file
326
src/layouts/insurance/insurance.vue
Normal file
|
|
@ -0,0 +1,326 @@
|
||||||
|
<template>
|
||||||
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
|
<loadingModal ref="loadingModal" />
|
||||||
|
<div class="container-fluid page-container-grouped-styles">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-4" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
class="mb-2 mt-5"
|
||||||
|
cmsWidgetName="InsuranceCoQuestionWidget"
|
||||||
|
includeSearchIcon
|
||||||
|
cornerStyle="rounded" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Components
|
||||||
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
||||||
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
|
|
||||||
|
// Supporting files
|
||||||
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
|
import {
|
||||||
|
getDamageString,
|
||||||
|
getIsWindshieldOnly,
|
||||||
|
isGlassAvailableForCarId,
|
||||||
|
} from "@/helpers/damage-helper";
|
||||||
|
import { required, regex } from "@/helpers/validation-rules";
|
||||||
|
import { Form, defineRule } from "vee-validate";
|
||||||
|
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
import { routerParams } from "@/router/router-constants/router-params";
|
||||||
|
|
||||||
|
import store from "@/store";
|
||||||
|
import vinPagesMixin from "@/mixins/vin-pages-mixin";
|
||||||
|
|
||||||
|
// DEFINE VALIDATION RULES
|
||||||
|
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||||
|
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
|
||||||
|
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
|
||||||
|
defineRule(
|
||||||
|
"email-address-format",
|
||||||
|
regex(
|
||||||
|
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/,
|
||||||
|
errorMessages.EMAIL_ADDRESS_FORMAT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
defineRule("vin-required", required(errorMessages.VIN_REQUIRED));
|
||||||
|
defineRule("vin-format", regex(/^[a-hA-Hj-nJ-NpPr-zR-Z0-9]{17}$/, errorMessages.VIN_FORMAT));
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "insurance",
|
||||||
|
mixins: [vinPagesMixin],
|
||||||
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
// Call APIs
|
||||||
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [
|
||||||
|
{
|
||||||
|
resultKey: "cmsContent",
|
||||||
|
promise: cmsContentPromise,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
|
// Call the "next" function to complete the transition to this page.
|
||||||
|
next((vm) => {
|
||||||
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
vin: this.getVinFromStore(),
|
||||||
|
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
|
||||||
|
emailAddress: this.getEmailFromStore(),
|
||||||
|
isCarIdDifferent: false,
|
||||||
|
customAlertData: {},
|
||||||
|
previouslyEnteredCarId: "",
|
||||||
|
vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
|
||||||
|
isSelectedGlassAvailableForVehicle: true,
|
||||||
|
displayInvalidZipAlert: false,
|
||||||
|
displayNonServiceableZipAlert: false,
|
||||||
|
displayVinNotFoundAlert: false,
|
||||||
|
displayMatchedDifferentVehicleAlert: false,
|
||||||
|
displayVinScanFailedAlert: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
return store.getters.vehicle.carId !== null;
|
||||||
|
},
|
||||||
|
getEmailFromStore() {
|
||||||
|
return this.$store.getters.order.customer.emailAddress;
|
||||||
|
},
|
||||||
|
getVinFromStore() {
|
||||||
|
return this.$store.getters.vehicle.vin;
|
||||||
|
},
|
||||||
|
getZipFromStore() {
|
||||||
|
return this.$store.getters.order.serviceLocation.zipCode;
|
||||||
|
},
|
||||||
|
attachCustomEvents() {
|
||||||
|
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||||
|
this.GaActions.SUBMITTED,
|
||||||
|
this.GaLabels.VIN_LOOKUP,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
backButtonAction() {
|
||||||
|
// route to move backwards
|
||||||
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
},
|
||||||
|
async forwardButtonAction() {
|
||||||
|
this.resetAlerts();
|
||||||
|
|
||||||
|
// If this is a new VIN Lookup, do both a Vehicle Lookup and a Zip Validation
|
||||||
|
if (!this.vinPopulatedOnPageLoad) {
|
||||||
|
const vehicleLookupResponse = this.dispatchStoreActionWithLogging(
|
||||||
|
storeActions.LOOKUP_VEHICLE_BY_VIN,
|
||||||
|
{ vin: this.vin },
|
||||||
|
"vin-lookup"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [
|
||||||
|
{
|
||||||
|
resultKey: "vehicleLookupResponse",
|
||||||
|
promise: vehicleLookupResponse,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: "zipCodeData",
|
||||||
|
promise: this.getZipCodeData(this.serviceZipCode),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
|
// If a Service Zip is entered and it is an invalid zip code (ex. 11111) then show an alert
|
||||||
|
const isZipValid = resultMap.zipCodeData.isValid;
|
||||||
|
if (this.serviceZipCode && !isZipValid) {
|
||||||
|
this.displayInvalidZipAlert = true;
|
||||||
|
return this.$refs.navbar.removeLoader();
|
||||||
|
}
|
||||||
|
this.displayInvalidZipAlert = false;
|
||||||
|
|
||||||
|
// If either lookup fails, remove the loader and stop processing the page.
|
||||||
|
if (!resultMap.vehicleLookupResponse || !resultMap.zipCodeData.isServiceable) {
|
||||||
|
// If the vehicle result is undefined, the vin entered was invalid.
|
||||||
|
if (!resultMap.vehicleLookupResponse) {
|
||||||
|
this.displayVinNotFoundAlert = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if Service Zip entered is serviceable, if not display an alert
|
||||||
|
if (!resultMap.zipCodeData.isServiceable) {
|
||||||
|
this.displayNonServiceableZipAlert = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove loader and stop processing the page.
|
||||||
|
return this.$refs.navbar.removeLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the CarId is different from the lookup vs what is in state currently.
|
||||||
|
this.isCarIdDifferent =
|
||||||
|
resultMap.vehicleLookupResponse.carId !== this.$store.getters.vehicle.carId;
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.isCarIdDifferent &&
|
||||||
|
resultMap.vehicleLookupResponse.carId !== this.previouslyEnteredCarId
|
||||||
|
) {
|
||||||
|
this.previouslyEnteredCarId = resultMap.vehicleLookupResponse.carId;
|
||||||
|
this.customAlertData.vehicleInfo = resultMap.vehicleLookupResponse;
|
||||||
|
this.displayMatchedDifferentVehicleAlert = true;
|
||||||
|
|
||||||
|
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
|
||||||
|
resultMap.vehicleLookupResponse.carId,
|
||||||
|
"vin-lookup"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update button "Continue with..."
|
||||||
|
this.$refs.navbar.updateButtonText(
|
||||||
|
`Continue with ${resultMap.vehicleLookupResponse.year} ${resultMap.vehicleLookupResponse.make} ${resultMap.vehicleLookupResponse.model}`
|
||||||
|
);
|
||||||
|
return this.$refs.navbar.removeLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save vin, vehicle, customer and service information
|
||||||
|
await this.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_VIN_LOOKUP,
|
||||||
|
{
|
||||||
|
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||||
|
vehicleInfo: Object.assign(resultMap.vehicleLookupResponse, {
|
||||||
|
vin: this.vin,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false);
|
||||||
|
await this.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
state: resultMap.zipCodeData.state,
|
||||||
|
zipCode: this.serviceZipCode,
|
||||||
|
zipCodeCtu: resultMap.zipCodeData.zipCodeCtu,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
return await this.navigateForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a VIN has already been found. Validate the Service Zip (in case of changes)
|
||||||
|
const zipCodeData = await this.getZipCodeData(this.serviceZipCode);
|
||||||
|
|
||||||
|
// Check if Service Zip entered is serviceable then save the ZIP info
|
||||||
|
if (zipCodeData.isServiceable) {
|
||||||
|
//Only save the zipCode, state, and zipCodeCtu if the zip changed or we lack zipCodeCtu
|
||||||
|
if (
|
||||||
|
this.$store.getters.order.serviceLocation.zipCode != this.serviceZipCode ||
|
||||||
|
!this.$store.getters.order.serviceLocation.zipCodeCtu
|
||||||
|
) {
|
||||||
|
await this.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
state: zipCodeData.state,
|
||||||
|
zipCode: this.serviceZipCode,
|
||||||
|
zipCodeCtu: zipCodeData.zipCodeCtu,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false);
|
||||||
|
|
||||||
|
return await this.navigateForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Service Zip is NOT serviceable then show an alert
|
||||||
|
if (zipCodeData.isValid) {
|
||||||
|
this.displayNonServiceableZipAlert = true;
|
||||||
|
} else {
|
||||||
|
this.displayInvalidZipAlert = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.$refs.navbar.removeLoader();
|
||||||
|
},
|
||||||
|
async navigateForward() {
|
||||||
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
|
this.$router.navigateWithSaving(
|
||||||
|
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||||
|
this.$route,
|
||||||
|
{},
|
||||||
|
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await this.navigateForwardWithSingleCarMatch();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
displayVinScanAlert() {
|
||||||
|
this.displayVinScanFailedAlert = true;
|
||||||
|
},
|
||||||
|
getVinFromImage(image) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.dispatchStoreActionWithLogging(
|
||||||
|
storeActions.LOOKUP_VIN_BY_IMAGE,
|
||||||
|
image,
|
||||||
|
"vin-lookup"
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.data.length > 0) {
|
||||||
|
resolve(response.data[0]);
|
||||||
|
} else {
|
||||||
|
reject("No VINs detected.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
reject("An error occurred during the lookup.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
resetAlerts() {
|
||||||
|
this.displayMatchedDifferentVehicleAlert = false;
|
||||||
|
this.displayNonServiceableZipAlert = false;
|
||||||
|
this.displayInvalidZipAlert = false;
|
||||||
|
this.displayVinNotFoundAlert = false;
|
||||||
|
this.displayVinScanFailedAlert = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.attachCustomEvents();
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
funnelHeader,
|
||||||
|
navbar,
|
||||||
|
funnelSubHeader,
|
||||||
|
textboxQuestion,
|
||||||
|
Form,
|
||||||
|
loadingModal,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -237,7 +237,7 @@ export default {
|
||||||
const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
|
const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||||
{
|
{
|
||||||
billToAccountNumber: "87291",
|
billToAccountNumber: store.getters.payment.billToAccountNumber,
|
||||||
providerNumber: store.getters.order.serviceLocation.provider.providerNumber,
|
providerNumber: store.getters.order.serviceLocation.provider.providerNumber,
|
||||||
appointmentType: store.getters.order.serviceLocation.appointmentType,
|
appointmentType: store.getters.order.serviceLocation.appointmentType,
|
||||||
serviceLocationCity: store.getters.order.serviceLocation.city,
|
serviceLocationCity: store.getters.order.serviceLocation.city,
|
||||||
|
|
@ -307,9 +307,6 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
// Line Items
|
|
||||||
const packageReqs = !!store.getters.order.lineItems.supportingItems;
|
|
||||||
|
|
||||||
// Service Location
|
// Service Location
|
||||||
const serviceLocation = store.getters.order.serviceLocation;
|
const serviceLocation = store.getters.order.serviceLocation;
|
||||||
const mobileReqs = !!(
|
const mobileReqs = !!(
|
||||||
|
|
@ -354,9 +351,7 @@ export default {
|
||||||
customer.emailAddress
|
customer.emailAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return serviceLocationReqs && isInsuranceSet && scheduleReqs && customerReqs;
|
||||||
packageReqs && serviceLocationReqs && isInsuranceSet && scheduleReqs && customerReqs
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
getPaymentMethodFromStore() {
|
getPaymentMethodFromStore() {
|
||||||
const piaType = store.getters.order.payment.piaType;
|
const piaType = store.getters.order.payment.piaType;
|
||||||
|
|
@ -398,7 +393,7 @@ export default {
|
||||||
await baseMixin.methods.dispatchStoreActionWithLogging(
|
await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||||
{
|
{
|
||||||
billToAccountNumber: "87291",
|
billToAccountNumber: store.getters.payment.billToAccountNumber,
|
||||||
providerNumber:
|
providerNumber:
|
||||||
this.$store.getters.order.serviceLocation.provider.providerNumber,
|
this.$store.getters.order.serviceLocation.provider.providerNumber,
|
||||||
appointmentType: this.$store.getters.order.serviceLocation.appointmentType,
|
appointmentType: this.$store.getters.order.serviceLocation.appointmentType,
|
||||||
|
|
|
||||||
|
|
@ -512,7 +512,7 @@ describe("payment.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("handleIFrameContentWindwMessage", () => {
|
describe("handleIFrameContentWindowMessage", () => {
|
||||||
test("Navigates back if afterpay is closed", () => {
|
test("Navigates back if afterpay is closed", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const event = {
|
const event = {
|
||||||
|
|
@ -524,7 +524,7 @@ describe("payment.vue", () => {
|
||||||
wrapper.vm.backButtonAction = jest.fn();
|
wrapper.vm.backButtonAction = jest.fn();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.handleIFrameContentWindwMessage(event);
|
wrapper.vm.handleIFrameContentWindowMessage(event);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.backButtonAction).toBeCalled();
|
expect(wrapper.vm.backButtonAction).toBeCalled();
|
||||||
|
|
@ -539,7 +539,7 @@ describe("payment.vue", () => {
|
||||||
const wrapper = setupMocks({});
|
const wrapper = setupMocks({});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.handleIFrameContentWindwMessage(event);
|
wrapper.vm.handleIFrameContentWindowMessage(event);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.vm.shouldBlockInteraction).toBe(true);
|
expect(wrapper.vm.shouldBlockInteraction).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ export default {
|
||||||
const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
|
const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||||
{
|
{
|
||||||
billToAccountNumber: "87291",
|
billToAccountNumber: store.getters.payment.billToAccountNumber,
|
||||||
providerNumber: store.getters.order.serviceLocation.provider.providerNumber,
|
providerNumber: store.getters.order.serviceLocation.provider.providerNumber,
|
||||||
appointmentType: store.getters.order.serviceLocation.appointmentType,
|
appointmentType: store.getters.order.serviceLocation.appointmentType,
|
||||||
serviceLocationCity: store.getters.order.serviceLocation.city,
|
serviceLocationCity: store.getters.order.serviceLocation.city,
|
||||||
|
|
@ -440,9 +440,6 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
// Line Items
|
|
||||||
const packageReqs = !!store.getters.order.lineItems.supportingItems;
|
|
||||||
|
|
||||||
// Service Location
|
// Service Location
|
||||||
const serviceLocation = store.getters.order.serviceLocation;
|
const serviceLocation = store.getters.order.serviceLocation;
|
||||||
const mobileReqs = !!(
|
const mobileReqs = !!(
|
||||||
|
|
@ -492,7 +489,6 @@ export default {
|
||||||
(store.getters.order.payment.isPia || !!store.getters.order.payment.piaType);
|
(store.getters.order.payment.isPia || !!store.getters.order.payment.piaType);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
packageReqs &&
|
|
||||||
serviceLocationReqs &&
|
serviceLocationReqs &&
|
||||||
isInsuranceSet &&
|
isInsuranceSet &&
|
||||||
scheduleReqs &&
|
scheduleReqs &&
|
||||||
|
|
@ -647,17 +643,19 @@ export default {
|
||||||
|
|
||||||
this.submitHopForm();
|
this.submitHopForm();
|
||||||
},
|
},
|
||||||
handleIFrameContentWindwMessage(event) {
|
handleIFrameContentWindowMessage(event) {
|
||||||
if (event.data.indexOf("afterpayClosed") > -1) {
|
if (typeof event.data === "string") {
|
||||||
this.backButtonAction();
|
if (event.data.indexOf("afterpayClosed") > -1) {
|
||||||
}
|
this.backButtonAction();
|
||||||
if (event.data.indexOf("creditCardSubmit") > -1) {
|
}
|
||||||
this.setUIBlock(true);
|
if (event.data.indexOf("creditCardSubmit") > -1) {
|
||||||
|
this.setUIBlock(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setIFrameListener() {
|
setIFrameListener() {
|
||||||
window.addEventListener("message", (event) =>
|
window.addEventListener("message", (event) =>
|
||||||
this.handleIFrameContentWindwMessage(event)
|
this.handleIFrameContentWindowMessage(event)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
setUIBlock(val) {
|
setUIBlock(val) {
|
||||||
|
|
|
||||||
|
|
@ -140,42 +140,6 @@ describe("quote.vue", () => {
|
||||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("IsInsurance true should navigateToHeritageFunnel", async () => {
|
|
||||||
//Arrange
|
|
||||||
store.getters = {
|
|
||||||
payment: {
|
|
||||||
insuranceCoverage: {},
|
|
||||||
isInsurance: true,
|
|
||||||
},
|
|
||||||
order: {
|
|
||||||
lineItems: [],
|
|
||||||
payment: {
|
|
||||||
parentAccountNumber: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const { wrapper } = setupMocks({
|
|
||||||
customMountOptions: {
|
|
||||||
router: {
|
|
||||||
navigateWithSaving: jest.fn(),
|
|
||||||
},
|
|
||||||
route: { quote },
|
|
||||||
mixins: [mockMixin],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
|
||||||
return {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
//Act
|
|
||||||
await wrapper.vm.forwardButtonAction();
|
|
||||||
|
|
||||||
//Assert
|
|
||||||
expect(navigateToHeritage.navigateToHeritageFunnel).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
test("should pass arePagePrerequisitesValid with a repair order", () => {
|
test("should pass arePagePrerequisitesValid with a repair order", () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
store.getters = {
|
store.getters = {
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,11 @@ export default {
|
||||||
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
this.dispatchStoreAction(
|
||||||
|
this.storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
||||||
|
applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|
@ -327,6 +332,10 @@ export default {
|
||||||
pageNameToLog: "quote",
|
pageNameToLog: "quote",
|
||||||
loadingModal: this.$refs.loadingModal,
|
loadingModal: this.$refs.loadingModal,
|
||||||
});
|
});
|
||||||
|
// this.$router.navigateWithSaving(
|
||||||
|
// this.navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
|
||||||
|
// this.$route
|
||||||
|
// );
|
||||||
} else {
|
} else {
|
||||||
this.$router.navigateWithSaving(
|
this.$router.navigateWithSaving(
|
||||||
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
activePromos() {
|
activePromos() {
|
||||||
this.selectDefaultPackage();
|
if (this.activePromos?.length) this.selectDefaultPackage();
|
||||||
},
|
},
|
||||||
selectedPackageName(newValue) {
|
selectedPackageName(newValue) {
|
||||||
const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
|
const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
|
||||||
|
|
|
||||||
|
|
@ -314,14 +314,13 @@ export default {
|
||||||
serviceLocation.provider.providerNumber);
|
serviceLocation.provider.providerNumber);
|
||||||
|
|
||||||
const paymentInfo = store.getters.payment.isInsurance !== null;
|
const paymentInfo = store.getters.payment.isInsurance !== null;
|
||||||
const supportingItems = store.getters.lineItems.supportingItems !== null;
|
|
||||||
|
|
||||||
const damageInfo =
|
const damageInfo =
|
||||||
store.getters.order.damage.isRepair ||
|
store.getters.order.damage.isRepair ||
|
||||||
(store.getters.order.lineItems?.glassParts != null &&
|
(store.getters.order.lineItems?.glassParts != null &&
|
||||||
store.getters.order.lineItems.glassParts.length > 0);
|
store.getters.order.lineItems.glassParts.length > 0);
|
||||||
|
|
||||||
return serviceLocationPreReqs && paymentInfo && supportingItems && damageInfo;
|
return serviceLocationPreReqs && paymentInfo && damageInfo;
|
||||||
},
|
},
|
||||||
async getAvailableDatesMethod(startDate, endDate) {
|
async getAvailableDatesMethod(startDate, endDate) {
|
||||||
const newShopTimeSlots = await getAvailableDates(
|
const newShopTimeSlots = await getAvailableDates(
|
||||||
|
|
@ -348,9 +347,14 @@ export default {
|
||||||
},
|
},
|
||||||
getSelectedTimeSlotInfo() {
|
getSelectedTimeSlotInfo() {
|
||||||
const supportingItems = this.getSupportingItems();
|
const supportingItems = this.getSupportingItems();
|
||||||
const isPremiumAppointment =
|
|
||||||
!!supportingItems.filter((lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE)
|
var isPremiumAppointment = false;
|
||||||
.length > 0;
|
if (supportingItems) {
|
||||||
|
isPremiumAppointment =
|
||||||
|
!!supportingItems.filter(
|
||||||
|
(lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE
|
||||||
|
).length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
const selectedTimeSlotInfo = {
|
const selectedTimeSlotInfo = {
|
||||||
timeSlot: store.getters.order.schedule,
|
timeSlot: store.getters.order.schedule,
|
||||||
|
|
@ -461,6 +465,10 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
if (!supportingItems) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// if it's not a mobile and/or premium early bird, then make sure we remove any that may have been added
|
// if it's not a mobile and/or premium early bird, then make sure we remove any that may have been added
|
||||||
const removePremiumFeeIndex = supportingItems.findIndex(
|
const removePremiumFeeIndex = supportingItems.findIndex(
|
||||||
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,14 @@ export async function getPricedMobileFeePart(serviceZipCode, pageNameToLog) {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
mobileFeePart.data === null ||
|
||||||
|
mobileFeePart.data === undefined ||
|
||||||
|
mobileFeePart.data === ""
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the Mobile Fee Part Price
|
// Get the Mobile Fee Part Price
|
||||||
const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
|
const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ import {
|
||||||
getServiceabilityDetails,
|
getServiceabilityDetails,
|
||||||
getShopProviderData,
|
getShopProviderData,
|
||||||
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||||
|
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
|
|
||||||
import { Provider } from "@/layouts/service-location/classes/provider";
|
import { Provider } from "@/layouts/service-location/classes/provider";
|
||||||
|
|
||||||
|
|
@ -348,11 +349,19 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
return (
|
// insurance drops the recycle fee on replace orders so it won't be in supportingItems
|
||||||
store.getters.lineItems.supportingItems !== null &&
|
if (store.getters.payment.isInsurance && !store.getters.order.damage.isRepair) {
|
||||||
store.getters.order.serviceLocation.zipCode !== null &&
|
return (
|
||||||
store.getters.payment.isInsurance !== null
|
store.getters.order.serviceLocation.zipCode !== null &&
|
||||||
);
|
store.getters.payment.isInsurance !== null
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
store.getters.lineItems.supportingItems !== null &&
|
||||||
|
store.getters.order.serviceLocation.zipCode !== null &&
|
||||||
|
store.getters.payment.isInsurance !== null
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setData(zipCodeData, serviceabilityDetails, mobileFeePart, shopProviderData) {
|
setData(zipCodeData, serviceabilityDetails, mobileFeePart, shopProviderData) {
|
||||||
if (zipCodeData) {
|
if (zipCodeData) {
|
||||||
|
|
@ -438,7 +447,14 @@ export default {
|
||||||
this.recalibrationInformationModal.openModal();
|
this.recalibrationInformationModal.openModal();
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
if (store.getters.order.payment.isInsurance) {
|
||||||
|
navigateToHeritageFunnel({ shouldSaveSession: false });
|
||||||
|
} else {
|
||||||
|
this.$router.navigateWithoutSaving(
|
||||||
|
this.navigationScenarios.CLICKED_BACK,
|
||||||
|
this.$route
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateAndSaveSupportingItems() {
|
updateAndSaveSupportingItems() {
|
||||||
const supportingItems = store.getters.lineItems.supportingItems;
|
const supportingItems = store.getters.lineItems.supportingItems;
|
||||||
|
|
@ -453,7 +469,7 @@ export default {
|
||||||
supportingItems[mobileFeeIndex].sellingPrice = this.mobileFeePart.sellingPrice;
|
supportingItems[mobileFeeIndex].sellingPrice = this.mobileFeePart.sellingPrice;
|
||||||
supportingItems[mobileFeeIndex].kitPrice = this.mobileFeePart.kitPrice;
|
supportingItems[mobileFeeIndex].kitPrice = this.mobileFeePart.kitPrice;
|
||||||
} else {
|
} else {
|
||||||
supportingItems.push(this.mobileFeePart);
|
if (this.mobileFeePart !== null) supportingItems.push(this.mobileFeePart);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
|
|
@ -463,7 +479,7 @@ export default {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// if it's not a mobile, then make sure we remove any that may have been added
|
// if it's not a mobile, then make sure we remove any that may have been added
|
||||||
const removeMobileFeeIndex = supportingItems.findIndex(
|
const removeMobileFeeIndex = supportingItems?.findIndex(
|
||||||
(item) => item.partType == MOBILE_FEE_PART_TYPE
|
(item) => item.partType == MOBILE_FEE_PART_TYPE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,19 +95,14 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
tintSelectionOptions() {
|
tintSelectionOptions() {
|
||||||
let tintOptions = [];
|
const tintOptions = Object.keys(this.featureListData).map((tintOption) => {
|
||||||
|
const buttonImage = this.getTintSourceImage(this.glassLocation, tintOption);
|
||||||
Object.keys(this.featureListData).forEach((tintOption) => {
|
return {
|
||||||
tintOptions.push({
|
|
||||||
value: tintOption,
|
value: tintOption,
|
||||||
buttonLabel: tintOption,
|
buttonLabel: tintOption,
|
||||||
buttonImage: require(`@/assets/img/tints/${this.getTintSourceImage(
|
buttonImage: buttonImage ? require(`@/assets/img/tints/${buttonImage}`) : null,
|
||||||
this.glassLocation,
|
};
|
||||||
tintOption
|
|
||||||
)}`),
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return tintOptions;
|
return tintOptions;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,14 @@ import analyticsMixin from "@/mixins/analytics-mixin";
|
||||||
import { experimentTriggers } from "../constants/experiments";
|
import { experimentTriggers } from "../constants/experiments";
|
||||||
import { applicationConfig } from "../constants/application-config";
|
import { applicationConfig } from "../constants/application-config";
|
||||||
import { shouldStripPromoQueryString } from "@/helpers/promotions-helper";
|
import { shouldStripPromoQueryString } from "@/helpers/promotions-helper";
|
||||||
|
import bailout from "@/layouts/bailout/bailout";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
|
{
|
||||||
|
path: "/bailout",
|
||||||
|
name: "bailout",
|
||||||
|
component: bailout,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
name: "root",
|
name: "root",
|
||||||
|
|
@ -103,6 +109,7 @@ const routes = [
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arePagePrerequisitesValid(component)) {
|
if (!arePagePrerequisitesValid(component)) {
|
||||||
|
console.log("Page prereq error: " + component.default.name);
|
||||||
GoToFunnelStartOn404(next);
|
GoToFunnelStartOn404(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,6 +117,7 @@ const routes = [
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isExistingFmgPageName(to.query.fmgPage)) {
|
if (!isExistingFmgPageName(to.query.fmgPage)) {
|
||||||
|
console.log("Not an existing fmg page name:" + to.query.fmgPage);
|
||||||
GoToFunnelStartOn404(next);
|
GoToFunnelStartOn404(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,6 +139,9 @@ const routes = [
|
||||||
.components.default();
|
.components.default();
|
||||||
|
|
||||||
if (!arePagePrerequisitesValid(nextComponent)) {
|
if (!arePagePrerequisitesValid(nextComponent)) {
|
||||||
|
console.log(
|
||||||
|
"Page Prereqs not valid for next component: " + nextComponent.default.name
|
||||||
|
);
|
||||||
GoToFunnelStartOn404(next);
|
GoToFunnelStartOn404(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,6 +335,7 @@ async function navigate(
|
||||||
const hasZip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
const hasZip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
||||||
const zip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
const zip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
||||||
const promo = getQuerystringParameter(queryStrings.PROMO);
|
const promo = getQuerystringParameter(queryStrings.PROMO);
|
||||||
|
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasZip &&
|
hasZip &&
|
||||||
|
|
@ -339,6 +351,10 @@ async function navigate(
|
||||||
queryStringsObject[queryStrings.PROMO] = promo;
|
queryStringsObject[queryStrings.PROMO] = promo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pageError) {
|
||||||
|
queryStringsObject[queryStrings.PAGE_ERROR] = pageError;
|
||||||
|
}
|
||||||
|
|
||||||
router.push({
|
router.push({
|
||||||
name: "root",
|
name: "root",
|
||||||
query: Object.assign(optionalQuery, queryStringsObject),
|
query: Object.assign(optionalQuery, queryStringsObject),
|
||||||
|
|
@ -431,7 +447,38 @@ async function DisplayPageError() {
|
||||||
);
|
);
|
||||||
|
|
||||||
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||||
location.reload();
|
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
|
||||||
|
|
||||||
|
// we use the pageError querystring as a counter to how many times a user has experienced an error and been routed here.
|
||||||
|
// once they receive more than 1 pageerrors, we'll reset their state to hopefully correct any issues they may be having.
|
||||||
|
var navPage = fmgPageValues.VEHICLE;
|
||||||
|
if (store.getters.payment.insuranceCoverage.isVerified) {
|
||||||
|
navPage = fmgPageValues.VEHICLE_DAMAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageError) {
|
||||||
|
var errorCount = Number(pageError);
|
||||||
|
if (errorCount > 1) {
|
||||||
|
deleteFunnelCookie();
|
||||||
|
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
|
||||||
|
|
||||||
|
router.push({
|
||||||
|
path: "/",
|
||||||
|
query: { fmgPage: navPage },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
errorCount++;
|
||||||
|
router.push({
|
||||||
|
path: "/",
|
||||||
|
query: { fmgPage: navPage, pageError: errorCount },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
router.push({
|
||||||
|
path: "/",
|
||||||
|
query: { fmgPage: navPage, pageError: "1" },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isExistingFmgPageName(pageName) {
|
function isExistingFmgPageName(pageName) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ const fmgPageValues = {
|
||||||
ESTIMATE: "estimate",
|
ESTIMATE: "estimate",
|
||||||
ADDRESS_VEHICLES: "address-vehicles",
|
ADDRESS_VEHICLES: "address-vehicles",
|
||||||
QUOTE: "quote",
|
QUOTE: "quote",
|
||||||
|
INSURANCE: "insurance",
|
||||||
SERVICE_LOCATION: "service-location",
|
SERVICE_LOCATION: "service-location",
|
||||||
HERITAGE: "heritage",
|
HERITAGE: "heritage",
|
||||||
SCHEDULE: "schedule",
|
SCHEDULE: "schedule",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ const navigationScenarios = {
|
||||||
CLICKED_BACK: "CLICKED_BACK",
|
CLICKED_BACK: "CLICKED_BACK",
|
||||||
CLICKED_FORWARD: "CLICKED_FORWARD",
|
CLICKED_FORWARD: "CLICKED_FORWARD",
|
||||||
CLICKED_FORWARD_WITH_CASH: "CLICKED_FORWARD_WITH_CASH",
|
CLICKED_FORWARD_WITH_CASH: "CLICKED_FORWARD_WITH_CASH",
|
||||||
|
CLICKED_FORWARD_WITH_INSURANCE: "CLICKED_FORWARD_WITH_INSURANCE",
|
||||||
|
|
||||||
// Vin selection
|
// Vin selection
|
||||||
CLICKED_BACK_WITH_VIN: "CLICKED_BACK_WITH_VIN",
|
CLICKED_BACK_WITH_VIN: "CLICKED_BACK_WITH_VIN",
|
||||||
|
|
|
||||||
|
|
@ -389,6 +389,23 @@ const routingTable = function (store) {
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
||||||
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
|
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
|
||||||
|
destinationFmgPageValue: fmgPageValues.INSURANCE,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fmgPageValue: fmgPageValues.INSURANCE,
|
||||||
|
maps: [
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
|
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||||
|
destinationFmgPageValue: fmgPageValues.SCHEDULE,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import {
|
||||||
} from "@/helpers/promotions-helper";
|
} from "@/helpers/promotions-helper";
|
||||||
import { getDateDifferenceInDays } from "@/helpers/date-helper";
|
import { getDateDifferenceInDays } from "@/helpers/date-helper";
|
||||||
import sharedMutations from "./vuex-shared-mutations/vuexSharedMutations";
|
import sharedMutations from "./vuex-shared-mutations/vuexSharedMutations";
|
||||||
|
import { coverageStatusValue } from "@/constants/coverage-status";
|
||||||
// Export State
|
// Export State
|
||||||
const getDefaultState = () => {
|
const getDefaultState = () => {
|
||||||
return {
|
return {
|
||||||
|
|
@ -83,6 +84,8 @@ const getDefaultState = () => {
|
||||||
partQuestionAnswers: null,
|
partQuestionAnswers: null,
|
||||||
moldingQuestionAnswers: null,
|
moldingQuestionAnswers: null,
|
||||||
capabilityQuestionAnswers: null,
|
capabilityQuestionAnswers: null,
|
||||||
|
dateOfLoss: null,
|
||||||
|
damageCause: null,
|
||||||
},
|
},
|
||||||
lineItems: {
|
lineItems: {
|
||||||
glassParts: null,
|
glassParts: null,
|
||||||
|
|
@ -99,6 +102,7 @@ const getDefaultState = () => {
|
||||||
coverageVerificationType: null,
|
coverageVerificationType: null,
|
||||||
},
|
},
|
||||||
parentAccountNumber: 0,
|
parentAccountNumber: 0,
|
||||||
|
billToAccountNumber: null,
|
||||||
isPia: null,
|
isPia: null,
|
||||||
piaType: null,
|
piaType: null,
|
||||||
inactivePromos: null,
|
inactivePromos: null,
|
||||||
|
|
@ -118,6 +122,14 @@ const getDefaultState = () => {
|
||||||
lastFour: null,
|
lastFour: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
policy: {
|
||||||
|
currentDeductible: 0,
|
||||||
|
policyNumber: null,
|
||||||
|
isItac: false,
|
||||||
|
additionalAuthFlag: null,
|
||||||
|
isNoComp: false,
|
||||||
|
insuranceCompanyName: null,
|
||||||
|
},
|
||||||
schedule: {
|
schedule: {
|
||||||
date: null,
|
date: null,
|
||||||
startTime: null,
|
startTime: null,
|
||||||
|
|
@ -240,6 +252,9 @@ export const mutations = {
|
||||||
updateParentAcctNumber(state, parentAcctNumber) {
|
updateParentAcctNumber(state, parentAcctNumber) {
|
||||||
state.order.payment.parentAccountNumber = parentAcctNumber;
|
state.order.payment.parentAccountNumber = parentAcctNumber;
|
||||||
},
|
},
|
||||||
|
updateBillToAcctNumber(state, billToAcctNumber) {
|
||||||
|
state.order.payment.billToAccountNumber = billToAcctNumber;
|
||||||
|
},
|
||||||
updateEON(state, eon) {
|
updateEON(state, eon) {
|
||||||
state.order.eon = eon;
|
state.order.eon = eon;
|
||||||
},
|
},
|
||||||
|
|
@ -499,6 +514,8 @@ export const mutations = {
|
||||||
state.order.damage.glassToReplace = sessionInformation.order.damage.glassToReplace;
|
state.order.damage.glassToReplace = sessionInformation.order.damage.glassToReplace;
|
||||||
state.order.damage.isRepair = sessionInformation.order.damage.isRepair;
|
state.order.damage.isRepair = sessionInformation.order.damage.isRepair;
|
||||||
state.order.damage.numberOfChips = sessionInformation.order.damage.numberOfChips;
|
state.order.damage.numberOfChips = sessionInformation.order.damage.numberOfChips;
|
||||||
|
state.order.damage.dateOfLoss = sessionInformation.order.damage?.dateOfLoss;
|
||||||
|
state.order.damage.damageCause = sessionInformation.order.damage?.damageCause;
|
||||||
|
|
||||||
state.order.damage.partQuestionAnswers =
|
state.order.damage.partQuestionAnswers =
|
||||||
sessionInformation.order.damage.partQuestionAnswers;
|
sessionInformation.order.damage.partQuestionAnswers;
|
||||||
|
|
@ -515,6 +532,8 @@ export const mutations = {
|
||||||
|
|
||||||
state.order.payment.parentAccountNumber =
|
state.order.payment.parentAccountNumber =
|
||||||
sessionInformation.order.payment.parentAccountNumber;
|
sessionInformation.order.payment.parentAccountNumber;
|
||||||
|
state.order.payment.billToAccountNumber =
|
||||||
|
sessionInformation.order.payment.billToAccountNumber;
|
||||||
state.order.payment.inactivePromos = sessionInformation.order.payment.inactivePromos;
|
state.order.payment.inactivePromos = sessionInformation.order.payment.inactivePromos;
|
||||||
|
|
||||||
state.order.serviceLocation.address =
|
state.order.serviceLocation.address =
|
||||||
|
|
@ -549,8 +568,9 @@ export const mutations = {
|
||||||
state.order.payment.isInsurance = sessionInformation.order.payment.isInsurance;
|
state.order.payment.isInsurance = sessionInformation.order.payment.isInsurance;
|
||||||
state.order.payment.insuranceCoverage.isVerified =
|
state.order.payment.insuranceCoverage.isVerified =
|
||||||
sessionInformation?.order.payment.insuranceCoverage.isVerified;
|
sessionInformation?.order.payment.insuranceCoverage.isVerified;
|
||||||
state.order.payment.insuranceCoverage.coverageStatus =
|
state.order.payment.insuranceCoverage.coverageStatus = coverageStatusValue(
|
||||||
sessionInformation?.order.payment.insuranceCoverage.coverageStatus;
|
sessionInformation?.order.payment.insuranceCoverage.coverageStatus
|
||||||
|
);
|
||||||
state.order.payment.insuranceCoverage.coverageVerificationType =
|
state.order.payment.insuranceCoverage.coverageVerificationType =
|
||||||
sessionInformation?.order.payment.insuranceCoverage.coverageVerificationType;
|
sessionInformation?.order.payment.insuranceCoverage.coverageVerificationType;
|
||||||
|
|
||||||
|
|
@ -565,12 +585,25 @@ export const mutations = {
|
||||||
state.applicationUser.pageData = sessionInformation.applicationUser.pageData;
|
state.applicationUser.pageData = sessionInformation.applicationUser.pageData;
|
||||||
state.applicationUser.lastPage = sessionInformation.applicationUser.lastPage;
|
state.applicationUser.lastPage = sessionInformation.applicationUser.lastPage;
|
||||||
|
|
||||||
|
if (sessionInformation.applicationUser.savedSessionId) {
|
||||||
|
state.applicationUser.savedSessionId =
|
||||||
|
sessionInformation.applicationUser.savedSessionId;
|
||||||
|
}
|
||||||
|
|
||||||
state.order.schedule.date = sessionInformation.order.schedule?.date;
|
state.order.schedule.date = sessionInformation.order.schedule?.date;
|
||||||
state.order.schedule.startTime = sessionInformation.order.schedule?.startTime;
|
state.order.schedule.startTime = sessionInformation.order.schedule?.startTime;
|
||||||
state.order.schedule.endTime = sessionInformation.order.schedule?.endTime;
|
state.order.schedule.endTime = sessionInformation.order.schedule?.endTime;
|
||||||
state.order.schedule.routeCode = sessionInformation.order.schedule?.routeCode;
|
state.order.schedule.routeCode = sessionInformation.order.schedule?.routeCode;
|
||||||
state.order.schedule.jobMaxMinutes = sessionInformation.order.schedule?.jobMaxMinutes;
|
state.order.schedule.jobMaxMinutes = sessionInformation.order.schedule?.jobMaxMinutes;
|
||||||
state.order.schedule.jobMinMinutes = sessionInformation.order.schedule?.jobMinMinutes;
|
state.order.schedule.jobMinMinutes = sessionInformation.order.schedule?.jobMinMinutes;
|
||||||
|
|
||||||
|
state.order.policy.currentDeductible = sessionInformation.order.policy?.currentDeductible;
|
||||||
|
state.order.policy.additionalAuthFlag = sessionInformation.order.policy?.additionalAuthFlag;
|
||||||
|
state.order.policy.isItac = sessionInformation.order.policy?.isItac;
|
||||||
|
state.order.policy.policyNumber = sessionInformation.order.policy?.policyNumber;
|
||||||
|
state.order.policy.insuranceCompanyName =
|
||||||
|
sessionInformation.order.policy?.insuranceCompanyName;
|
||||||
|
state.order.policy.isNoComp = sessionInformation.order.policy?.noComprehensive;
|
||||||
},
|
},
|
||||||
updateExperiments(state, experiments) {
|
updateExperiments(state, experiments) {
|
||||||
state.applicationUser.experiments = experiments;
|
state.applicationUser.experiments = experiments;
|
||||||
|
|
@ -656,6 +689,7 @@ export const getters = {
|
||||||
applicationUser: (state) => state.applicationUser,
|
applicationUser: (state) => state.applicationUser,
|
||||||
order: (state) => state.order,
|
order: (state) => state.order,
|
||||||
payment: (state) => state.order.payment,
|
payment: (state) => state.order.payment,
|
||||||
|
policy: (state) => state.order.policy,
|
||||||
experimentOrder: (state) => {
|
experimentOrder: (state) => {
|
||||||
return {
|
return {
|
||||||
funnelVehicleYear: state.order.vehicle.year,
|
funnelVehicleYear: state.order.vehicle.year,
|
||||||
|
|
@ -1334,7 +1368,7 @@ export const actions = {
|
||||||
getMobileFeePart(context, { pageNameToLog }) {
|
getMobileFeePart(context, { pageNameToLog }) {
|
||||||
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
|
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
|
||||||
const parentAccountNumber = context.getters.payment.parentAccountNumber;
|
const parentAccountNumber = context.getters.payment.parentAccountNumber;
|
||||||
const billToAccountNumber = 87291; // TODO: MAKE THIS REAL
|
const billToAccountNumber = context.getters.payment.billToAccountNumber;
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetMobileFeePart.method,
|
method: endpoints.GetMobileFeePart.method,
|
||||||
|
|
@ -1345,15 +1379,19 @@ export const actions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getServiceabilityDetails(context, { payload: { serviceZipCode }, pageNameToLog }) {
|
getServiceabilityDetails(context, { payload: { serviceZipCode }, pageNameToLog }) {
|
||||||
const lineItemsWithOnlyPartNumbers = context.getters.order.lineItems.supportingItems.map(
|
const lineItemsWithOnlyPartNumbers = context.getters.order.lineItems.supportingItems?.map(
|
||||||
(lineItem) => ({
|
(lineItem) => ({
|
||||||
partNumber: lineItem.partNumber,
|
partNumber: lineItem.partNumber,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const lineItems = buildQueryStringParameterFromArrayOfComplexObjects(
|
|
||||||
lineItemsWithOnlyPartNumbers,
|
var lineItems = null;
|
||||||
"lineItems"
|
if (lineItemsWithOnlyPartNumbers) {
|
||||||
);
|
lineItems = buildQueryStringParameterFromArrayOfComplexObjects(
|
||||||
|
lineItemsWithOnlyPartNumbers,
|
||||||
|
"lineItems"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const vehicle = context.getters.vehicle;
|
const vehicle = context.getters.vehicle;
|
||||||
const carId = vehicle.carId;
|
const carId = vehicle.carId;
|
||||||
|
|
@ -1365,9 +1403,18 @@ export const actions = {
|
||||||
"glassPieces"
|
"glassPieces"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var endPoint = `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}`;
|
||||||
|
if (lineItems) {
|
||||||
|
endPoint += `&${lineItems}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glassPieces) {
|
||||||
|
endPoint += `&${glassPieces}`;
|
||||||
|
}
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetServiceabilityDetails.method,
|
method: endpoints.GetServiceabilityDetails.method,
|
||||||
endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&${lineItems}&${glassPieces}`,
|
endpoint: endPoint,
|
||||||
logApiCall: true,
|
logApiCall: true,
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
});
|
});
|
||||||
|
|
@ -1444,7 +1491,7 @@ export const actions = {
|
||||||
) {
|
) {
|
||||||
const order = context.state.order;
|
const order = context.state.order;
|
||||||
const vehicle = context.state.order.vehicle;
|
const vehicle = context.state.order.vehicle;
|
||||||
|
const payment = context.state.order.payment;
|
||||||
let lineItems = [
|
let lineItems = [
|
||||||
...(order.lineItems.supportingItems ?? []),
|
...(order.lineItems.supportingItems ?? []),
|
||||||
...(order.lineItems.vaps ?? []),
|
...(order.lineItems.vaps ?? []),
|
||||||
|
|
@ -1466,15 +1513,16 @@ export const actions = {
|
||||||
endDate: endDate,
|
endDate: endDate,
|
||||||
shopAppointmentType: shopAppointmentType,
|
shopAppointmentType: shopAppointmentType,
|
||||||
applicationName: applicationConfig.APPLICATION_NAME,
|
applicationName: applicationConfig.APPLICATION_NAME,
|
||||||
parentAccountNumber: context.getters.payment.parentAccountNumber,
|
parentAccountNumber: payment.parentAccountNumber,
|
||||||
carId: vehicle.carId,
|
carId: vehicle.carId,
|
||||||
lineItems: lineItems,
|
lineItems: lineItems,
|
||||||
glassPieces: glassPieces,
|
glassPieces: glassPieces,
|
||||||
eon: order.eon,
|
eon: order.eon,
|
||||||
|
billToAccountNumber: context.getters.payment.billToAccountNumber,
|
||||||
coverage: {
|
coverage: {
|
||||||
status: "",
|
status: payment.insuranceCoverage.coverageStatus,
|
||||||
deductible: 0,
|
deductible: order.policy.currentDeductible,
|
||||||
additionalAuthFlag: "",
|
additionalAuthFlag: order.policy.additionalAuthFlag,
|
||||||
},
|
},
|
||||||
partSelection: {
|
partSelection: {
|
||||||
hasAnsweredPartQuestions: !!order.damage.partQuestionAnswers?.length,
|
hasAnsweredPartQuestions: !!order.damage.partQuestionAnswers?.length,
|
||||||
|
|
@ -1512,6 +1560,7 @@ export const actions = {
|
||||||
getMobileTimeSlots(context, { payload: { startDate, endDate }, pageNameToLog }) {
|
getMobileTimeSlots(context, { payload: { startDate, endDate }, pageNameToLog }) {
|
||||||
const order = context.state.order;
|
const order = context.state.order;
|
||||||
const vehicle = context.state.order.vehicle;
|
const vehicle = context.state.order.vehicle;
|
||||||
|
const payment = context.state.order.payment;
|
||||||
let lineItems = [
|
let lineItems = [
|
||||||
...(order.lineItems.supportingItems ?? []),
|
...(order.lineItems.supportingItems ?? []),
|
||||||
...(order.lineItems.vaps ?? []),
|
...(order.lineItems.vaps ?? []),
|
||||||
|
|
@ -1530,15 +1579,16 @@ export const actions = {
|
||||||
startDate: startDate,
|
startDate: startDate,
|
||||||
endDate: endDate,
|
endDate: endDate,
|
||||||
applicationName: applicationConfig.APPLICATION_NAME,
|
applicationName: applicationConfig.APPLICATION_NAME,
|
||||||
parentAccountNumber: context.getters.payment.parentAccountNumber,
|
parentAccountNumber: payment.parentAccountNumber,
|
||||||
carId: vehicle.carId,
|
carId: vehicle.carId,
|
||||||
lineItems: lineItems,
|
lineItems: lineItems,
|
||||||
glassPieces: glassPieces,
|
glassPieces: glassPieces,
|
||||||
eon: order.eon,
|
eon: order.eon,
|
||||||
|
billToAccountNumber: context.getters.payment.billToAccountNumber,
|
||||||
coverage: {
|
coverage: {
|
||||||
status: "",
|
status: payment.insuranceCoverage.coverageStatus,
|
||||||
deductible: 0,
|
deductible: order.policy.currentDeductible,
|
||||||
additionalAuthFlag: "",
|
additionalAuthFlag: order.policy.additionalAuthFlag,
|
||||||
},
|
},
|
||||||
partSelection: {
|
partSelection: {
|
||||||
hasAnsweredPartQuestions: !!order.damage.partQuestionAnswers?.length,
|
hasAnsweredPartQuestions: !!order.damage.partQuestionAnswers?.length,
|
||||||
|
|
@ -1557,6 +1607,7 @@ export const actions = {
|
||||||
},
|
},
|
||||||
zipCode: order.serviceLocation.zipCode,
|
zipCode: order.serviceLocation.zipCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetMobileTimeSlots.method,
|
method: endpoints.GetMobileTimeSlots.method,
|
||||||
endpoint: endpoints.GetMobileTimeSlots.url,
|
endpoint: endpoints.GetMobileTimeSlots.url,
|
||||||
|
|
@ -1691,6 +1742,7 @@ export const actions = {
|
||||||
lastFour: order.payment.ccToken.lastFour,
|
lastFour: order.payment.ccToken.lastFour,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
policy: {},
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
streetAddress: order.serviceLocation.address,
|
streetAddress: order.serviceLocation.address,
|
||||||
streetAddress2: order.serviceLocation.address2,
|
streetAddress2: order.serviceLocation.address2,
|
||||||
|
|
@ -2107,6 +2159,9 @@ export const actions = {
|
||||||
saveParentAccountNumber(context, parentAccountNumber) {
|
saveParentAccountNumber(context, parentAccountNumber) {
|
||||||
context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccountNumber);
|
context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccountNumber);
|
||||||
},
|
},
|
||||||
|
saveBillToAccountNumber(context, billToAccountNumber) {
|
||||||
|
context.commit(storeMutations.UPDATE_BILL_TO_ACCT_NUMBER, billToAccountNumber);
|
||||||
|
},
|
||||||
|
|
||||||
saveSupportingItems(context, supportingItems) {
|
saveSupportingItems(context, supportingItems) {
|
||||||
if (!deepEqual(supportingItems, context.state.order.lineItems.supportingItems)) {
|
if (!deepEqual(supportingItems, context.state.order.lineItems.supportingItems)) {
|
||||||
|
|
@ -2200,6 +2255,7 @@ export const actions = {
|
||||||
|
|
||||||
const vehicle = context.getters.order.vehicle;
|
const vehicle = context.getters.order.vehicle;
|
||||||
|
|
||||||
|
// TODO: Insurance pricing...`ParentAccountNumber=${context.getters.order.payment.parentAccountNumber}`
|
||||||
let queryString =
|
let queryString =
|
||||||
`ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` +
|
`ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` +
|
||||||
`&CTU=${ctuToUse}` +
|
`&CTU=${ctuToUse}` +
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
class="d-flex w-100 align-items-center px-2 h-100 list-card-content button-content rounded-3"
|
class="d-flex w-100 align-items-center px-2 h-100 list-card-content button-content rounded-3"
|
||||||
:class="labelClasses">
|
:class="labelClasses">
|
||||||
<img
|
<img
|
||||||
|
v-if="buttonImage"
|
||||||
:id="buttonImageId"
|
:id="buttonImageId"
|
||||||
:class="!isWide ? 'order-1' : 'ms-auto order-3'"
|
:class="!isWide ? 'order-1' : 'ms-auto order-3'"
|
||||||
:src="buttonImage"
|
:src="buttonImage"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue