CASH-291 The issue here is that when computing the tier one price for determining which tab to select. we are including the service package discount of $50 bringing the tier one price to $287(337-50), which is less than $300 and causing the cash tab to be selected. This is not the tier one price we show but only used in the computation for determining which tab to default.
795 lines
34 KiB
Vue
795 lines
34 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 quote-page"
|
|
:class="showSaveProgressPopup ? 'show-save-progress-popup' : ''">
|
|
<div class="row justify-content-center funnel-header-wrapper">
|
|
<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 mt-4">
|
|
<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 mb-5" :class="getColCount()">
|
|
<servicePackageQuestion
|
|
ref="servicePackage"
|
|
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
|
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
|
groupName="ServicePackageQuestion"
|
|
:availableLineItems="availableLineItems"
|
|
:isInsuranceSelected="isInsuranceSelected"
|
|
:isRecalibrationOnOrder="isRecalibrationOnOrder"
|
|
:shouldHideRecalibration="shouldHideRecalibration"
|
|
@vapsItemsSelected="vapsItemsSelectedAction"
|
|
@servicePackageDiscountSelected="servicePackageDiscountSelectedAction"
|
|
@currentNumberOfPackages="currentNumberOfPackagesAction"
|
|
: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-12" :class="getColCount()">
|
|
<!-- 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-flex justify-content-center"
|
|
v-model="lineItems"
|
|
:addableVaps="addableVaps"
|
|
pageName="quote"
|
|
:taxPromos="false"
|
|
:useDefaultCashParentAccount="true"
|
|
modalWidgetName="PromoModalWidget" />
|
|
</div>
|
|
</div>
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-6 col-xl-4">
|
|
<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" />
|
|
|
|
<saveProgressModalQuestion
|
|
modalWidgetName="SaveProgressModalWidget"
|
|
modalName="SaveProgressModal"
|
|
v-if="showSaveProgressModal"
|
|
pageName="quote" />
|
|
|
|
<textBlock
|
|
cmsWidgetName="quoteDisclaimer"
|
|
justifyText="center"
|
|
typeStyle="caption"
|
|
class="mb-5 quote-disclaimer" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row justify-content-center save-progress-popup">
|
|
<div class="col-md-6 col-xl-4">
|
|
<saveProgressPopupQuestion
|
|
modalWidgetName="SaveProgressPopupWidget"
|
|
modalName="SaveProgressPopup"
|
|
pageName="quote"
|
|
v-if="showSaveProgressPopup"
|
|
:showSaveProgressPopup="showSaveProgressPopup"
|
|
@save-progress-saved="updateSaveProgressAsSaved"
|
|
@close-save-progress-popup="closeSaveProgressPopup" />
|
|
</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 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";
|
|
import saveProgressModalQuestion from "@/fmg-components/save-progress-modal-question/save-progress-modal-question";
|
|
import saveProgressPopupQuestion from "@/fmg-components/save-progress-popup-question/save-progress-popup-question";
|
|
|
|
// 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";
|
|
import { saveQuote } from "@/helpers/heritage-integration/order-helper.js";
|
|
import { getBoolFromString } from "@/helpers/boolean-helper";
|
|
|
|
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 emailFromStore = store.getters.order.customer.emailAddress;
|
|
const isEmailInStoreOnPageLoad = emailFromStore?.length > 0;
|
|
const showSaveProgressPopup = isEmailInStoreOnPageLoad ? false : true;
|
|
const showSaveProgressModal = isEmailInStoreOnPageLoad ? false : true;
|
|
|
|
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.showSaveProgressPopup = showSaveProgressPopup;
|
|
vm.showSaveProgressModal = showSaveProgressModal;
|
|
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) => {
|
|
// query param checked here is set on insurance-selection "Pay on my own" link click
|
|
if (to.query?.isCashSelected || to.query?.iscashselected) {
|
|
return false;
|
|
}
|
|
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);
|
|
|
|
const lineItemsNoDiscount =
|
|
baseMixin.methods.filterOutServicePackageDiscountPart(
|
|
lineItemsForCalculatingPrice
|
|
);
|
|
|
|
if (isInsuranceFromQueryString != null) {
|
|
if (isInsuranceFromQueryString.toLowerCase() === "true") {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
const tierOnePrice =
|
|
baseMixin.methods.getTierOnePackagePrice(lineItemsNoDiscount);
|
|
// prettier-ignore
|
|
{
|
|
if (store.getters.applicationUser.loggingOption) {
|
|
console.log(new Date() + " quote tierOnePrice comparison: " + tierOnePrice + " > " + insuranceThreshold + "=" + (tierOnePrice > insuranceThreshold));
|
|
}
|
|
}
|
|
|
|
// compare base price vs arbitrary threshold (representing insurance price)
|
|
return tierOnePrice > insuranceThreshold;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
let thresholdToUse = INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT;
|
|
let internalThreshold = experimentMixin.methods.getSettingValue(
|
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL
|
|
);
|
|
let externalThreshold = experimentMixin.methods.getSettingValue(
|
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL
|
|
);
|
|
const isExternalParameter = store.getters.externalParameterState?.isExternalParameter;
|
|
|
|
// prettier-ignore
|
|
{
|
|
if (store.getters.applicationUser.loggingOption) {
|
|
console.log("------------- quote.vue thresholds start -----------------");
|
|
console.log(new Date() + " isExternalParameter: " + isExternalParameter);
|
|
console.log(new Date() + " internalThreshold: " + internalThreshold);
|
|
console.log(new Date() + " externalThreshold: " + externalThreshold);
|
|
console.log("------------- quote.vue thresholds end -----------------");
|
|
}
|
|
}
|
|
|
|
if (isExternalParameter === externalParameterStatus.NOT_SET) {
|
|
// prettier-ignore
|
|
{
|
|
if (store.getters.applicationUser.loggingOption) {
|
|
console.log(new Date() + "quote.vue tab select EXTERNAL 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, however, the externalParms may have been reset on service-zip, property-questions, etc...
|
|
if (getBoolFromString(store.getters.externalParameterQuote?.isInsurance)) {
|
|
// prettier-ignore
|
|
{
|
|
if (store.getters.applicationUser.loggingOption) {
|
|
console.log(new Date() + "quote.vue tab select EXTERNAL ISINSURANCE");
|
|
}
|
|
}
|
|
|
|
// did user intentionally select insurance?
|
|
vm.isInsuranceSelected = true;
|
|
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
|
|
await nextTick();
|
|
|
|
if (
|
|
vm.servicePackage != null &&
|
|
isExternalParameter === externalParameterStatus.ACTIVE
|
|
) {
|
|
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
|
|
if (isValid) {
|
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
vm.forwardButtonAction();
|
|
}
|
|
}
|
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
} else {
|
|
if (externalThreshold) thresholdToUse = externalThreshold;
|
|
|
|
// prettier-ignore
|
|
{
|
|
if (store.getters.applicationUser.loggingOption) {
|
|
console.log(new Date() + "quote.vue tab select NOT EXTERNAL");
|
|
}
|
|
}
|
|
|
|
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
|
vm.availableLineItems,
|
|
thresholdToUse
|
|
);
|
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
data() {
|
|
return {
|
|
isInsuranceSelected: null,
|
|
availableLineItems: null,
|
|
lineItems: [],
|
|
addableVaps: [],
|
|
servicePackage: null,
|
|
holdParentAccountNumber: null,
|
|
holdBillToAccountNumber: null,
|
|
showSaveProgressPopup: null,
|
|
showSaveProgressModal: null,
|
|
isSaveProgressComplete: null,
|
|
packageNumber: null,
|
|
};
|
|
},
|
|
mounted() {
|
|
this.attachCustomEvents();
|
|
},
|
|
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 (
|
|
experimentMixin.methods
|
|
.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)
|
|
?.toLowerCase() === "true" && this.isRecalibrationOnOrder
|
|
);
|
|
},
|
|
showAfterpayBanner() {
|
|
return (
|
|
!this.isInsuranceSelected &&
|
|
(!this.isRecalibrationOnOrder || !this.shouldHideRecalibration)
|
|
);
|
|
},
|
|
isRecalPriceRemove() {
|
|
return (
|
|
experimentMixin.methods
|
|
.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)
|
|
?.toLowerCase() === "true"
|
|
);
|
|
},
|
|
showRecalDisclaimer() {
|
|
return this.isRecalibrationOnOrder && this.isRecalPriceRemove;
|
|
},
|
|
},
|
|
methods: {
|
|
getColCount() {
|
|
if (this.packageNumber > 2) {
|
|
return "col-xl-8";
|
|
} else {
|
|
return "col-xl-6";
|
|
}
|
|
},
|
|
currentNumberOfPackagesAction(packageNumber) {
|
|
this.packageNumber = packageNumber;
|
|
},
|
|
openModalAction(modalName) {
|
|
this.$refs[modalName].openModal();
|
|
},
|
|
arePagePrerequisitesValid() {
|
|
const payment = store.getters.order.payment;
|
|
|
|
const preReqResult =
|
|
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);
|
|
|
|
// prettier-ignore
|
|
{
|
|
const log = getQuerystringParameter(queryStrings.LOG);
|
|
if (log === "true" || !preReqResult) {
|
|
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 preReqResult;
|
|
},
|
|
vapsItemsSelectedAction(vapsItemsSelected) {
|
|
this.lineItems.vaps = vapsItemsSelected;
|
|
},
|
|
servicePackageDiscountSelectedAction(supportingItemsSelected) {
|
|
this.lineItems.supportingItems = supportingItemsSelected;
|
|
},
|
|
backButtonAction() {
|
|
vehicleQuestionsMixin.methods.navigateBack(this);
|
|
},
|
|
updateSaveProgressAsSaved() {
|
|
this.showSaveProgressModal = false;
|
|
},
|
|
closeSaveProgressPopup() {
|
|
this.showSaveProgressPopup = false;
|
|
},
|
|
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
|
|
);
|
|
}
|
|
if (this.isInsuranceSelected && this.isServicePackageDiscountOnOrder) {
|
|
let supportingItems = this.lineItems.supportingItems;
|
|
supportingItems = supportingItems.filter((item) => {
|
|
return item.partType != this.servicePackageDiscountParts[0].partType;
|
|
});
|
|
this.dispatchStoreAction(
|
|
this.storeActions.SAVE_SUPPORTING_ITEMS,
|
|
supportingItems,
|
|
false
|
|
);
|
|
} else {
|
|
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.additionalButtonData?.servicePackageDiscount &&
|
|
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);
|
|
});
|
|
},
|
|
},
|
|
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,
|
|
funnelSubHeader,
|
|
Form,
|
|
textBlock,
|
|
cashOrInsuranceQuestion,
|
|
servicePackageQuestion,
|
|
contentGroupModal,
|
|
loadingModal,
|
|
afterpayModalBanner,
|
|
promoModalQuestion,
|
|
recalDisclaimer,
|
|
saveProgressModalQuestion,
|
|
saveProgressPopupQuestion,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.quote-page.show-save-progress-popup .row.justify-content-center {
|
|
display: none;
|
|
|
|
&.funnel-header-wrapper,
|
|
&.save-progress-popup {
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
.funnel-sub-header {
|
|
p {
|
|
font-size: 1rem;
|
|
}
|
|
}
|
|
.text-block {
|
|
display: block;
|
|
}
|
|
</style>
|