diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index 76847f3e9..d9d399921 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -33,10 +33,9 @@ :key="i" class="packaged-cart-item"> <{{ cartItem.name - }}> + >{{ cartItem.name + }} @@ -112,7 +110,7 @@ class="my-2 lh-1 applied-promo" v-for="(promoCode, i) in this.getPromoCodeList()" :key="i"> - Promo code <{{ promoCode }}> applied + Promo code {{ promoCode }} applied @@ -158,7 +156,6 @@ export default { style: "currency", currency: "USD", }), - lineItems: deepClone(this.modelValue), }; }, methods: { @@ -236,8 +233,6 @@ export default { this.lineItems[category] = this.lineItems[category].filter( (lineItemsToKeep) => lineItemsToKeep.cartItemType != cartItemType ); - - this.$emit("update:modelValue", this.lineItems); }, getPromoCodeList() { if (this.$refs["promoModalQuestion"]) { @@ -245,12 +240,16 @@ export default { } return []; }, - handleAddedPromo(lineItems) { - // NOTE: these lineItems are passed from promo-modal-question - this.$emit("update:modelValue", lineItems); - }, }, computed: { + lineItems: { + get: function () { + return this.modelValue; + }, + set: function (newValue) { + this.$emit("update:modelValue", newValue); + }, + }, screenReaderTotalAmountDueText() { return this.getCmsContent("ScreenReaderTotalAmountDueWidget", "Text"); }, @@ -843,14 +842,6 @@ export default { return this.subTotal + this.salesTax; }, }, - watch: { - modelValue: { - handler(newValue) { - this.lineItems = deepClone(newValue); - }, - deep: true, - }, - }, components: { textBlock, textLink, diff --git a/src/fmg-components/promo-modal-question/promo-modal-question.vue b/src/fmg-components/promo-modal-question/promo-modal-question.vue index 59c1523b2..dd64321bb 100644 --- a/src/fmg-components/promo-modal-question/promo-modal-question.vue +++ b/src/fmg-components/promo-modal-question/promo-modal-question.vue @@ -99,7 +99,7 @@ export default { props: { modelValue: Object, modalWidgetName: String, - availableVaps: Object, + addableVaps: Object, pageName: String, taxPromos: { type: Boolean, @@ -186,14 +186,14 @@ export default { resetModalButtonStyle() { this.modal.resetButtonStyle(); }, - async getPromoCodeData(promoCode, lineItems, availableVaps, pageNameToLog = null) { + async getPromoCodeData(promoCode, lineItems, addableVaps, pageNameToLog = null) { const pageName = pageNameToLog ?? this.$options?.name; const promoValidationResponse = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA, { promoCode: promoCode, lineItemsToUse: lineItems, - addableVaps: availableVaps, + addableVaps: addableVaps, }, pageName, false @@ -258,7 +258,7 @@ export default { const promoCodeData = await this.getPromoCodeData( this.promoCode, this.lineItems, - this.availableVaps, + this.addableVaps, this.pageName ); if (promoCodeData.isValid) { @@ -292,7 +292,7 @@ export default { ); const taxedVaps = mapTaxedLineItemsToStoreFormat( taxedLineItems, - this.availableVaps + this.addableVaps ); const getVaps = getVapsThatNeedToBeAddedToSatisfyPromos( @@ -304,7 +304,6 @@ export default { this.lineItems.vaps?.push(...getVaps); } this.lineItems?.promos.push(...promoCodeData.promoCode); - this.$emit("added-promo", this.lineItems); this.closeModal(); } else { this.getErrorMessage(promoCodeData.errorCode, promoCodeData.additionalInfo); diff --git a/src/helpers/heritage-integration/navigation-helper.js b/src/helpers/heritage-integration/navigation-helper.js index feba06ae3..da21df752 100644 --- a/src/helpers/heritage-integration/navigation-helper.js +++ b/src/helpers/heritage-integration/navigation-helper.js @@ -73,6 +73,13 @@ export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLo heritageParms["promo"] = promo; } + if ( + process.env.VUE_APP_HERITAGE_FUNNEL.includes("fixmyglassdev") && + process.env.VUE_APP_CURRENT_ENVIRONMENT === "Localhost" + ) { + heritageParms["forceEndToEndInsurance"] = true; + } + router.navigateToExternalUrl(externalUrls.HERITAGE_FUNNEL, heritageParms); } diff --git a/src/helpers/promotions-helper.js b/src/helpers/promotions-helper.js index c9b305f99..e8d5f4e8f 100644 --- a/src/helpers/promotions-helper.js +++ b/src/helpers/promotions-helper.js @@ -331,10 +331,10 @@ export function getNewlyInactivatedPromos(oldInactivePromos, newInactivePromos) export function createPromoSuccessAlert(promoCode) { return { - messageHeadline: "Promo applied!", - messageCopy: `Promo "${getPromoCodeWithoutBundleIdentifier( + messageHeadline: "Promo code applied!", + messageCopy: `Promo code ${getPromoCodeWithoutBundleIdentifier( promoCode.toUpperCase() - )}" was successfully applied to your cart.`, + )} was successfully applied to your cart.`, type: "alert-success", isDismissible: true, shouldAutoFade: true, @@ -343,19 +343,19 @@ export function createPromoSuccessAlert(promoCode) { export function createPromoErrorAlert(promoCode, errorCode = null, additionalInfo) { const alert = { - messageHeadline: "Promo error", + messageHeadline: "Promo code error", type: "alert-danger", shouldAutoFade: false, isDismissible: true, }; if (stackingPromoErrorCodes.includes(errorCode)) { - alert.messageCopy = `Sorry, promo code "${getPromoCodeWithoutBundleIdentifier( + alert.messageCopy = `Sorry, promo code ${getPromoCodeWithoutBundleIdentifier( promoCode.toUpperCase() - )}" cannot be combined with "${additionalInfo[0].toUpperCase()}"`; + )} cannot be combined with ${additionalInfo[0].toUpperCase()}`; } else { - alert.messageCopy = `Sorry, promo code "${getPromoCodeWithoutBundleIdentifier( + alert.messageCopy = `Sorry, promo code ${getPromoCodeWithoutBundleIdentifier( promoCode.toUpperCase() - )}" is not valid`; + )} is not valid`; } return alert; } diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index c1dd44145..27093cfdf 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -29,7 +29,7 @@ :availableLineItems="availableLineItems" :isInsuranceSelected="isInsuranceSelected" @vapsItemsSelected="vapsItemsSelectedAction" - :activePromos="allActivePromos" + :activePromos="lineItems.promos" v-on="{ 'buttonEvent.openModal': openModalAction }" validationRules="option-required" isRequired /> @@ -42,7 +42,7 @@ @@ -86,6 +86,7 @@ import baseMixin from "@/mixins/base-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 { required } from "@/helpers/validation-rules"; @@ -149,7 +150,8 @@ export default { ]; const resultMap = await settleAllPromises(promiseResultMap); - const lineItems = store.getters.order.lineItems; + const lineItems = deepClone(store.getters.order.lineItems); + lineItems.vaps = lineItems.vaps ?? []; const nullSafeGlassParts = lineItems.glassParts ?? []; const availableLineItems = [ resultMap.rainDefense, @@ -172,30 +174,29 @@ export default { 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 availableVaps = [...resultMap.wipers, resultMap.rainDefense]; 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" ); - lineItems.glassParts = nullSafeGlassParts; - lineItems.promos = lineItems.promos ?? []; - lineItems.vaps = lineItems.vaps ?? []; + // 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((vm) => { vm.setCmsContent(resultMap.cmsContent); - vm.availableVaps = availableVaps; + vm.addableVaps = addableVaps; vm.lineItems = lineItems; vm.availableLineItems = pricingResults; vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems); @@ -225,13 +226,10 @@ export default { isInsuranceSelected: null, availableLineItems: null, lineItems: [], - availableVaps: [], + addableVaps: [], }; }, computed: { - allActivePromos() { - return this.lineItems.promos ?? []; - }, lineItemsCloneForWatcher() { return Object.assign({}, this.lineItems); }, @@ -304,7 +302,7 @@ export default { this.$store.getters.order.payment.parentAccountNumber != applicationConfig.CASH_PARENT_ACCOUNT_NUMBER ) { - this.supportingItems = this.filterOutFees(this.supportingItems); + this.lineItems.supportingItems = this.filterOutFees(this.lineItems.supportingItems); } if (this.lineItems.glassParts?.length > 0) { @@ -320,7 +318,6 @@ export default { storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, { activePromos: this.lineItems.promos, - inactivePromos: this.$store.getters.order.payment.inactivePromos, }, false ); diff --git a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue index 25a73e112..280edfc6c 100644 --- a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue +++ b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue @@ -95,19 +95,14 @@ export default { }, tintSelectionOptions() { - let tintOptions = []; - - Object.keys(this.featureListData).forEach((tintOption) => { - tintOptions.push({ + const tintOptions = Object.keys(this.featureListData).map((tintOption) => { + const buttonImage = this.getTintSourceImage(this.glassLocation, tintOption); + return { value: tintOption, buttonLabel: tintOption, - buttonImage: require(`@/assets/img/tints/${this.getTintSourceImage( - this.glassLocation, - tintOption - )}`), - }); + buttonImage: buttonImage ? require(`@/assets/img/tints/${buttonImage}`) : null, + }; }); - return tintOptions; }, diff --git a/src/router/index.js b/src/router/index.js index ae31f82d0..63904343b 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -72,7 +72,7 @@ const routes = [ // the saveSessionPromise will no longer point to a valid promise baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); - if (!to.query.fmgPage.startsWith("payment")) { + if (!to.query.fmgPage?.startsWith("payment")) { //payment pages used to return from safelitehop so exclude here // Remove the parameter after quote release const loadSessionResponse = await loadSessionIfPresent( @@ -451,6 +451,11 @@ async function DisplayPageError() { // 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) { @@ -459,19 +464,19 @@ async function DisplayPageError() { router.push({ path: "/", - query: { fmgPage: "vehicle" }, + query: { fmgPage: navPage }, }); } else { errorCount++; router.push({ path: "/", - query: { fmgPage: "vehicle", pageError: errorCount }, + query: { fmgPage: navPage, pageError: errorCount }, }); } } else { router.push({ path: "/", - query: { fmgPage: "vehicle", pageError: "1" }, + query: { fmgPage: navPage, pageError: "1" }, }); } } diff --git a/src/store/index.js b/src/store/index.js index cd4937877..1c371f3a5 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -514,7 +514,7 @@ export const mutations = { state.order.damage.glassToReplace = sessionInformation.order.damage.glassToReplace; state.order.damage.isRepair = sessionInformation.order.damage.isRepair; state.order.damage.numberOfChips = sessionInformation.order.damage.numberOfChips; - state.order.damage.dateOfLoss = sessionInformation.order.damage?.lossDate; + state.order.damage.dateOfLoss = sessionInformation.order.damage?.dateOfLoss; state.order.damage.damageCause = sessionInformation.order.damage?.damageCause; state.order.damage.partQuestionAnswers = @@ -1101,6 +1101,10 @@ export const actions = { parentAccountNumber, } ) { + if (!pageName) { + return; + } + var payload = { userId: userId, sessionKey: sessionKey, @@ -1146,6 +1150,10 @@ export const actions = { parentAccountNumber, } ) { + if (!pageName) { + return; + } + var payload = { userId: userId, sessionKey: sessionKey, diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue index 902baa1e1..ffdf4efc0 100644 --- a/src/ux-components/list-card/list-card.vue +++ b/src/ux-components/list-card/list-card.vue @@ -10,6 +10,7 @@ class="d-flex w-100 align-items-center px-2 h-100 list-card-content button-content rounded-3" :class="labelClasses">