Merge branch 'develop' into feature/CSR-32-A

This commit is contained in:
Leah Schumann 2024-03-05 06:44:59 -05:00
commit 9b7d2c8e81
10 changed files with 70 additions and 66 deletions

View file

@ -33,10 +33,9 @@
:key="i" :key="i"
class="packaged-cart-item"> class="packaged-cart-item">
<span <span
><span v-if="cartItem.category === 'promos'">&lt;</span ><span v-if="cartItem.category === 'promos'"></span>{{ cartItem.name
>{{ cartItem.name }}<span v-if="cartItem.category === 'promos'"></span
}}<span v-if="cartItem.category === 'promos'">&gt;</span></span ></span>
>
<textLink <textLink
v-if="allowItemRemoval" v-if="allowItemRemoval"
ref="removeLink" ref="removeLink"
@ -103,7 +102,6 @@
ref="promoModalQuestion" ref="promoModalQuestion"
class="small mt-4" class="small mt-4"
v-model="lineItems" v-model="lineItems"
@addedPromo="handleAddedPromo"
:availableVaps="availableVaps" :availableVaps="availableVaps"
modalWidgetName="PromoModalWidget" /> modalWidgetName="PromoModalWidget" />
</div> </div>
@ -112,7 +110,7 @@
class="my-2 lh-1 applied-promo" class="my-2 lh-1 applied-promo"
v-for="(promoCode, i) in this.getPromoCodeList()" v-for="(promoCode, i) in this.getPromoCodeList()"
:key="i"> :key="i">
<span class="caption">Promo code &lt;{{ promoCode }}&gt; applied </span> <span class="caption">Promo code {{ promoCode }} applied </span>
</div> </div>
<contentGroupModal ref="RecycleModal" cmsWidgetName="RecycleModal"> <contentGroupModal ref="RecycleModal" cmsWidgetName="RecycleModal">
<textBlock cmsWidgetName="RecycleTextBlock" /> <textBlock cmsWidgetName="RecycleTextBlock" />
@ -158,7 +156,6 @@ export default {
style: "currency", style: "currency",
currency: "USD", currency: "USD",
}), }),
lineItems: deepClone(this.modelValue),
}; };
}, },
methods: { methods: {
@ -236,8 +233,6 @@ export default {
this.lineItems[category] = this.lineItems[category].filter( this.lineItems[category] = this.lineItems[category].filter(
(lineItemsToKeep) => lineItemsToKeep.cartItemType != cartItemType (lineItemsToKeep) => lineItemsToKeep.cartItemType != cartItemType
); );
this.$emit("update:modelValue", this.lineItems);
}, },
getPromoCodeList() { getPromoCodeList() {
if (this.$refs["promoModalQuestion"]) { if (this.$refs["promoModalQuestion"]) {
@ -245,12 +240,16 @@ export default {
} }
return []; return [];
}, },
handleAddedPromo(lineItems) {
// NOTE: these lineItems are passed from promo-modal-question
this.$emit("update:modelValue", lineItems);
},
}, },
computed: { computed: {
lineItems: {
get: function () {
return this.modelValue;
},
set: function (newValue) {
this.$emit("update:modelValue", newValue);
},
},
screenReaderTotalAmountDueText() { screenReaderTotalAmountDueText() {
return this.getCmsContent("ScreenReaderTotalAmountDueWidget", "Text"); return this.getCmsContent("ScreenReaderTotalAmountDueWidget", "Text");
}, },
@ -843,14 +842,6 @@ export default {
return this.subTotal + this.salesTax; return this.subTotal + this.salesTax;
}, },
}, },
watch: {
modelValue: {
handler(newValue) {
this.lineItems = deepClone(newValue);
},
deep: true,
},
},
components: { components: {
textBlock, textBlock,
textLink, textLink,

View file

@ -99,7 +99,7 @@ export default {
props: { props: {
modelValue: Object, modelValue: Object,
modalWidgetName: String, modalWidgetName: String,
availableVaps: Object, addableVaps: Object,
pageName: String, pageName: String,
taxPromos: { taxPromos: {
type: Boolean, type: Boolean,
@ -186,14 +186,14 @@ export default {
resetModalButtonStyle() { resetModalButtonStyle() {
this.modal.resetButtonStyle(); this.modal.resetButtonStyle();
}, },
async getPromoCodeData(promoCode, lineItems, availableVaps, pageNameToLog = null) { async getPromoCodeData(promoCode, lineItems, addableVaps, pageNameToLog = null) {
const pageName = pageNameToLog ?? this.$options?.name; const pageName = pageNameToLog ?? this.$options?.name;
const promoValidationResponse = await baseMixin.methods.dispatchStoreActionWithLogging( const promoValidationResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA, storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA,
{ {
promoCode: promoCode, promoCode: promoCode,
lineItemsToUse: lineItems, lineItemsToUse: lineItems,
addableVaps: availableVaps, addableVaps: addableVaps,
}, },
pageName, pageName,
false false
@ -258,7 +258,7 @@ export default {
const promoCodeData = await this.getPromoCodeData( const promoCodeData = await this.getPromoCodeData(
this.promoCode, this.promoCode,
this.lineItems, this.lineItems,
this.availableVaps, this.addableVaps,
this.pageName this.pageName
); );
if (promoCodeData.isValid) { if (promoCodeData.isValid) {
@ -292,7 +292,7 @@ export default {
); );
const taxedVaps = mapTaxedLineItemsToStoreFormat( const taxedVaps = mapTaxedLineItemsToStoreFormat(
taxedLineItems, taxedLineItems,
this.availableVaps this.addableVaps
); );
const getVaps = getVapsThatNeedToBeAddedToSatisfyPromos( const getVaps = getVapsThatNeedToBeAddedToSatisfyPromos(
@ -304,7 +304,6 @@ export default {
this.lineItems.vaps?.push(...getVaps); this.lineItems.vaps?.push(...getVaps);
} }
this.lineItems?.promos.push(...promoCodeData.promoCode); this.lineItems?.promos.push(...promoCodeData.promoCode);
this.$emit("added-promo", this.lineItems);
this.closeModal(); this.closeModal();
} else { } else {
this.getErrorMessage(promoCodeData.errorCode, promoCodeData.additionalInfo); this.getErrorMessage(promoCodeData.errorCode, promoCodeData.additionalInfo);

View file

@ -73,6 +73,13 @@ export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLo
heritageParms["promo"] = promo; 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); router.navigateToExternalUrl(externalUrls.HERITAGE_FUNNEL, heritageParms);
} }

View file

@ -331,10 +331,10 @@ export function getNewlyInactivatedPromos(oldInactivePromos, newInactivePromos)
export function createPromoSuccessAlert(promoCode) { export function createPromoSuccessAlert(promoCode) {
return { return {
messageHeadline: "Promo applied!", messageHeadline: "Promo code applied!",
messageCopy: `Promo "${getPromoCodeWithoutBundleIdentifier( messageCopy: `Promo code ${getPromoCodeWithoutBundleIdentifier(
promoCode.toUpperCase() promoCode.toUpperCase()
)}" was successfully applied to your cart.`, )} was successfully applied to your cart.`,
type: "alert-success", type: "alert-success",
isDismissible: true, isDismissible: true,
shouldAutoFade: true, shouldAutoFade: true,
@ -343,19 +343,19 @@ export function createPromoSuccessAlert(promoCode) {
export function createPromoErrorAlert(promoCode, errorCode = null, additionalInfo) { export function createPromoErrorAlert(promoCode, errorCode = null, additionalInfo) {
const alert = { const alert = {
messageHeadline: "Promo error", messageHeadline: "Promo code error",
type: "alert-danger", type: "alert-danger",
shouldAutoFade: false, shouldAutoFade: false,
isDismissible: true, isDismissible: true,
}; };
if (stackingPromoErrorCodes.includes(errorCode)) { if (stackingPromoErrorCodes.includes(errorCode)) {
alert.messageCopy = `Sorry, promo code "${getPromoCodeWithoutBundleIdentifier( alert.messageCopy = `Sorry, promo code ${getPromoCodeWithoutBundleIdentifier(
promoCode.toUpperCase() promoCode.toUpperCase()
)}" cannot be combined with "${additionalInfo[0].toUpperCase()}"`; )} cannot be combined with ${additionalInfo[0].toUpperCase()}`;
} else { } else {
alert.messageCopy = `Sorry, promo code "${getPromoCodeWithoutBundleIdentifier( alert.messageCopy = `Sorry, promo code ${getPromoCodeWithoutBundleIdentifier(
promoCode.toUpperCase() promoCode.toUpperCase()
)}" is not valid`; )} is not valid`;
} }
return alert; return alert;
} }

View file

@ -29,7 +29,7 @@
:availableLineItems="availableLineItems" :availableLineItems="availableLineItems"
:isInsuranceSelected="isInsuranceSelected" :isInsuranceSelected="isInsuranceSelected"
@vapsItemsSelected="vapsItemsSelectedAction" @vapsItemsSelected="vapsItemsSelectedAction"
:activePromos="allActivePromos" :activePromos="lineItems.promos"
v-on="{ 'buttonEvent.openModal': openModalAction }" v-on="{ 'buttonEvent.openModal': openModalAction }"
validationRules="option-required" validationRules="option-required"
isRequired /> isRequired />
@ -42,7 +42,7 @@
<promoModalQuestion <promoModalQuestion
class="small mt-4" class="small mt-4"
v-model="lineItems" v-model="lineItems"
:availableVaps="availableVaps" :addableVaps="addableVaps"
pageName="quote" pageName="quote"
:taxPromos="false" :taxPromos="false"
modalWidgetName="PromoModalWidget" /> modalWidgetName="PromoModalWidget" />
@ -86,6 +86,7 @@ import baseMixin from "@/mixins/base-mixin.js";
import vehicleQuestionsMixin from "../../mixins/vehicle-questions-mixin"; import vehicleQuestionsMixin from "../../mixins/vehicle-questions-mixin";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import { deepClone } from "@/helpers/object-helper";
import store from "@/store"; import store from "@/store";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { required } from "@/helpers/validation-rules"; import { required } from "@/helpers/validation-rules";
@ -149,7 +150,8 @@ export default {
]; ];
const resultMap = await settleAllPromises(promiseResultMap); 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 nullSafeGlassParts = lineItems.glassParts ?? [];
const availableLineItems = [ const availableLineItems = [
resultMap.rainDefense, resultMap.rainDefense,
@ -172,30 +174,29 @@ export default {
resultMap.supportingItems, resultMap.supportingItems,
false false
); );
lineItems.supportingItems = resultMap.supportingItems;
const addableVaps = [...resultMap.wipers, resultMap.rainDefense];
// Promo logic // Promo logic
// Populate the previous state of promos for toast message usage in "next()" // 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 oldActivePromos = store.getters.lineItems.promos?.slice(0);
const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0); const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0);
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO); const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
const { validatePromoResponse, revalidatePromoResponse } = const { validatePromoResponse, revalidatePromoResponse } =
await revalidatePromosAndValidateQueryStringPromo( await revalidatePromosAndValidateQueryStringPromo(
promoCodeFromQueryString, promoCodeFromQueryString,
pricingResults, pricingResults,
"quote" "quote"
); );
lineItems.glassParts = nullSafeGlassParts; // Sync local promos with any new promos added by validate/revalidate
lineItems.promos = lineItems.promos ?? []; lineItems.promos = store.getters.lineItems.promos ?? [];
lineItems.vaps = lineItems.vaps ?? [];
// End of promo logic // End of promo logic
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.availableVaps = availableVaps; vm.addableVaps = addableVaps;
vm.lineItems = lineItems; vm.lineItems = lineItems;
vm.availableLineItems = pricingResults; vm.availableLineItems = pricingResults;
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems); vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems);
@ -225,13 +226,10 @@ export default {
isInsuranceSelected: null, isInsuranceSelected: null,
availableLineItems: null, availableLineItems: null,
lineItems: [], lineItems: [],
availableVaps: [], addableVaps: [],
}; };
}, },
computed: { computed: {
allActivePromos() {
return this.lineItems.promos ?? [];
},
lineItemsCloneForWatcher() { lineItemsCloneForWatcher() {
return Object.assign({}, this.lineItems); return Object.assign({}, this.lineItems);
}, },
@ -304,7 +302,7 @@ export default {
this.$store.getters.order.payment.parentAccountNumber != this.$store.getters.order.payment.parentAccountNumber !=
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER 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) { if (this.lineItems.glassParts?.length > 0) {
@ -320,7 +318,6 @@ export default {
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
{ {
activePromos: this.lineItems.promos, activePromos: this.lineItems.promos,
inactivePromos: this.$store.getters.order.payment.inactivePromos,
}, },
false false
); );

View file

@ -95,19 +95,14 @@ export default {
}, },
tintSelectionOptions() { tintSelectionOptions() {
let tintOptions = []; const tintOptions = Object.keys(this.featureListData).map((tintOption) => {
const buttonImage = this.getTintSourceImage(this.glassLocation, tintOption);
Object.keys(this.featureListData).forEach((tintOption) => { return {
tintOptions.push({
value: tintOption, value: tintOption,
buttonLabel: tintOption, buttonLabel: tintOption,
buttonImage: require(`@/assets/img/tints/${this.getTintSourceImage( buttonImage: buttonImage ? require(`@/assets/img/tints/${buttonImage}`) : null,
this.glassLocation, };
tintOption
)}`),
});
}); });
return tintOptions; return tintOptions;
}, },

View file

@ -72,7 +72,7 @@ const routes = [
// the saveSessionPromise will no longer point to a valid promise // the saveSessionPromise will no longer point to a valid promise
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_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 //payment pages used to return from safelitehop so exclude here
// Remove the parameter after quote release // Remove the parameter after quote release
const loadSessionResponse = await loadSessionIfPresent( 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. // 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. // 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) { if (pageError) {
var errorCount = Number(pageError); var errorCount = Number(pageError);
if (errorCount > 1) { if (errorCount > 1) {
@ -459,19 +464,19 @@ async function DisplayPageError() {
router.push({ router.push({
path: "/", path: "/",
query: { fmgPage: "vehicle" }, query: { fmgPage: navPage },
}); });
} else { } else {
errorCount++; errorCount++;
router.push({ router.push({
path: "/", path: "/",
query: { fmgPage: "vehicle", pageError: errorCount }, query: { fmgPage: navPage, pageError: errorCount },
}); });
} }
} else { } else {
router.push({ router.push({
path: "/", path: "/",
query: { fmgPage: "vehicle", pageError: "1" }, query: { fmgPage: navPage, pageError: "1" },
}); });
} }
} }

View file

@ -514,7 +514,7 @@ export const mutations = {
state.order.damage.glassToReplace = sessionInformation.order.damage.glassToReplace; state.order.damage.glassToReplace = sessionInformation.order.damage.glassToReplace;
state.order.damage.isRepair = sessionInformation.order.damage.isRepair; state.order.damage.isRepair = sessionInformation.order.damage.isRepair;
state.order.damage.numberOfChips = sessionInformation.order.damage.numberOfChips; 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.damageCause = sessionInformation.order.damage?.damageCause;
state.order.damage.partQuestionAnswers = state.order.damage.partQuestionAnswers =
@ -1101,6 +1101,10 @@ export const actions = {
parentAccountNumber, parentAccountNumber,
} }
) { ) {
if (!pageName) {
return;
}
var payload = { var payload = {
userId: userId, userId: userId,
sessionKey: sessionKey, sessionKey: sessionKey,
@ -1146,6 +1150,10 @@ export const actions = {
parentAccountNumber, parentAccountNumber,
} }
) { ) {
if (!pageName) {
return;
}
var payload = { var payload = {
userId: userId, userId: userId,
sessionKey: sessionKey, sessionKey: sessionKey,

View file

@ -10,6 +10,7 @@
class="d-flex w-100 align-items-center px-2 h-100 list-card-content button-content rounded-3" class="d-flex w-100 align-items-center px-2 h-100 list-card-content button-content rounded-3"
:class="labelClasses"> :class="labelClasses">
<img <img
v-if="buttonImage"
:id="buttonImageId" :id="buttonImageId"
:class="!isWide ? 'order-1' : 'ms-auto order-3'" :class="!isWide ? 'order-1' : 'ms-auto order-3'"
:src="buttonImage" :src="buttonImage"

View file

@ -1,5 +1,6 @@
process.env.VUE_APP_CONSUMER_CF_DISTRO = "https://digitalapi.dev.safelite.io"; process.env.VUE_APP_CONSUMER_CF_DISTRO = "https://digitalapi.dev.safelite.io";
process.env.VUE_APP_HERITAGE_FUNNEL = "http://localhost:38000/default.aspx"; //process.env.VUE_APP_HERITAGE_FUNNEL = "http://localhost:38000/default.aspx";
process.env.VUE_APP_HERITAGE_FUNNEL = "https://fixmyglassdev.safelite.com/default.aspx";
process.env.VUE_APP_GOOGLE_PLACES_API_KEY = "AIzaSyDptGCkOPgN2uWJOy4ou4M33phRD4MAoJo"; process.env.VUE_APP_GOOGLE_PLACES_API_KEY = "AIzaSyDptGCkOPgN2uWJOy4ou4M33phRD4MAoJo";
process.env.VUE_APP_CURRENT_ENVIRONMENT = "Localhost"; process.env.VUE_APP_CURRENT_ENVIRONMENT = "Localhost";
process.env.VUE_APP_MY_ACCOUNT = "https://myaccountdev.safelite.com/"; process.env.VUE_APP_MY_ACCOUNT = "https://myaccountdev.safelite.com/";