Merge pull request #1583 from Safelite/release/2023.12.07
Release/2023.12.07
This commit is contained in:
commit
70048339f1
7 changed files with 93 additions and 34 deletions
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@
|
|||
class="row vin-toggle flex align-items-center pt-4"
|
||||
:class="[isExpanded ? 'expanded' : '']"
|
||||
@click="toggleIsExpanded()">
|
||||
<a href="#!" class="col d-flex justify-content-between py-0">
|
||||
<a
|
||||
aria-label="expand cart"
|
||||
href="#!"
|
||||
class="col d-flex justify-content-between py-0">
|
||||
<span class="label">{{ amountDueText }}</span>
|
||||
<span class="label amount-due">{{ getFormattedAmount("", amountDue) }}</span>
|
||||
</a>
|
||||
|
|
@ -13,7 +16,8 @@
|
|||
<div class="price-table">
|
||||
<div class="service-type">
|
||||
<textBlock :cmsWidgetName="servicePackageTitleWidget" />
|
||||
<span>
|
||||
<span tabindex="0">
|
||||
<span class="sr-only">{{ screenReaderTotalAmountDueText }}</span>
|
||||
{{ getFormattedAmount("", packagePrice) }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -27,7 +31,11 @@
|
|||
linkType="text"
|
||||
:text="removeLinkText"
|
||||
href="#!"
|
||||
@click-event="removeItem(cartItem.cartItemType, cartItem.category)" />
|
||||
@click-event="removeItem(cartItem.cartItemType, cartItem.category)">
|
||||
<template v-slot:after-text>
|
||||
<span class="sr-only">{{ cartItem.name }}</span>
|
||||
</template>
|
||||
</textLink>
|
||||
</div>
|
||||
|
||||
<!-- Nonpackaged Cart Items -->
|
||||
|
|
@ -56,25 +64,40 @@
|
|||
<span v-else-if="cartItem == recycleFeeCartItem">
|
||||
{{ recycleFeeCartItem.name }}
|
||||
</span>
|
||||
<span>{{ getFormattedAmount(cartItem.category, cartItem.subTotal) }}</span>
|
||||
<span tabindex="0"
|
||||
><span class="sr-only">{{ screenReaderRecycleFeeText }}</span
|
||||
>{{ getFormattedAmount(cartItem.category, cartItem.subTotal) }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Sub total, sales tax, total columns -->
|
||||
<div class="sub-total">
|
||||
<span>{{ subtotalText }}</span
|
||||
><span>{{ getFormattedAmount("", subTotal) }}</span>
|
||||
><span tabindex="0"
|
||||
><span class="sr-only">{{ screenReaderSubTotalText }}</span
|
||||
>{{ getFormattedAmount("", subTotal) }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="sales-tax">
|
||||
<span>{{ salesTaxText }}</span
|
||||
><span>{{ getFormattedAmount("", salesTax) }}</span>
|
||||
><span tabindex="0"
|
||||
><span class="sr-only">{{ screenReaderSalesTaxText }}</span
|
||||
>{{ getFormattedAmount("", salesTax) }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="showAsPaid" class="amount-paid">
|
||||
<span>{{ amountPaidText }}</span
|
||||
><span>{{ getFormattedAmount("", amountPaid) }}</span>
|
||||
><span tabindex="0"
|
||||
><span class="sr-only">{{ screenReaderAmountPaidText }}</span
|
||||
>{{ getFormattedAmount("", amountPaid) }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="amount-due">
|
||||
<span>{{ amountDueText }}</span
|
||||
><span>{{ getFormattedAmount("", amountDue) }}</span>
|
||||
><span tabindex="0"
|
||||
><span class="sr-only">{{ screenReaderTotalAmountDueText }}</span
|
||||
>{{ getFormattedAmount("", amountDue) }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -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 [];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue