diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index c9592c315..41e5896bd 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -102,6 +102,8 @@ const storeActions = { RESET_SUBMITTED_ORDER: "resetSubmittedOrder", RESET_EXTERNAL_PARAMETER_STATE: "resetExternalParameterState", UPDATE_EXTERNAL_PARAMETER_MMS: "updateExternalParameterMMS", + + SAVE_LOGGING_OPTION: "saveLoggingOption", }; export { storeActions }; diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index 02b05bd28..740c5a47e 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -84,6 +84,7 @@ const storeMutations = { UPDATE_STATE_WITH_ORDER_INFORMATION: "updateStateWithOrderInformation", UPDATE_SAVE_SESSION_PROMISE: "updateSaveSessionPromise", UPDATE_LAST_PAGE_VISITED: "updateLastPageVisited", + UPDATE_LOGGING_OPTION: "updateLoggingOption", // EXPERIMENT MUTATIONS UPDATE_EXPERIMENTS: "updateExperiments", diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index 52049b0c9..e21a5037a 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -199,6 +199,7 @@ export default { shouldHideRecalibration: Boolean, isItac: Boolean, isNoComp: Boolean, + isExpandedOnLoad: Boolean, }, data() { return { @@ -217,7 +218,7 @@ export default { this.isExpanded = !this.isExpanded; }, updateIsExpandedWithDefault() { - this.isExpanded = this.shouldHideRecalibration; + this.isExpanded = this.isExpandedOnLoad; }, getVapsPrice(packageName) { const vapsItems = this.getVapsCartItemsForSelectedPackage(packageName); @@ -297,8 +298,8 @@ export default { this.lineItems[category] = this.lineItems[category].filter( (lineItemsToKeep) => lineItemsToKeep.cartItemType != cartItemType ); - if (category == cartItemCategories.VAPS) { - await this.dispatchStoreAction(storeActions.SAVE_VAPS, this.lineItems.vaps, false); + if (category == cartItemCategories.VAPS || category == cartItemCategories.PROMOS) { + this.saveVaps(this.lineItems); } if (category == cartItemCategories.SUPPORTING_ITEMS) { await this.dispatchStoreAction( @@ -331,9 +332,8 @@ export default { }, computed: { isCartReadyToLoad() { - var myReturn = this.shouldHideRecalibration !== null; this.updateIsExpandedWithDefault(); - return myReturn; + return this.isExpandedOnLoad !== null; }, lineItems: { get: function () { @@ -749,8 +749,13 @@ export default { recycleFeeCartItemName() { return this.getCmsContent("RecycleFeeTextWidget", "Text"); }, - requiresRecycleFeeCartItem() { - return !this.isRepair; + showRecycleFeeCartItem() { + if (!this.isInsurance || this.isItac || this.isNoComp) { + // CASH, ITAC, NOCOMP ORDERS + return !this.isRepair; + } else { + return false; + } }, recycleFeeCartItem() { let cartItem = null; @@ -759,7 +764,7 @@ export default { (supportingItem) => supportingItem.partType == partTypeStrings.REPLACE_FEE ); - if (!recycleFeeLineItem && this.requiresRecycleFeeCartItem) { + if (!recycleFeeLineItem && this.showRecycleFeeCartItem) { recycleFeeLineItem = { partNumber: partTypeStrings.RECYCLE_FEE, partType: partTypeStrings.REPLACE_FEE, diff --git a/src/fmg-components/promo-modal-question/promo-modal-question.spec.js b/src/fmg-components/promo-modal-question/promo-modal-question.spec.js index 435a53277..b2e0547b0 100644 --- a/src/fmg-components/promo-modal-question/promo-modal-question.spec.js +++ b/src/fmg-components/promo-modal-question/promo-modal-question.spec.js @@ -19,6 +19,11 @@ jest.mock("@/mixins/base-mixin", () => ({ return mockReturnsForStoreActions[action]; } ), + dispatchStoreAction: jest.fn( + (action, { promoCode, addableVaps }, pageNameToLog, someBool) => { + return mockReturnsForStoreActions[action]; + } + ), }, })); @@ -286,6 +291,13 @@ describe("promo-modal-question.vue", () => { (lineItemsToKeep) => getPromoCodeWithoutBundleIdentifier(lineItemsToKeep.promoCode) != promo )); + await baseMixin.methods.dispatchStoreAction( + storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, + { + activePromos: lineItems.promos, + }, + false + ); //Assert expect(existingPromo).toEqual(lineItems.promos); 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 97788a4b9..656aeaa38 100644 --- a/src/fmg-components/promo-modal-question/promo-modal-question.vue +++ b/src/fmg-components/promo-modal-question/promo-modal-question.vue @@ -10,7 +10,7 @@ :ref="modalName" :headerText="modalHeaderText" :onModalClosedCallback="onModalClosed" - :onModalOpenedCallback="focusOnPromoInput" + :onModalOpenedCallback="openModal" :footerButtonText="modalFooterText" @footer-button-event="addPromoCode"> getPromoCodeWithoutBundleIdentifier(lineItemsToKeep.promoCode) != promo ); + await baseMixin.methods.dispatchStoreAction( + storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, + { + activePromos: this.lineItems.promos, + }, + false + ); }, getErrorMessage(error, additionalInfo) { switch (error) { diff --git a/src/helpers/heritage-integration/cookie-helper.js b/src/helpers/heritage-integration/cookie-helper.js index 0bd4ae563..4ff5c0c8e 100644 --- a/src/helpers/heritage-integration/cookie-helper.js +++ b/src/helpers/heritage-integration/cookie-helper.js @@ -13,7 +13,7 @@ export function updateOrCreateFunnelCookie() { // Set up cookie with all the props. setFunnelCookieProperties({ - LastTouched: new Date().toUTCString(), + LastTouched: new Date().toJSON(), SavedSessionTimeoutDate: store.getters.applicationUser.savedSessionTimeout, DidHeritageFunnelUpdateLast: false, ShouldResetState: false, diff --git a/src/helpers/heritage-integration/session-helper.js b/src/helpers/heritage-integration/session-helper.js index 291ebfaf8..d932969d1 100644 --- a/src/helpers/heritage-integration/session-helper.js +++ b/src/helpers/heritage-integration/session-helper.js @@ -43,5 +43,5 @@ Function to calculate the date for the saved session timeout. export function getDateForSavedSessionTimeout() { const currentDate = new Date(new Date().toUTCString()); currentDate.setDate(currentDate.getDate() + applicationConfig.SAVED_SESSION_TIMEOUT_DAYS); - return currentDate.toUTCString(); + return currentDate.toJSON(); } diff --git a/src/helpers/heritage-integration/session-helper.spec.js b/src/helpers/heritage-integration/session-helper.spec.js index fe3e308da..11440c544 100644 --- a/src/helpers/heritage-integration/session-helper.spec.js +++ b/src/helpers/heritage-integration/session-helper.spec.js @@ -81,7 +81,7 @@ describe("getDateForSavedSessionTimeout", () => { currentDate.setDate(currentDate.getDate() + applicationConfig.SAVED_SESSION_TIMEOUT_DAYS); // Act - const result = getDateForSavedSessionTimeout(); + const result = new Date(getDateForSavedSessionTimeout()).toUTCString(); // Assert expect(result).toEqual(currentDate.toUTCString()); diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue index 09b666920..90886a9b7 100644 --- a/src/layouts/confirmation/confirmation.vue +++ b/src/layouts/confirmation/confirmation.vue @@ -45,7 +45,7 @@ class="duration-text-block" /> -
+
@@ -111,6 +112,8 @@ import { containsRecalParts } from "@/helpers/recal-helper.js"; export default { name: "confirmation", async beforeRouteEnter(to, from, next) { + const hasRecalPriceRemoveExperiment = await store.getters.shouldHideRecalibration; + await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_ORDER); // This nulls the Store order // Call APIs @@ -155,10 +158,6 @@ export default { const isNoComp = submittedOrder?.policy?.isNoComp; const isItac = submittedOrder?.policy?.isItac; const isRecalibrationOnOrder = containsRecalParts(lineItemsFromSubmittedOrder); - const hasRecalPriceRemoveExperiment = - experimentMixin.methods - .getSettingValue(experimentSettings.RECAL_PRICE_REMOVE) - ?.toLowerCase() === "true"; const shouldHideRecalibration = () => { if (isNoComp || isItac) { diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index f4972a054..fa6fd234c 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -32,9 +32,10 @@ :showInsuranceCoverageAs="showInsuranceCoverageAs" :shouldHideRecalibration="shouldHideRecalibration" :isItac="isItac" - :isNoComp="isNoComp" /> + :isNoComp="isNoComp" + :isExpandedOnLoad="false" /> -
+
-
+

-
+
+ :isNoComp="isNoComp" + :isExpandedOnLoad="true" />
diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index 5b8695d3e..533081210 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -428,8 +428,11 @@ export default { ); }, shouldHideRecalibration() { - if (this.isInsuranceSelected) return false; - return (experimentMixin.methods.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)?.toLowerCase() === "true" && this.isRecalibrationOnOrder); + return ( + experimentMixin.methods + .getSettingValue(experimentSettings.RECAL_PRICE_REMOVE) + ?.toLowerCase() === "true" && this.isRecalibrationOnOrder + ); }, showAfterpayBanner() { return ( diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 732e23ba9..7cce1c120 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -436,7 +436,6 @@ export default { policy.policyNumber !== ""; const skipVin = await skipVinLookup(); - if (vehicleChangedDuringPolicyLookupInHeritage) { if (skipVin) { this.$router.navigateWithSaving( @@ -455,13 +454,22 @@ export default { { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false } ); } else { - this.$router.navigateWithSaving( - this.navigationScenarios - .CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE, - this.$route, - {}, - { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false } - ); + if (store.getters.vehicle.vin) { + this.$router.navigateWithSaving( + this.navigationScenarios + .CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE, + this.$route, + {}, + { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false } + ); + } else { + this.$router.navigateWithSaving( + this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN, + this.$route, + {}, + { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false } + ); + } } } } diff --git a/src/router/index.js b/src/router/index.js index f736854b4..53adc4613 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -460,6 +460,7 @@ async function navigate( const promo = getQuerystringParameter(queryStrings.PROMO); const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR); const logQs = getQuerystringParameter(queryStrings.LOG); + baseMixin.methods.dispatchStoreAction(storeActions.SAVE_LOGGING_OPTION, logQs, false); log("------------- router index.js navigate start -----------------"); log(" --scenario: ", scenario); diff --git a/src/store/index.js b/src/store/index.js index a5d1f4e68..6a67a9bc7 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -41,7 +41,11 @@ import { coverageTypeValue, coverageTypeEnum, } from "@/constants/insurance"; -import { containsRecalParts, getTopLevelPartsWithRecal } from "@/helpers/recal-helper"; +import { + containsRecalParts, + getTopLevelPartsWithRecal, + isRecalPartOrHasChildRecalPart, +} from "@/helpers/recal-helper"; import { externalParameterStatus } from "@/constants/external-parameters"; import { experimentSettings } from "@/constants/experiments"; import experimentMixin from "@/mixins/experiment-mixin.js"; @@ -180,6 +184,7 @@ const getDefaultState = () => { experiments: [], triggeredSiteEntry: false, affiliateCookies: [], + loggingOption: false, }, }; }; @@ -410,6 +415,9 @@ export const mutations = { updateLastPageVisited(state, lastPageVisited) { state.applicationUser.lastPageVisited = lastPageVisited; }, + updateLoggingOption(state, loggingOption) { + state.applicationUser.loggingOption = loggingOption; + }, // EVENT BUS MUTATIONS addEventToBus(state, event) { state.applicationUser.eventBus.push(event); @@ -685,6 +693,10 @@ export const mutations = { !sessionInformation.order.payment.isInsurance && !sessionInformation.order.serviceLocation.provider?.providerNumber ) { + console.log( + "------------- updateStateWithOrderInformation reset isInsurance -----------------" + ); + console.log(new Date() + " sessionInformation: " + JSON.stringify(sessionInformation)); state.order.payment.isInsurance = null; } else { state.order.payment.isInsurance = sessionInformation.order.payment.isInsurance; @@ -1025,6 +1037,7 @@ export const actions = { endpoint: endpoints.LookupVehicleByVin.url, payload: { vin: vin, // EX "1J4GW58S4XC541166" + logEnabled: context.getters.applicationUser.loggingOption, }, logApiCall: true, pageNameToLog: pageNameToLog, @@ -1651,9 +1664,10 @@ export const actions = { const partialLineItemsObjects = context.getters.order.lineItems.glassParts?.map( (lineItem) => ({ partNumber: lineItem.partNumber, - recalibrationType: lineItem.recalibrationType - ? escapeRecalibrationType(lineItem.recalibrationType) - : undefined, + recalibrationType: + lineItem.recalibrationType && isRecalPartOrHasChildRecalPart(lineItem) + ? escapeRecalibrationType(lineItem.recalibrationType) + : undefined, }) ); @@ -3009,6 +3023,15 @@ export const actions = { ); }, + saveLoggingOption(context, loggingOption) { + var option = false; + if (loggingOption != null) { + option = loggingOption == "true" ? true : false; + } + + context.commit(storeMutations.UPDATE_LOGGING_OPTION, option); + }, + async getRecalPartsAndSaveToLineItems(context, { pageNameToLog }) { // identify each part that needs recal const glassParts = context.state.order?.lineItems?.glassParts diff --git a/src/store/store.spec.js b/src/store/store.spec.js index 313e7e37f..094793bc1 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -404,6 +404,11 @@ describe("Actions", () => { it("lookupVehicleByVin action, should return car data", async () => { // Arrange const context = state; + context.getters = { + applicationUser: { + loggingOption: false, + }, + }; // Act globalMethods.callHttpClient.mockImplementation(() => { diff --git a/src/styles/common-styles.scss b/src/styles/common-styles.scss index 730712297..002debed8 100644 --- a/src/styles/common-styles.scss +++ b/src/styles/common-styles.scss @@ -10,7 +10,7 @@ body { overflow-x: unset; } &.page-container-grouped-styles { - height: 100vh; + height: 100dvh; display: flex; flex-direction: column; } @@ -68,6 +68,14 @@ body { height: 1px; overflow: hidden; } + + // Fix "iOS viewport scroll bug" issue on iPhone + // where bottom of page is covered by address bar + @media only screen and (min-device-width: 375px) and (max-device-width: 812px) and (-webkit-min-device-pixel-ratio: 3) and (orientation: portrait) { + .page-container-grouped-styles { + padding-bottom: 3rem; + } + } } .modal-open { .container-fluid { diff --git a/src/ux-components/list-button-horizontal/list-button-horizontal.vue b/src/ux-components/list-button-horizontal/list-button-horizontal.vue index 3a360c1bc..8bcd7bd3a 100644 --- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue +++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue @@ -7,7 +7,7 @@ ]" v-model="selectedValue">
+ class="button-content list-button-horizontal-content d-flex flex-column justify-content-center py-3 px-1"> {{ buttonLabel }}