CSR-2262 persist isInsurance through the site so that we know when we get to the quote page if it was set through the leadgen querystring parm
669 lines
28 KiB
Vue
669 lines
28 KiB
Vue
<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">
|
|
<vehicleBanner
|
|
cmsWidgetName="VehicleBannerWidget"
|
|
:displayGenericVehicleImage="false" />
|
|
|
|
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" />
|
|
|
|
<cashOrInsuranceQuestion
|
|
ref="cashOrInsurance"
|
|
cmsWidgetName="CashOrInsuranceQuestionWidget"
|
|
v-model="isInsuranceSelected"
|
|
groupName="CashOrInsuranceQuestion" />
|
|
</div>
|
|
</div>
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-12 col-xl-8">
|
|
<servicePackageQuestion
|
|
ref="servicePackage"
|
|
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
|
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
|
groupName="ServicePackageQuestion"
|
|
:availableLineItems="availableLineItems"
|
|
:isInsuranceSelected="isInsuranceSelected"
|
|
:isRecalibrationOnOrder="isRecalibrationOnOrder"
|
|
:shouldHideRecalibration="shouldHideRecalibration"
|
|
@vapsItemsSelected="vapsItemsSelectedAction"
|
|
@servicePackageDiscountSelected="servicePackageDiscountSelectedAction"
|
|
:servicePackage="servicePackage"
|
|
:activePromos="lineItems.promos"
|
|
v-on="{ 'buttonEvent.openModal': openModalAction }"
|
|
validationRules="option-required"
|
|
isRequired />
|
|
</div>
|
|
</div>
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-6 col-xl-4">
|
|
<!-- If Cash AND vehicle does not require recal OR if Cash AND State requires showing recal, then show Afterpay banner -->
|
|
<afterpayModalBanner
|
|
v-if="showAfterpayBanner"
|
|
cmsWidgetName="AfterpayModalWidget"
|
|
:lineItems="lineItems" />
|
|
|
|
<!-- If vehicle requires recal AND we are hiding recal pricing info, then show recal disclaimer banner. -->
|
|
<recalDisclaimer
|
|
class="mb-0"
|
|
cmsWidgetName="RecalDisclaimerWidget"
|
|
v-if="showRecalDisclaimer"
|
|
v-on="{ textLinkClicked: openModalAction }"
|
|
alertClass="alert-info" />
|
|
|
|
<promoModalQuestion
|
|
class="small mt-6 d-md-flex justify-content-md-center"
|
|
v-model="lineItems"
|
|
:addableVaps="addableVaps"
|
|
pageName="quote"
|
|
:taxPromos="false"
|
|
:useDefaultCashParentAccount="true"
|
|
modalWidgetName="PromoModalWidget" />
|
|
|
|
<textBlock
|
|
cmsWidgetName="quoteDisclaimer"
|
|
justifyText="left"
|
|
typeStyle="caption"
|
|
class="mt-6 quote-disclaimer" />
|
|
|
|
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
|
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
|
<contentGroupModal ref="RearWiperModal" cmsWidgetName="RearWiperModal" />
|
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" isRecal />
|
|
|
|
<navbar
|
|
cmsWidgetName="FunnelFooterWidget"
|
|
:isForwardActionDisabled="!meta.valid"
|
|
:isBackButtonHidden="shouldHideBackButton"
|
|
@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 vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
|
import cashOrInsuranceQuestion from "./cash-or-insurance-question/cash-or-insurance-question";
|
|
import servicePackageQuestion from "./service-package-question/service-package-question";
|
|
import textBlock from "@/digital-components/text-block/text-block";
|
|
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
|
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
|
import afterpayModalBanner from "@/layouts/quote/afterpay-modal-banner/afterpay-modal-banner";
|
|
import recalDisclaimer from "@/layouts/quote/recal-disclaimer/recal-disclaimer.vue";
|
|
|
|
// Supporting files
|
|
import baseMixin from "@/mixins/base-mixin.js";
|
|
import experimentMixin from "@/mixins/experiment-mixin.js";
|
|
import vehicleQuestionsMixin from "../../mixins/vehicle-questions-mixin";
|
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
|
import { storeActions } from "@/constants/store-actions";
|
|
import { deepClone } from "@/helpers/object-helper";
|
|
import store from "@/store";
|
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|
import { experimentSettings } from "@/constants/experiments";
|
|
import { required } from "@/helpers/validation-rules";
|
|
import { errorMessages } from "@/constants/error-messages";
|
|
import { Form, defineRule } from "vee-validate";
|
|
import { applicationConfig } from "@/constants/application-config";
|
|
import { payWithInsuranceStates } from "@/constants/insurance";
|
|
import {
|
|
revalidatePromosAndValidateQueryStringPromo,
|
|
buildToastMessagesFromRevalidateOrValidatePromoResponse,
|
|
createPromoSuccessAlert,
|
|
} from "@/helpers/promotions-helper";
|
|
import { queryStrings } from "@/constants/query-strings";
|
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
|
import promoModalQuestion from "@/fmg-components/promo-modal-question/promo-modal-question";
|
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
|
import {
|
|
containsLineItemWithPartType,
|
|
findLineItemsWithPartType,
|
|
} from "@/helpers/service-package-helper";
|
|
import { nextTick } from "vue";
|
|
import { packageNames } from "@/constants/package-names";
|
|
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));
|
|
|
|
const INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT = 300;
|
|
|
|
export default {
|
|
name: "quote",
|
|
async beforeRouteEnter(to, from, next) {
|
|
// Call APIs
|
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
|
const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.GET_WIPERS,
|
|
{
|
|
serviceZipCode: store.getters.order.serviceLocation.zipCode,
|
|
carId: store.getters.vehicle.carId,
|
|
},
|
|
"quote"
|
|
);
|
|
const rainDefensePromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.GET_RAIN_DEFENSE,
|
|
null,
|
|
"quote"
|
|
);
|
|
const supportingItemsPromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.GET_SUPPORTING_ITEMS,
|
|
null,
|
|
"quote"
|
|
);
|
|
|
|
const promiseResultMap = [
|
|
{
|
|
resultKey: "cmsContent",
|
|
promise: cmsContentPromise,
|
|
},
|
|
{
|
|
resultKey: "wipers",
|
|
promise: wipersPromise,
|
|
},
|
|
{
|
|
resultKey: "rainDefense",
|
|
promise: rainDefensePromise,
|
|
},
|
|
{
|
|
resultKey: "supportingItems",
|
|
promise: supportingItemsPromise,
|
|
},
|
|
];
|
|
|
|
const resultMap = await settleAllPromises(promiseResultMap);
|
|
const lineItems = deepClone(store.getters.order.lineItems);
|
|
lineItems.vaps = lineItems.vaps ?? [];
|
|
const nullSafeGlassParts = lineItems.glassParts ?? [];
|
|
const servicePackageDiscountSettingValue = experimentMixin.methods.getSettingValue(
|
|
experimentSettings.SERVICE_PACKAGE_DISCOUNT
|
|
);
|
|
const isServicePackageDiscount = servicePackageDiscountSettingValue === "True";
|
|
//Service package cash discount api call when experiment is active
|
|
var servicePackageDiscountPart = [];
|
|
if (isServicePackageDiscount) {
|
|
const servicePackageDiscountPartResponse =
|
|
await baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.GET_SERVICE_PACKAGE_DISCOUNT_PART,
|
|
null,
|
|
"quote"
|
|
);
|
|
if (servicePackageDiscountPartResponse.data) {
|
|
servicePackageDiscountPart.push(servicePackageDiscountPartResponse.data);
|
|
}
|
|
}
|
|
const availableLineItems = [
|
|
resultMap.rainDefense,
|
|
...resultMap.supportingItems,
|
|
...resultMap.wipers,
|
|
...nullSafeGlassParts,
|
|
...servicePackageDiscountPart,
|
|
];
|
|
|
|
// When calling pricing from the quote page, always use the cash parent account but save the existing one in case it's unverified insurance navigating backwards
|
|
var holdParentAccountNumber = store.getters.order.payment?.parentAccountNumber;
|
|
var holdBillToAccountNumber = store.getters.order.payment?.billToAccountNumber;
|
|
|
|
baseMixin.methods.dispatchStoreAction(
|
|
storeActions.SAVE_PARENT_ACCOUNT_NUMBER,
|
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
|
|
false
|
|
);
|
|
baseMixin.methods.dispatchStoreAction(
|
|
storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
|
applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER,
|
|
false
|
|
);
|
|
|
|
const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
|
{
|
|
availableLineItems: availableLineItems,
|
|
},
|
|
"quote",
|
|
false
|
|
);
|
|
|
|
baseMixin.methods.dispatchStoreAction(
|
|
storeActions.SAVE_SUPPORTING_ITEMS,
|
|
resultMap.supportingItems,
|
|
false
|
|
);
|
|
lineItems.supportingItems = resultMap.supportingItems;
|
|
const addableVaps = [...resultMap.wipers, resultMap.rainDefense];
|
|
|
|
// Promo logic
|
|
// Populate the previous state of promos for toast message usage in "next()"
|
|
const oldActivePromos = store.getters.lineItems.promos?.slice(0);
|
|
const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0);
|
|
|
|
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
|
|
const { validatePromoResponse, revalidatePromoResponse } =
|
|
await revalidatePromosAndValidateQueryStringPromo(
|
|
promoCodeFromQueryString,
|
|
pricingResults,
|
|
"quote",
|
|
true
|
|
);
|
|
// Sync local promos with any new promos added by validate/revalidate
|
|
lineItems.promos = store.getters.lineItems.promos ?? [];
|
|
// End of promo logic
|
|
|
|
// Call the "next" function to complete the transition to this page.
|
|
next(async (vm) => {
|
|
vm.setCmsContent(resultMap.cmsContent);
|
|
vm.addableVaps = addableVaps;
|
|
vm.lineItems = lineItems;
|
|
vm.availableLineItems = pricingResults;
|
|
vm.holdParentAccountNumber = holdParentAccountNumber;
|
|
vm.holdBillToAccountNumber = holdBillToAccountNumber;
|
|
|
|
if (revalidatePromoResponse) {
|
|
const revalidateAlerts = buildToastMessagesFromRevalidateOrValidatePromoResponse(
|
|
revalidatePromoResponse,
|
|
oldActivePromos,
|
|
oldInactivePromos
|
|
);
|
|
revalidateAlerts.forEach((alert) => {
|
|
vm.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade);
|
|
});
|
|
}
|
|
if (validatePromoResponse) {
|
|
const validateAlerts =
|
|
buildToastMessagesFromRevalidateOrValidatePromoResponse(validatePromoResponse);
|
|
vm.$refs.funnelHeader.pushGlobalAlert(
|
|
validateAlerts[0],
|
|
validateAlerts[0].shouldAutoFade
|
|
);
|
|
}
|
|
|
|
// This is a safeguard to prevent verified insurance from seeing quote page again.
|
|
const payment = store.getters.payment;
|
|
if (payment?.isInsurance && payment?.insuranceCoverage?.isVerified) {
|
|
navigateToHeritageFunnel({ shouldSaveSession: true, pageNameToLog: "quote" });
|
|
}
|
|
|
|
const getIsInsuranceSelectedValue = (availableLineItems, insuranceThreshold) => {
|
|
const serviceLocationState = store.getters.order.serviceLocation.state;
|
|
|
|
// 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 hideRecalCost =
|
|
experimentMixin.methods
|
|
.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)
|
|
?.toLowerCase() === "true";
|
|
|
|
//Default to Insurance Tab if user Service zip is from certain States
|
|
if (
|
|
serviceLocationState != null &&
|
|
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
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 internalThreshold = experimentMixin.methods.getSettingValue(
|
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL
|
|
);
|
|
const isExternalParameter = store.getters.externalParameterState?.isExternalParameter;
|
|
|
|
if (isExternalParameter === externalParameterStatus.NOT_SET) {
|
|
// there are no active or inactive external parameters; use internal threshold
|
|
if (internalThreshold) thresholdToUse = internalThreshold;
|
|
|
|
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
|
vm.availableLineItems,
|
|
thresholdToUse
|
|
);
|
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
} else {
|
|
// user came from an external source
|
|
if (store.getters.externalParameterQuote?.isInsurance == true) {
|
|
// did user intentionally select insurance?
|
|
vm.isInsuranceSelected = true;
|
|
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
|
|
await nextTick();
|
|
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
|
|
if (isValid) {
|
|
vm.forwardButtonAction();
|
|
} else {
|
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
}
|
|
} else {
|
|
const externalThreshold = experimentMixin.methods.getSettingValue(
|
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL
|
|
);
|
|
thresholdToUse = externalThreshold;
|
|
|
|
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
|
vm.availableLineItems,
|
|
thresholdToUse
|
|
);
|
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
data() {
|
|
return {
|
|
isInsuranceSelected: null,
|
|
availableLineItems: null,
|
|
lineItems: [],
|
|
addableVaps: [],
|
|
servicePackage: null,
|
|
holdParentAccountNumber: null,
|
|
holdBillToAccountNumber: null,
|
|
};
|
|
},
|
|
computed: {
|
|
lineItemsCloneForWatcher() {
|
|
return Object.assign({}, this.lineItems);
|
|
},
|
|
isRecalibrationOnOrder() {
|
|
return store.getters.isRecalibrationOnOrder;
|
|
},
|
|
isServicePackageDiscountOnOrder() {
|
|
return containsLineItemWithPartType(
|
|
partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
|
|
this.availableLineItems
|
|
);
|
|
},
|
|
servicePackageDiscountParts() {
|
|
return findLineItemsWithPartType(
|
|
partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
|
|
this.availableLineItems
|
|
);
|
|
},
|
|
shouldHideRecalibration() {
|
|
return store.getters.shouldHideRecalibration;
|
|
},
|
|
showAfterpayBanner() {
|
|
return (
|
|
!this.isInsuranceSelected &&
|
|
(!this.isRecalibrationOnOrder || !this.shouldHideRecalibration)
|
|
);
|
|
},
|
|
showRecalDisclaimer() {
|
|
return this.isRecalibrationOnOrder && this.shouldHideRecalibration;
|
|
},
|
|
},
|
|
methods: {
|
|
openModalAction(modalName) {
|
|
this.$refs[modalName].openModal();
|
|
},
|
|
arePagePrerequisitesValid() {
|
|
const payment = store.getters.order.payment;
|
|
const log = getQuerystringParameter(queryStrings.LOG);
|
|
if (eval(log)) {
|
|
console.log("------------- quote.vue pagePrereqs start -----------------");
|
|
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(
|
|
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
|
|
);
|
|
console.log("----------------- quote.vue pagePrereqs end -----------------");
|
|
}
|
|
return (
|
|
store.getters.order.serviceLocation.zipCode &&
|
|
store.getters.order.serviceLocation.zipCodeCtu &&
|
|
(store.getters.order.damage.isRepair ||
|
|
(store.getters.order.lineItems?.glassParts != null &&
|
|
store.getters.order.lineItems.glassParts.length > 0)) &&
|
|
(payment.insuranceCoverage?.isVerified == null ||
|
|
payment.insuranceCoverage?.isVerified === false)
|
|
);
|
|
},
|
|
vapsItemsSelectedAction(vapsItemsSelected) {
|
|
this.lineItems.vaps = vapsItemsSelected;
|
|
},
|
|
servicePackageDiscountSelectedAction(supportingItemsSelected) {
|
|
this.lineItems.supportingItems = supportingItemsSelected;
|
|
},
|
|
backButtonAction() {
|
|
vehicleQuestionsMixin.methods.navigateBack(this);
|
|
},
|
|
forwardButtonAction() {
|
|
this.dispatchStoreAction(
|
|
this.storeActions.SAVE_PAYMENT_TYPE,
|
|
this.isInsuranceSelected,
|
|
false
|
|
);
|
|
|
|
if (!this.isInsuranceSelected) {
|
|
this.dispatchStoreAction(
|
|
this.storeActions.SAVE_PARENT_ACCOUNT_NUMBER,
|
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
|
|
false
|
|
);
|
|
this.dispatchStoreAction(
|
|
this.storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
|
applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER,
|
|
false
|
|
);
|
|
} else {
|
|
baseMixin.methods.dispatchStoreAction(
|
|
storeActions.SAVE_PARENT_ACCOUNT_NUMBER,
|
|
this.holdParentAccountNumber,
|
|
false
|
|
);
|
|
baseMixin.methods.dispatchStoreAction(
|
|
storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
|
this.holdBillToAccountNumber,
|
|
false
|
|
);
|
|
}
|
|
|
|
if (
|
|
this.$store.getters.order.payment.parentAccountNumber !=
|
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
|
|
) {
|
|
this.lineItems.supportingItems = this.filterOutFees(this.lineItems.supportingItems);
|
|
}
|
|
|
|
if (this.lineItems.glassParts?.length > 0) {
|
|
this.dispatchStoreAction(
|
|
this.storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING,
|
|
this.lineItems.glassParts,
|
|
false
|
|
);
|
|
}
|
|
this.dispatchStoreAction(
|
|
this.storeActions.SAVE_SUPPORTING_ITEMS,
|
|
this.lineItems.supportingItems,
|
|
false
|
|
);
|
|
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.lineItems.vaps, false);
|
|
this.dispatchStoreAction(
|
|
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
|
|
{
|
|
activePromos: this.lineItems.promos,
|
|
},
|
|
false
|
|
);
|
|
|
|
const payment = this.$store.getters.payment;
|
|
if (payment.isInsurance) {
|
|
this.$router.navigateWithSaving(
|
|
this.navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
|
|
this.$route
|
|
);
|
|
} else {
|
|
this.$router.navigateWithSaving(
|
|
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
|
this.$route
|
|
);
|
|
}
|
|
},
|
|
attachCustomEvents() {
|
|
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
|
if (!this.isInsuranceSelected && this.lineItems.vaps?.length == 0) {
|
|
const tierOnePrice =
|
|
this.lineItems.promos?.length > 0
|
|
? this.$refs.servicePackage.getDiscountedPackagePriceString(
|
|
packageNames.TIER_ONE,
|
|
false
|
|
)
|
|
: this.$refs.servicePackage.getPackagePriceString(
|
|
packageNames.TIER_ONE
|
|
);
|
|
this.pushEventToGA(
|
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
|
this.GaActions.CASH_QUOTE_DISPLAYED,
|
|
tierOnePrice,
|
|
true
|
|
);
|
|
}
|
|
});
|
|
this.$nextTick(() => {
|
|
const availablePackageNames = this.$refs.servicePackage?.servicePackageAnswers;
|
|
var eventLabel = "";
|
|
availablePackageNames?.forEach((tier) => {
|
|
if (tier) {
|
|
let lineItemsToPrice = this.availableLineItems;
|
|
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
|
lineItemsToPrice =
|
|
baseMixin.methods.filterOutRecalibration(lineItemsToPrice);
|
|
}
|
|
if (this.isServicePackageDiscountOnOrder) {
|
|
lineItemsToPrice = lineItemsToPrice?.filter((item) => {
|
|
return (
|
|
item.partType != this.servicePackageDiscountParts[0].partType
|
|
);
|
|
});
|
|
}
|
|
let price = 0;
|
|
if (tier.value == "TierTwo" && this.isServicePackageDiscountOnOrder) {
|
|
lineItemsToPrice.push(...this.servicePackageDiscountParts);
|
|
}
|
|
price += baseMixin.methods.getTierOnePackagePrice(
|
|
baseMixin.methods.filterOutFees(lineItemsToPrice)
|
|
);
|
|
price += this.$refs.servicePackage.getVapsPrice(tier.value);
|
|
const formattedPrice = parseFloat(price).toFixed(2);
|
|
eventLabel += tier.value + "_" + formattedPrice;
|
|
}
|
|
eventLabel += ",";
|
|
});
|
|
eventLabel = eventLabel.slice(0, -1);
|
|
|
|
this.pushEventToGA("quote", this.GaActions.SERVICE_PACKAGE_PRICE, eventLabel, true);
|
|
});
|
|
},
|
|
},
|
|
mounted() {
|
|
this.attachCustomEvents();
|
|
},
|
|
watch: {
|
|
lineItemsCloneForWatcher: {
|
|
handler(newValue, oldValue) {
|
|
if (
|
|
!oldValue ||
|
|
oldValue.length == 0 ||
|
|
!oldValue.vaps ||
|
|
!newValue ||
|
|
newValue.length == 0
|
|
) {
|
|
return;
|
|
}
|
|
if (oldValue.promos.length < newValue.promos.length) {
|
|
const oldPromoCodes = oldValue.promos.map(
|
|
(promoObject) => promoObject.promoCode
|
|
);
|
|
const newlyActivatedPromoCodes = newValue.promos.filter(
|
|
(newPromo) => !oldPromoCodes.includes(newPromo.promoCode)
|
|
);
|
|
const alert = createPromoSuccessAlert(newlyActivatedPromoCodes[0].promoCode);
|
|
this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade);
|
|
}
|
|
},
|
|
deep: true,
|
|
},
|
|
},
|
|
components: {
|
|
funnelHeader,
|
|
navbar,
|
|
vehicleBanner,
|
|
funnelSubHeader,
|
|
Form,
|
|
textBlock,
|
|
cashOrInsuranceQuestion,
|
|
servicePackageQuestion,
|
|
contentGroupModal,
|
|
loadingModal,
|
|
afterpayModalBanner,
|
|
promoModalQuestion,
|
|
recalDisclaimer,
|
|
},
|
|
};
|
|
</script>
|
|
<style>
|
|
.funnel-sub-header {
|
|
p {
|
|
font-size: 1rem;
|
|
}
|
|
}
|
|
.text-block {
|
|
display: block;
|
|
}
|
|
</style>
|