diff --git a/src/constants/query-strings.js b/src/constants/query-strings.js index 40f3a2242..5c056c934 100644 --- a/src/constants/query-strings.js +++ b/src/constants/query-strings.js @@ -19,6 +19,7 @@ const queryStrings = { AUTH_CODE: "auth_code", TRANSACTION_ID: "transaction_id", TRANS_REFERENCE_NUMBER: "auth_trans_ref_no", + DISPLAY_PIA_ALERT: "displayPiaAlert", }; export { queryStrings }; diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index c1a9608a8..1180b3152 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -5,7 +5,10 @@ class="row vin-toggle flex align-items-center pt-4" :class="[isExpanded ? 'expanded' : '']" @click="toggleIsExpanded()"> - + {{ amountDueText }} {{ getFormattedAmount("", amountDue) }} @@ -13,7 +16,8 @@
- + + {{ screenReaderTotalAmountDueText }} {{ getFormattedAmount("", packagePrice) }}
@@ -27,7 +31,11 @@ linkType="text" :text="removeLinkText" href="#!" - @click-event="removeItem(cartItem.cartItemType, cartItem.category)" /> + @click-event="removeItem(cartItem.cartItemType, cartItem.category)"> + +
@@ -56,25 +64,40 @@ {{ recycleFeeCartItem.name }} - {{ getFormattedAmount(cartItem.category, cartItem.subTotal) }} + {{ screenReaderRecycleFeeText }}{{ getFormattedAmount(cartItem.category, cartItem.subTotal) }}
{{ subtotalText }}{{ getFormattedAmount("", subTotal) }} + >{{ screenReaderSubTotalText }}{{ getFormattedAmount("", subTotal) }}
{{ salesTaxText }}{{ getFormattedAmount("", salesTax) }} + >{{ screenReaderSalesTaxText }}{{ getFormattedAmount("", salesTax) }}
{{ amountPaidText }}{{ getFormattedAmount("", amountPaid) }} + >{{ screenReaderAmountPaidText }}{{ getFormattedAmount("", amountPaid) }}
{{ amountDueText }}{{ getFormattedAmount("", amountDue) }} + >{{ screenReaderTotalAmountDueText }}{{ getFormattedAmount("", amountDue) }}
@@ -187,6 +210,24 @@ export default { }, }, computed: { + screenReaderTotalAmountDueText() { + return this.getCmsContent("ScreenReaderTotalAmountDueWidget", "Text"); + }, + screenReaderRemoveVapsText() { + return this.getCmsContent("ScreenReaderRemoveVapsWidget", "Text"); + }, + screenReaderRecycleFeeText() { + return this.getCmsContent("ScreenReaderRecycleFeeWidget", "Text"); + }, + screenReaderSubTotalText() { + return this.getCmsContent("ScreenReaderSubTotalWidget", "Text"); + }, + screenReaderAmountPaidText() { + return this.getCmsContent("ScreenReaderAmountPaidWidget", "Text"); + }, + screenReaderSalesTaxText() { + return this.getCmsContent("ScreenReaderSalesTaxWidget", "Text"); + }, availableLineItems() { if (!this.lineItems || this.lineItems.length < 1) { return []; diff --git a/src/helpers/promotions-helper.js b/src/helpers/promotions-helper.js index 567304de6..3968248d6 100644 --- a/src/helpers/promotions-helper.js +++ b/src/helpers/promotions-helper.js @@ -132,8 +132,19 @@ export async function revalidatePromosAndValidateQueryStringPromo( pageNameToLog, false ); - if (!excludeFromInactivePromoErrorCodes.includes(validatePromoResponse.errorCode)) { - // Save any valid (applied or not) query string promoCode to inactivePromos + if (validatePromoResponse.errorCode == null) { + // Save promo to store + const activePromos = store.getters.order.lineItems.promos ?? []; + activePromos.push(...validatePromoResponse.orderPromos); + baseMixin.methods.dispatchStoreAction( + storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, + { + activePromos: activePromos, + }, + false + ); + } else if (!excludeFromInactivePromoErrorCodes.includes(validatePromoResponse.errorCode)) { + // Save any valid query string promoCode (not applied) to inactivePromos // in order to not lose the query string promoCode if back button is pressed const inactivePromoCodes = store.getters.payment.inactivePromos ?? []; if (!inactivePromoCodes.includes(newPromo)) { @@ -202,16 +213,33 @@ export function buildToastMessagesFromRevalidateOrValidatePromoResponse( } export function getPromosThatMatchLineItemsOnOrder(promos, lineItemsOnOrder) { + const matchingPromoCodes = []; const matchingPromos = []; + const consolidatedPromosWithIds = {}; + // Combine bundle promos to make sure each part of the bundle is satisfied promos.forEach((promo) => { + const cleanPromoCode = getPromoCodeWithoutBundleIdentifier(promo.promoCode); + if (consolidatedPromosWithIds[cleanPromoCode]) { + consolidatedPromosWithIds[cleanPromoCode].push(...promo.discountedLineItemIds); + } else { + consolidatedPromosWithIds[cleanPromoCode] = promo.discountedLineItemIds.slice(0); + } + }); + Object.keys(consolidatedPromosWithIds).forEach((promoCode) => { let allIdsMatch = true; - promo.discountedLineItemIds.forEach((id) => { + consolidatedPromosWithIds[promoCode].forEach((id) => { if (lineItemsOnOrder.filter((x) => x.id === id).length === 0) { allIdsMatch = false; return; } }); if (allIdsMatch) { + matchingPromoCodes.push(promoCode); + } + }); + promos.forEach((promo) => { + const cleanPromoCode = getPromoCodeWithoutBundleIdentifier(promo.promoCode); + if (matchingPromoCodes.includes(cleanPromoCode)) { matchingPromos.push(promo); } }); diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 6fa1b02a6..e13f62590 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -103,6 +103,7 @@ import { getNewlyInactivatedPromos, } from "@/helpers/promotions-helper"; import { queryStrings } from "@/constants/query-strings"; +import { routerParams } from "@/router/router-constants/router-params"; import { getQuerystringParameter } from "@/helpers/querystring-helper"; import { deepClone } from "@/helpers/object-helper"; @@ -421,7 +422,7 @@ export default { } catch (error) { console.log("error: response from pia submit work order:" + error.message); this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); - this.$route.params[this.routerParams.DISPLAY_PIA_ALERT] = true; + this.$route.params[routerParams.DISPLAY_PIA_ALERT] = true; return; } } @@ -469,7 +470,10 @@ export default { return this.paymentMethodInternalModel; }, shouldDisplayPiaAlert() { - return this.$route.params[this.routerParams.DISPLAY_PIA_ALERT]; + return ( + this.$route.query[queryStrings.DISPLAY_PIA_ALERT] || + this.$route.params[routerParams.DISPLAY_PIA_ALERT] + ); }, // Necessary to make the watcher of lineItems work // JavaScript does not keep a record of the old value, only a reference to it's location in the memory. diff --git a/src/layouts/payment-pia-return/payment-pia-return.vue b/src/layouts/payment-pia-return/payment-pia-return.vue index 8088cbb06..d12e45705 100644 --- a/src/layouts/payment-pia-return/payment-pia-return.vue +++ b/src/layouts/payment-pia-return/payment-pia-return.vue @@ -24,12 +24,9 @@ export default { if (piaError) { console.log("Error during payment: " + piaError); - this.$router.navigateWithoutSaving( - this.navigationScenarios.PIA_ERROR, - this.$route, - {}, - { [routerParams.DISPLAY_PIA_ALERT]: true } - ); + this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_ERROR, this.$route, { + [queryStrings.DISPLAY_PIA_ALERT]: true, + }); } else { switch (store.getters.order.payment.piaType) { case paymentMethods.CREDIT_CARD: diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index a07f73566..e48e8fff8 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -178,7 +178,6 @@ export default { vm.supportingItems = resultMap.supportingItems; vm.availableLineItems = pricingResults; vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems); - vm.newValidatedPromos = validatePromoResponse?.orderPromos; if (revalidatePromoResponse) { const revalidateAlerts = buildToastMessagesFromRevalidateOrValidatePromoResponse( @@ -207,16 +206,11 @@ export default { availableLineItems: null, supportingItems: null, pricedGlassParts: null, - newValidatedPromos: null, }; }, computed: { allActivePromos() { - const allActivePromos = []; - if (this.newValidatedPromos) allActivePromos.push(...this.newValidatedPromos); - if (this.$store.getters.order.lineItems.promos) - allActivePromos.push(...this.$store.getters.order.lineItems.promos); - return allActivePromos; + return this.$store.getters.order.lineItems.promos ?? []; }, }, methods: { @@ -294,14 +288,6 @@ export default { } this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false); - this.dispatchStoreAction( - this.storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, - { activePromos: this.allActivePromos }, - false - ); - // Clear out local promos to avoid duplicates in `allActivePromos` computed - // otherwise package price changes while next page is loading - this.newValidatedPromos = []; const payment = this.$store.getters.payment; if (payment.isInsurance) { diff --git a/src/store/index.js b/src/store/index.js index 332b60cf6..efaf5b428 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2130,6 +2130,8 @@ export const actions = { }, // Manage promo saving to ensure a promoCode never ends up in both active and inactive saveActiveAndOrInactivePromos(context, { activePromos = null, inactivePromos = null }) { + activePromos = activePromos?.slice(0); + inactivePromos = inactivePromos?.slice(0); let activePromosToSave; let inactivePromosToSave; if (!activePromos && !inactivePromos) {