From d5321112fb2e5dffe92a4b049a5ba585f3301ef1 Mon Sep 17 00:00:00 2001 From: Mark Harris Date: Mon, 19 Sep 2022 15:35:21 -0400 Subject: [PATCH 01/20] Renamed helper method --- src/store/index.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 614d54d4b..2ea58660e 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -393,20 +393,20 @@ export const getters = { funnelIsCoverageVerified: state.order.payment.insuranceCoverage.isVerified, funnelHasRecalibrationPart: getHasRecalibrationPart(state), funnelSelectedMultiGlass: state.order.damage.glassToReplace?.length > 1, - funnelSelectedWindshieldGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.WINDSHIELD), - funnelSelectedBackGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.REAR), - funnelSelectedDriverSideGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.DRIVER), - funnelSelectedPassengerSideGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.PASSENGER), + funnelSelectedWindshieldGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.WINDSHIELD), + funnelSelectedBackGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.REAR), + funnelSelectedDriverSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.DRIVER), + funnelSelectedPassengerSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.PASSENGER), - funnelOrderPartNumbers: [...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "partNumber"), ...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, "partNumber")], + funnelOrderPartNumbers: [...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "partNumber"), ...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, "partNumber")], - funnelOrderPartTypes: [...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType"), ...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, "recalibrationType")], + funnelOrderPartTypes: [...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType"), ...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, "recalibrationType")], } }, experimentSettings: (state) => state.applicationUser.experiments.map(x => x.settings).reduce((r, c) => Object.assign(r, c), {}) ?? {} } -function getAllValuesOfPropertyInArrayOfObjects(array, propertyName) { +function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) { return (array ?? []).map(x => x[propertyName]).filter(x => x); } @@ -1121,12 +1121,12 @@ export default createStore({ // Private Functions function getHasRecalibrationPart(state) { - var hasRequiresRecalibration = getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "requiresRecalibration")?.length > 0; - var hasRecalibrationType = getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType")?.length > 0; + var hasRequiresRecalibration = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "requiresRecalibration")?.length > 0; + var hasRecalibrationType = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType")?.length > 0; if (hasRequiresRecalibration) { if (hasRecalibrationType) { // Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType' - return getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType")[0].toLowerCase() != "unknown"; + return getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType")[0].toLowerCase() != "unknown"; } else { // Has 'requiresRecalibration' but no 'recalibrationType' at all return true; } From aba72ca59329c5117eb50a44297043c09074adc5 Mon Sep 17 00:00:00 2001 From: Katie Date: Thu, 29 Sep 2022 15:08:13 -0400 Subject: [PATCH 02/20] CSR-762 Get GA event working with state --- .../base-input-button/base-input-button.vue | 112 +-- src/constants/store-actions.js | 138 ++-- src/constants/store-mutations.js | 124 ++-- src/main.js | 2 + src/mixins/analytics-mixin.js | 2 + src/store/gaState.js | 122 ++-- src/store/index.js | 642 +++++++++++++----- 7 files changed, 736 insertions(+), 406 deletions(-) diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index e46e1a07d..d3574fef2 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -25,6 +25,8 @@ import { queryStrings } from "@/constants/query-strings"; import { useField } from "vee-validate"; import { toRef } from "vue"; +import { gaStoreActions } from "../../constants/store-actions"; +import store from "../../store"; export default { name: "base-input-button", @@ -83,7 +85,12 @@ export default { case eventTypes.KEYPRESS_SUBMIT: case eventTypes.CHANGE: this.handleClick(e); - window.lastFocusedInputGroup = this.groupName; + this.dispatchStoreAction( + gaStoreActions.UPDATE_LAST_FOCUSED_INPUT_GROUP, + this.groupName, + false + ); + // window.lastFocusedInputGroup = this.groupName; this.pushClickEventToGA(); break; } @@ -119,9 +126,17 @@ export default { this.valueToEmit = this.value; } - window.currentlySelectedValues = - window.currentlySelectedValues ?? {}; - window.currentlySelectedValues[this.groupName] = this.value; + // window.currentlySelectedValues = + // window.currentlySelectedValues ?? {}; + this.dispatchStoreAction( + gaStoreActions.UPDATE_CURRENTLY_SELECTED_VALUES, + { + groupName: this.groupName, + value: this.value, + }, + // false + ); + // window.currentlySelectedValues[this.groupName] = this.value; this.handleChange(this.valueToEmit); }, handleClick(e) { @@ -129,10 +144,20 @@ export default { this.$emit("buttonClicked", this.valueToEmit); }, pushClickEventToGA(value) { - window.firedGaClickEventValues = - window.firedGaClickEventValues ?? {}; - window.firedGaClickEventValues[window.lastFocusedInputGroup] = - value ?? this.value; + // window.firedGaClickEventValues = + // window.firedGaClickEventValues ?? {}; + const lastFocusedInputGroup = + store.getters.gaClickInformation.lastFocusedInputGroup; + this.dispatchStoreAction( + gaStoreActions.UPDATE_FIRED_GA_CLICK_EVENT_VALUES, + { + groupName: lastFocusedInputGroup, + value: value ?? this.value, + }, + // false + ); + // window.firedGaClickEventValues[window.lastFocusedInputGroup] = + // value ?? this.value; this.pushEventToGA( this.$route.query[queryStrings.FMG_PAGE], @@ -143,65 +168,68 @@ export default { ); }, handleBlur() { - window.lastFocusedInputGroup = this.groupName; - window.wasLastFocusedInputMultiselect = this.isMultiSelect; + this.dispatchStoreAction( + gaStoreActions.UPDATE_LAST_FOCUSED_INPUT_GROUP, + this.groupName, + false + ); + this.dispatchStoreAction( + gaStoreActions.UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT, + this.isMultiSelect, + false + ); + // window.lastFocusedInputGroup = this.groupName; + // window.wasLastFocusedInputMultiselect = this.isMultiSelect; }, handleKeyboardNavigation(key) { this.test(key); }, test(event) { - window.firedGaClickEventValues = - window.firedGaClickEventValues ?? {}; - window.currentlySelectedValues = - window.currentlySelectedValues ?? {}; + const gaClickInformation = store.getters.gaClickInformation; + const firedGaClickEventValues = + gaClickInformation.firedGaClickEventValues; + const currentlySelectedValues = + gaClickInformation.currentlySelectedValues; + const lastFocusedInputGroup = + gaClickInformation.lastFocusedInputGroup; + const wasLastFocusedInputMultiselect = + gaClickInformation.wasLastFocusedInputMultiselect; const keyCode = event?.code; // Keyboard navigation if (keyCode) { if ( - window.currentlySelectedValues && - window.firedGaClickEventValues && - window.lastFocusedInputGroup && - !window.wasLastFocusedInputMultiselect && - window.currentlySelectedValues[ - window.lastFocusedInputGroup - ] && - window.firedGaClickEventValues[ - window.lastFocusedInputGroup - ] != - window.currentlySelectedValues[ - window.lastFocusedInputGroup - ] + !wasLastFocusedInputMultiselect && + currentlySelectedValues[lastFocusedInputGroup] && + firedGaClickEventValues[lastFocusedInputGroup] != + currentlySelectedValues[lastFocusedInputGroup] ) { if (keyCode === "Tab") { this.pushClickEventToGA( - window.currentlySelectedValues[ - window.lastFocusedInputGroup - ] + currentlySelectedValues[lastFocusedInputGroup] ); } else if (keyCode?.includes("Arrow")) { - if (window.lastFocusedInputGroup != this.groupName) { + if (lastFocusedInputGroup != this.groupName) { this.pushClickEventToGA( - window.currentlySelectedValues[ - window.lastFocusedInputGroup - ] + currentlySelectedValues[lastFocusedInputGroup] ); } } } } else { // Radio click - window.lastFocusedInputGroup = this.groupName; + this.dispatchStoreAction( + gaStoreActions.UPDATE_LAST_FOCUSED_INPUT_GROUP, + this.groupName, + false + ); + // window.lastFocusedInputGroup = this.groupName; if ( - window.firedGaClickEventValues[ - window.lastFocusedInputGroup - ] != - window.currentlySelectedValues[window.lastFocusedInputGroup] + firedGaClickEventValues[lastFocusedInputGroup] != + currentlySelectedValues[lastFocusedInputGroup] ) { this.pushClickEventToGA( - window.currentlySelectedValues[ - window.lastFocusedInputGroup - ] + currentlySelectedValues[lastFocusedInputGroup] ); } } diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index ff5100070..65d3789a1 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -1,78 +1,84 @@ const storeActions = { - // Content Actions - GET_ROUTE_INFO_ACTION: "getRouteInfo", - GET_HOMEPAGE_NAME: "getHomepageName", - GET_PAGE_DATA: "getPageData", + // Content Actions + GET_ROUTE_INFO_ACTION: "getRouteInfo", + GET_HOMEPAGE_NAME: "getHomepageName", + GET_PAGE_DATA: "getPageData", - // Vehicle Actions - GET_VEHICLE_YEARS: "getVehicleYears", - GET_VEHICLE_MAKES: "getVehicleMakes", - GET_VEHICLE_MODELS: "getVehicleModels", - GET_VEHICLE_STYLES: "getVehicleStyles", - SET_VEHICLE: "setVehicle", - GET_DAMAGE_OPTIONS: "getDamageOptions", - GET_EVOX_IMAGE: "getEvoxImage", + // Vehicle Actions + GET_VEHICLE_YEARS: "getVehicleYears", + GET_VEHICLE_MAKES: "getVehicleMakes", + GET_VEHICLE_MODELS: "getVehicleModels", + GET_VEHICLE_STYLES: "getVehicleStyles", + SET_VEHICLE: "setVehicle", + GET_DAMAGE_OPTIONS: "getDamageOptions", + GET_EVOX_IMAGE: "getEvoxImage", - // Lookup Actions - LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms", - LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin", - LOOKUP_VIN_BY_PLATE: "lookupVinByPlate", - LOOKUP_VIN_BY_ADDRESS: "lookupVinByAddress", + // Lookup Actions + LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms", + LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin", + LOOKUP_VIN_BY_PLATE: "lookupVinByPlate", + LOOKUP_VIN_BY_ADDRESS: "lookupVinByAddress", - GET_PARTS_OR_QUESTIONS: "getPartsOrQuestions", - GET_PARTS: "getParts", - GET_CAPABILITY_QUESTIONS: "getCapabilityQuestions", - GET_PART_FROM_CAPABILITY_QUESTION_ANSWER: - "getPartFromCapabilityQuestionAnswer", - GET_MOLDING_QUESTIONS: "getMoldingQuestions", - SAVE_ORDER: "saveOrder", - LOAD_ORDER: "loadOrder", - UPDATE_STORE_WITH_SAVE_ORDER_RESPONSE: "updateStoreWithSaveOrderResponse", - VALIDATE_ZIP: "validateZip", - LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure", - LOG_PAGE_VIEW: "logPageView", - LOG_CUSTOM_EVENT: "logCustomEvent", - INITIALIZE_SESSION: "initializeSession", - GET_EXPERIMENTS_BY_USER: "GetExperimentsByUser", - RUN_EXPERIMENTS_FOR_TRIGGER: "runExperimentsForTrigger", - CLEAR_VIN: "clearVin", - RESET_SAVE_ORDER_PROMISE: "resetSaveOrderPromise", + GET_PARTS_OR_QUESTIONS: "getPartsOrQuestions", + GET_PARTS: "getParts", + GET_CAPABILITY_QUESTIONS: "getCapabilityQuestions", + GET_PART_FROM_CAPABILITY_QUESTION_ANSWER: + "getPartFromCapabilityQuestionAnswer", + GET_MOLDING_QUESTIONS: "getMoldingQuestions", + SAVE_ORDER: "saveOrder", + LOAD_ORDER: "loadOrder", + UPDATE_STORE_WITH_SAVE_ORDER_RESPONSE: "updateStoreWithSaveOrderResponse", + VALIDATE_ZIP: "validateZip", + LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure", + LOG_PAGE_VIEW: "logPageView", + LOG_CUSTOM_EVENT: "logCustomEvent", + INITIALIZE_SESSION: "initializeSession", + GET_EXPERIMENTS_BY_USER: "GetExperimentsByUser", + RUN_EXPERIMENTS_FOR_TRIGGER: "runExperimentsForTrigger", + CLEAR_VIN: "clearVin", + RESET_SAVE_ORDER_PROMISE: "resetSaveOrderPromise", - // DEPENDENCY MUTATIONS - RESET_VEHICLE_STATE_AND_DEPENDENCIES: "resetVehicleAndDependencies", - RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies", - RESET_REGISTRATION_STATE_AND_DEPENDENCIES: - "resetRegistrationAndDependencies", - RESET_PARTS_STATE_AND_DEPENDENCIES: "resetPartsAndDependencies", - RESET_STATE: "resetState", + // DEPENDENCY MUTATIONS + RESET_VEHICLE_STATE_AND_DEPENDENCIES: "resetVehicleAndDependencies", + RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies", + RESET_REGISTRATION_STATE_AND_DEPENDENCIES: "resetRegistrationAndDependencies", + RESET_PARTS_STATE_AND_DEPENDENCIES: "resetPartsAndDependencies", + RESET_STATE: "resetState", - // SAVE COMPONENT STATE - SAVE_VEHICLE_YEAR: "saveVehicleYear", - SAVE_VEHICLE_MAKE: "saveVehicleMake", - SAVE_VEHICLE_MODEL: "saveVehicleModel", - SAVE_VEHICLE_STYLE: "saveVehicleStyle", - SAVE_VEHICLE_DAMAGE: "saveVehicleDamage", - SAVE_VIN_LOOKUP: "saveVinLookup", - SAVE_SERVICE_LOCATION: "saveServiceLocation", - SAVE_EMAIL: "saveEmail", - SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP: - "saveRegistrationLicensePlateLookup", - SAVE_VIN: "saveVin", - SAVE_REGISTRATION_ADDRESS_LOOKUP: "saveRegistrationAddressLookup", - SAVE_GLASS_PARTS: "saveGlassParts", - SAVE_PART_QUESTION_ANSWERS: "savePartQuestionAnswers", - RESET_MOLDING_AND_CAPABILITY_QUESTIONS_IF_NEEDED: - "resetMoldingAndCapabilityQuestionAnswersIfNeeded", - SAVE_MOLDING_QUESTION_ANSWERS: "saveMoldingQuestionAnswers", - SAVE_CAPABILITY_QUESTION_ANSWERS: "saveCapabilityQuestionAnswers", + // SAVE COMPONENT STATE + SAVE_VEHICLE_YEAR: "saveVehicleYear", + SAVE_VEHICLE_MAKE: "saveVehicleMake", + SAVE_VEHICLE_MODEL: "saveVehicleModel", + SAVE_VEHICLE_STYLE: "saveVehicleStyle", + SAVE_VEHICLE_DAMAGE: "saveVehicleDamage", + SAVE_VIN_LOOKUP: "saveVinLookup", + SAVE_SERVICE_LOCATION: "saveServiceLocation", + SAVE_EMAIL: "saveEmail", + SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP: "saveRegistrationLicensePlateLookup", + SAVE_VIN: "saveVin", + SAVE_REGISTRATION_ADDRESS_LOOKUP: "saveRegistrationAddressLookup", + SAVE_GLASS_PARTS: "saveGlassParts", + SAVE_PART_QUESTION_ANSWERS: "savePartQuestionAnswers", + RESET_MOLDING_AND_CAPABILITY_QUESTIONS_IF_NEEDED: + "resetMoldingAndCapabilityQuestionAnswersIfNeeded", + SAVE_MOLDING_QUESTION_ANSWERS: "saveMoldingQuestionAnswers", + SAVE_CAPABILITY_QUESTION_ANSWERS: "saveCapabilityQuestionAnswers", + + // START GA click event actions + // UPDATE_CURRENTLY_SELECTED_VALUES: "updateCurrentlySelectedValues", + // UPDATE_FIRED_GA_CLICK_EVENT_VALUES: "updateFiredGaClickEventValues", + // UPDATE_LAST_FOCUSED_INPUT_GROUP: "updateLastFocusedInputGroup", + // UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT: + // "updateWasLastFocusedInputMultiselect", + // END GA click event actions }; const gaStoreActions = { - UPDATE_CURRENTLY_SELECTED_VALUES: "updateCurrentlySelectedValues", - UPDATE_FIRED_GA_CLICK_EVENT_VALUES: "updateFiredGaClickEventValues", - UPDATE_LAST_FOCUSED_INPUT_GROUP: "updateLastFocusedInputGroup", - UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT: - "updateWasLastFocusedInputMultiselect", + UPDATE_CURRENTLY_SELECTED_VALUES: "updateCurrentlySelectedValues", + UPDATE_FIRED_GA_CLICK_EVENT_VALUES: "updateFiredGaClickEventValues", + UPDATE_LAST_FOCUSED_INPUT_GROUP: "updateLastFocusedInputGroup", + UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT: + "updateWasLastFocusedInputMultiselect", }; export { storeActions, gaStoreActions }; diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index 0e72b5849..1f960abd1 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -1,71 +1,79 @@ const storeMutations = { - // VEHICLE MUTATIONS - UPDATE_YEAR: "updateYear", - UPDATE_MAKE: "updateMake", - UPDATE_MODEL: "updateModel", - UPDATE_STYLE: "updateStyle", - UPDATE_CAR_ID: "updateCarId", - UPDATE_VEHICLE_CATEGORY: "updateVehicleCategory", - UPDATE_VEHICLE_IMAGE_URL: "updateVehicleImageUrl", - UPDATE_VEHICLE_IMAGE_VIF_NUMBER: "updateVehicleImageVifNumber", - UPDATE_VEHICLE_IMAGE_COLOR: "updateVehicleImageColor", - UPDATE_VEHICLE_VIN: "updateVehicleVin", - UPDATE_VEHICLE: "updateVehicle", + // VEHICLE MUTATIONS + UPDATE_YEAR: "updateYear", + UPDATE_MAKE: "updateMake", + UPDATE_MODEL: "updateModel", + UPDATE_STYLE: "updateStyle", + UPDATE_CAR_ID: "updateCarId", + UPDATE_VEHICLE_CATEGORY: "updateVehicleCategory", + UPDATE_VEHICLE_IMAGE_URL: "updateVehicleImageUrl", + UPDATE_VEHICLE_IMAGE_VIF_NUMBER: "updateVehicleImageVifNumber", + UPDATE_VEHICLE_IMAGE_COLOR: "updateVehicleImageColor", + UPDATE_VEHICLE_VIN: "updateVehicleVin", + UPDATE_VEHICLE: "updateVehicle", - UPDATE_IS_REPAIR: "updateIsRepair", - UPDATE_NUMBER_OF_CHIPS: "updateNumberOfChips", - UPDATE_GLASS_TO_REPLACE: "updateGlassToReplace", - UPDATE_PART_QUESTION_ANSWERS: "updatePartQuestionAnswers", - UPDATE_MOLDING_QUESTION_ANSWERS: "updateMoldingQuestionAnswers", - UPDATE_CAPABILITY_QUESTION_ANSWERS: "updateCapabilityQuestionAnswers", - UPDATE_GLASS_PARTS: "updateGlassParts", - UPDATE_OTHER_PARTS: "updateOtherParts", + UPDATE_IS_REPAIR: "updateIsRepair", + UPDATE_NUMBER_OF_CHIPS: "updateNumberOfChips", + UPDATE_GLASS_TO_REPLACE: "updateGlassToReplace", + UPDATE_PART_QUESTION_ANSWERS: "updatePartQuestionAnswers", + UPDATE_MOLDING_QUESTION_ANSWERS: "updateMoldingQuestionAnswers", + UPDATE_CAPABILITY_QUESTION_ANSWERS: "updateCapabilityQuestionAnswers", + UPDATE_GLASS_PARTS: "updateGlassParts", + UPDATE_OTHER_PARTS: "updateOtherParts", - UPDATE_REGISTRATION_LICENSE_PLATE: "updateRegistrationLicensePlate", - UPDATE_REGISTRATION_ADDRESS: "updateRegistrationAddress", - UPDATE_REGISTRATION_CITY: "updateRegistrationCity", - UPDATE_REGISTRATION_STATE: "updateRegistrationState", - UPDATE_REGISTRATION_ZIP_CODE: "updateRegistrationZipCode", - UPDATE_REGISTRATION_FIRST_NAME: "updateRegistrationFirstName", - UPDATE_REGISTRATION_LAST_NAME: "updateRegistrationLastName", - UPDATE_REGISTRATION: "updateRegistration", + UPDATE_REGISTRATION_LICENSE_PLATE: "updateRegistrationLicensePlate", + UPDATE_REGISTRATION_ADDRESS: "updateRegistrationAddress", + UPDATE_REGISTRATION_CITY: "updateRegistrationCity", + UPDATE_REGISTRATION_STATE: "updateRegistrationState", + UPDATE_REGISTRATION_ZIP_CODE: "updateRegistrationZipCode", + UPDATE_REGISTRATION_FIRST_NAME: "updateRegistrationFirstName", + UPDATE_REGISTRATION_LAST_NAME: "updateRegistrationLastName", + UPDATE_REGISTRATION: "updateRegistration", - UPDATE_SERVICE_LOCATION_ZIP_CODE: "updateServiceLocationZipCode", - UPDATE_SERVICE_LOCATION_STATE: "updateServiceLocationState", - UPDATE_SERVICE_LOCATION: "updateServiceLocation", + UPDATE_SERVICE_LOCATION_ZIP_CODE: "updateServiceLocationZipCode", + UPDATE_SERVICE_LOCATION_STATE: "updateServiceLocationState", + UPDATE_SERVICE_LOCATION: "updateServiceLocation", - UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress", + UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress", - // ORDER MUTATIONS - UPDATE_REFERRAL_NUMBER: "updateReferralNumber", - UPDATE_REFERRAL_DATE: "updateReferralDate", - UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId", - UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber", - UPDATE_EON: "updateEON", - UPDATE_SAVED_SESSION_ID: "updateSavedSessionId", - UPDATE_CRM_CUSTOMER_ID: "updateCrmCustomerId", + // ORDER MUTATIONS + UPDATE_REFERRAL_NUMBER: "updateReferralNumber", + UPDATE_REFERRAL_DATE: "updateReferralDate", + UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId", + UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber", + UPDATE_EON: "updateEON", + UPDATE_SAVED_SESSION_ID: "updateSavedSessionId", + UPDATE_CRM_CUSTOMER_ID: "updateCrmCustomerId", - // EVENT BUS MUTATIONS - ADD_EVENT_TO_BUS: "addEventToBus", - REMOVE_EVENT_FROM_BUS: "removeEventFromBus", + // EVENT BUS MUTATIONS + ADD_EVENT_TO_BUS: "addEventToBus", + REMOVE_EVENT_FROM_BUS: "removeEventFromBus", - // DEPENDENCY MUTATIONS - RESET_VEHICLE_STATE: "resetVehicleState", - RESET_DAMAGE_STATE: "resetDamageState", - RESET_REGISTRATION_STATE: "resetRegistrationState", - RESET_GLASS_PARTS_STATE: "resetGlassPartsState", - RESET_STATE: "resetState", - RESET_SAVE_ORDER_PROMISE: "resetSaveOrderPromise", + // DEPENDENCY MUTATIONS + RESET_VEHICLE_STATE: "resetVehicleState", + RESET_DAMAGE_STATE: "resetDamageState", + RESET_REGISTRATION_STATE: "resetRegistrationState", + RESET_GLASS_PARTS_STATE: "resetGlassPartsState", + RESET_STATE: "resetState", + RESET_SAVE_ORDER_PROMISE: "resetSaveOrderPromise", - // OTHER MUTATIONS - UPDATE_PAGE_DATA: "updatePageData", - UPDATE_STATE_WITH_ORDER_INFORMATION: "updateStateWithOrderInformation", - UPDATE_SAVE_ORDER_PROMISE: "updateSaveOrderPromise", - UPDATE_LAST_PAGE_VISITED: "updateLastPageVisited", + // OTHER MUTATIONS + UPDATE_PAGE_DATA: "updatePageData", + UPDATE_STATE_WITH_ORDER_INFORMATION: "updateStateWithOrderInformation", + UPDATE_SAVE_ORDER_PROMISE: "updateSaveOrderPromise", + UPDATE_LAST_PAGE_VISITED: "updateLastPageVisited", - // EXPERIMENT MUTATIONS - UPDATE_EXPERIMENTS: "updateExperiments", - UPDATE_TRIGGERED_SITE_ENTRY: "updateTriggeredSiteEntry", + // EXPERIMENT MUTATIONS + UPDATE_EXPERIMENTS: "updateExperiments", + UPDATE_TRIGGERED_SITE_ENTRY: "updateTriggeredSiteEntry", + + // START GA click event mutations + // UPDATE_CURRENTLY_SELECTED_VALUES: "updateCurrentlySelectedValues", + // UPDATE_FIRED_GA_CLICK_EVENT_VALUES: "updateFiredGaClickEventValues", + // UPDATE_LAST_FOCUSED_INPUT_GROUP: "updateLastFocusedInputGroup", + // UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT: + // "updateWasLastFocusedInputMultiselect", + // END GA click event mutations }; const gaStoreMutations = { diff --git a/src/main.js b/src/main.js index 01aa5406d..37c623b0b 100644 --- a/src/main.js +++ b/src/main.js @@ -8,12 +8,14 @@ import baseMixin from "@/mixins/base-mixin.js"; import analyticsMixin from "@/mixins/analytics-mixin.js"; import experimentMixin from "@/mixins/experiment-mixin.js"; import "../node_modules/bootstrap/dist/js/bootstrap.js"; +import gaState from "./store/gaState"; // Vue App Setup const vueApp = createApp(App); vueApp.use(router); vueApp.use(store); +vueApp.use(gaState) vueApp.use(LoadScript); vueApp.use(Maska); vueApp.mixin(baseMixin); diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index 6eb18e462..556ca509e 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -29,6 +29,8 @@ export default { logCustomEvent(category, action, label, value) { const currentPageName = getPageNameByQueryString(); + console.log("PUSHING: ", label) + var payload = { userId: getDeviceIdValue(), sessionKey: getSessionKeyValue(), diff --git a/src/store/gaState.js b/src/store/gaState.js index 7d42e6866..ab8e2dff8 100644 --- a/src/store/gaState.js +++ b/src/store/gaState.js @@ -1,90 +1,72 @@ -import { createStore } from "vuex"; -import { endpoints } from "@/constants/endpoints.js"; import { gaStoreMutations } from "@/constants/store-mutations"; -import { getDateForSavedSessionTimeout } from "@/helpers/heritage-integration/session-helper"; -import createPersistedState from "vuex-persistedstate"; -import globalMethods from "@/global-methods"; -import { gaStoreActions } from "@/constants/store-actions"; -import { applicationConfig } from "@/constants/application-config"; -import { experimentTriggers } from "@/constants/experiments"; -import { damageLocationsSelected } from "@/constants/damage-locations-selected"; -import { fmgPageValues } from "@/router/router-constants/fmgPage-values"; // Export State const getDefaultState = () => { - return { - gaClickInformation: { - currentlySelectedValues: {}, - firedGaClickEventValues: {}, - lastFocusedInputGroup: "", - wasLastFocusedInputMultiselect: undefined, - }, - }; + return { + gaClickInformation: { + currentlySelectedValues: {}, + firedGaClickEventValues: {}, + lastFocusedInputGroup: "", + wasLastFocusedInputMultiselect: undefined, + }, + }; }; export const gaState = getDefaultState(); // Export Mutations export const gaMutations = { - updateCurrentlySelectedValues(state, groupName, value) { - state.gaClickInformation.currentlySelectedValues[groupName] = value; - }, - updateFiredGaClickEventValues(state, groupName, value) { - state.gaClickInformation.firedGaClickEventValues[groupName] = value; - }, - updateLastFocusedInputGroup(state, groupName) { - state.gaClickInformation.lastFocusedInputGroup = groupName; - }, - updateWasLastFocusedInputMultiselect( - state, - wasLastFocusedInputMultiselect - ) { - state.gaClickInformation.wasLastFocusedInputMultiselect = - wasLastFocusedInputMultiselect; - }, + updateCurrentlySelectedValues(state, { groupName, value }) { + state.gaClickInformation.currentlySelectedValues[groupName] = value; + }, + updateFiredGaClickEventValues(state, { groupName, value }) { + state.gaClickInformation.firedGaClickEventValues[groupName] = value; + }, + updateLastFocusedInputGroup(state, groupName) { + state.gaClickInformation.lastFocusedInputGroup = groupName; + }, + updateWasLastFocusedInputMultiselect(state, wasLastFocusedInputMultiselect) { + state.gaClickInformation.wasLastFocusedInputMultiselect = + wasLastFocusedInputMultiselect; + }, }; // Export Getters export const getters = { - gaClickInformation: (state) => state.gaClickInformation, + gaClickInformation: (state) => state.gaClickInformation, }; // Export Actions export const gaActions = { - updateCurrentlySelectedValues(context, groupName, value) { - context.commit( - gaStoreMutations.UPDATE_CURRENTLY_SELECTED_VALUES, - groupName, - value - ); - }, - updateFiredGaClickEventValues(context, groupName, value) { - context.commit( - gaStoreMutations.UPDATE_FIRED_GA_CLICK_EVENT_VALUES, - groupName, - value - ); - }, - updateLastFocusedInputGroup(context, groupName) { - context.commit( - gaStoreMutations.UPDATE_LAST_FOCUSED_INPUT_GROUP, - groupName - ); - }, - updateWasLastFocusedInputMultiselect( - context, - wasLastFocusedInputMultiselect - ) { - context.commit( - gaStoreMutations.UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT, - wasLastFocusedInputMultiselect - ); - }, + updateCurrentlySelectedValues(context, { groupName, value }) { + context.commit(gaStoreMutations.UPDATE_CURRENTLY_SELECTED_VALUES, { + groupName, + value, + }); + }, + updateFiredGaClickEventValues(context, { groupName, value }) { + context.commit(gaStoreMutations.UPDATE_FIRED_GA_CLICK_EVENT_VALUES, { + groupName, + value, + }); + }, + updateLastFocusedInputGroup(context, groupName) { + context.commit(gaStoreMutations.UPDATE_LAST_FOCUSED_INPUT_GROUP, groupName); + }, + updateWasLastFocusedInputMultiselect( + context, + wasLastFocusedInputMultiselect + ) { + context.commit( + gaStoreMutations.UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT, + wasLastFocusedInputMultiselect + ); + }, }; -export default createStore({ - gaState, - gaMutations, - getters, - gaActions, -}); +export default { + state: gaState, + mutations: gaMutations, + getters, + actions: gaActions, +}; diff --git a/src/store/index.js b/src/store/index.js index cacb03b83..34bba86c0 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,4 +1,4 @@ -import { createStore } from "vuex"; +import { createStore, Store } from "vuex"; import { endpoints } from "@/constants/endpoints.js"; import { storeMutations } from "@/constants/store-mutations"; import { getDateForSavedSessionTimeout } from "@/helpers/heritage-integration/session-helper"; @@ -9,6 +9,7 @@ import { applicationConfig } from "@/constants/application-config"; import { experimentTriggers } from "@/constants/experiments"; import { damageLocationsSelected } from "@/constants/damage-locations-selected"; import { fmgPageValues } from "@/router/router-constants/fmgPage-values"; +import gaState from "./gaState"; // Export State const getDefaultState = () => { @@ -50,22 +51,22 @@ const getDefaultState = () => { glassToReplace: null, partQuestionAnswers: null, moldingQuestionAnswers: null, - capabilityQuestionAnswers: null + capabilityQuestionAnswers: null, }, lineItems: { - glassParts: null + glassParts: null, }, payment: { isInsurance: null, insuranceCoverage: { - isVerified: null - } + isVerified: null, + }, }, referralNumber: null, referralDate: null, referralCorrelationId: null, accountNumber: 0, - eon: null + eon: null, }, applicationUser: { eventBus: [], @@ -76,14 +77,15 @@ const getDefaultState = () => { crmCustomerId: null, lastPageVisited: null, experiments: [], - triggeredSiteEntry: false + triggeredSiteEntry: false, }, - gaInformation: { - currentlySelectedValues: {}, - firedGaClickEventValues: {}, - lastFocusedInputGroup: "" - } - } + // gaClickInformation: { + // currentlySelectedValues: {}, + // firedGaClickEventValues: {}, + // lastFocusedInputGroup: "", + // wasLastFocusedInputMultiselect: undefined, + // }, + }; }; export const state = getDefaultState(); @@ -200,7 +202,6 @@ export const mutations = { state.order.customer.emailAddress = customerEmailAddress; }, updateVehicle(state, vehicleInfo) { - state.order.vehicle.year = vehicleInfo.year; state.order.vehicle.make = vehicleInfo.make; state.order.vehicle.model = vehicleInfo.model; @@ -214,7 +215,8 @@ export const mutations = { state.order.vehicle.imageColor = vehicleInfo.imageVifColor; }, updateRegistration(state, registrationInfo) { - state.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate; + state.order.vehicle.registration.licensePlate = + registrationInfo?.licensePlate; state.order.vehicle.registration.address = registrationInfo?.address; state.order.vehicle.registration.city = registrationInfo?.city; state.order.vehicle.registration.state = registrationInfo?.state; @@ -240,7 +242,7 @@ export const mutations = { state.applicationUser.crmCustomerId = crmCustomerId; }, updateLastPageVisited(state, lastPageVisited) { - state.applicationUser.lastPageVisited = lastPageVisited + state.applicationUser.lastPageVisited = lastPageVisited; }, // EVENT BUS MUTATIONS addEventToBus(state, event) { @@ -249,8 +251,7 @@ export const mutations = { removeEventFromBus(state, eventData) { const matchedEvent = state.applicationUser.eventBus.find( ({ category, subCategory }) => - category === eventData.category && - subCategory === eventData.subCategory + category === eventData.category && subCategory === eventData.subCategory ); const itemIndex = state.applicationUser.eventBus.indexOf(matchedEvent); @@ -336,7 +337,7 @@ export const mutations = { state: orderInformation.vehicle.registration.state, zipCode: orderInformation.vehicle.registration.zipCode, licensePlate: orderInformation.vehicle.registration.licensePlateNumber, - } + }, }); state.order.damage.glassToReplace = orderInformation.damage.glassToReplace; @@ -345,13 +346,18 @@ export const mutations = { state.order.lineItems.glassParts = orderInformation.parts; state.order.accountNumber = orderInformation.accountNumber; - state.order.serviceLocation.address = orderInformation.serviceLocation.streetAddress, - state.order.serviceLocation.city = orderInformation.serviceLocation.city, - state.order.serviceLocation.state = orderInformation.serviceLocation.state, - state.order.serviceLocation.zipCode = orderInformation.serviceLocation.zipCode; + (state.order.serviceLocation.address = + orderInformation.serviceLocation.streetAddress), + (state.order.serviceLocation.city = + orderInformation.serviceLocation.city), + (state.order.serviceLocation.state = + orderInformation.serviceLocation.state), + (state.order.serviceLocation.zipCode = + orderInformation.serviceLocation.zipCode); state.order.payment.isInsurance = orderInformation.IsInsuranceOrder; - state.order.payment.insuranceCoverage.isVerified = orderInformation?.insuranceInfo.coverageVerified; + state.order.payment.insuranceCoverage.isVerified = + orderInformation?.insuranceInfo.coverageVerified; state.order.customer.emailAddress = orderInformation.customer.emailAddress; state.applicationUser.experiments = orderInformation.experiments; @@ -361,8 +367,23 @@ export const mutations = { }, updateTriggeredSiteEntry(state, wasSiteEntryTriggered) { state.applicationUser.triggeredSiteEntry = wasSiteEntryTriggered; - } -} + }, + // START GA click event mutations + // updateCurrentlySelectedValues(state, groupName, value) { + // state.gaClickInformation.currentlySelectedValues[groupName] = value; + // }, + // updateFiredGaClickEventValues(state, groupName, value) { + // state.gaClickInformation.firedGaClickEventValues[groupName] = value; + // }, + // updateLastFocusedInputGroup(state, groupName) { + // state.gaClickInformation.lastFocusedInputGroup = groupName; + // }, + // updateWasLastFocusedInputMultiselect(state, wasLastFocusedInputMultiselect) { + // state.gaClickInformation.wasLastFocusedInputMultiselect = + // wasLastFocusedInputMultiselect; + // }, + // END GA click event mutations +}; // Export Getters export const getters = { @@ -378,7 +399,9 @@ export const getters = { eventBus: (state) => state.applicationUser.eventBus, damage: (state) => state.order.damage, lineItems: (state) => state.order.lineItems, - pageData: (state) => (page) => { return state.applicationUser.pageData[page]; }, + pageData: (state) => (page) => { + return state.applicationUser.pageData[page]; + }, applicationUser: (state) => state.applicationUser, order: (state) => state.order, payment: (state) => state.order.payment, @@ -395,29 +418,63 @@ export const getters = { funnelServiceState: state.order.serviceLocation.state, funnelServiceZipCode: state.order.serviceLocation.zipCode, funnelParentAccountNumber: state.order.accountNumber, - funnelIsCoverageVerified: state.order.payment.insuranceCoverage.isVerified, + funnelIsCoverageVerified: + state.order.payment.insuranceCoverage.isVerified, funnelHasRecalibrationPart: getHasRecalibrationPart(state), funnelSelectedMultiGlass: state.order.damage.glassToReplace?.length > 1, - funnelSelectedWindshieldGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.WINDSHIELD), - funnelSelectedBackGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.REAR), - funnelSelectedDriverSideGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.DRIVER), - funnelSelectedPassengerSideGlass: getAllValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.PASSENGER), + funnelSelectedWindshieldGlass: getAllValuesOfPropertyInArrayOfObjects( + state.order.damage.glassToReplace, + "glassLocation" + ).includes(damageLocationsSelected.WINDSHIELD), + funnelSelectedBackGlass: getAllValuesOfPropertyInArrayOfObjects( + state.order.damage.glassToReplace, + "glassLocation" + ).includes(damageLocationsSelected.REAR), + funnelSelectedDriverSideGlass: getAllValuesOfPropertyInArrayOfObjects( + state.order.damage.glassToReplace, + "glassLocation" + ).includes(damageLocationsSelected.DRIVER), + funnelSelectedPassengerSideGlass: getAllValuesOfPropertyInArrayOfObjects( + state.order.damage.glassToReplace, + "glassLocation" + ).includes(damageLocationsSelected.PASSENGER), - funnelOrderPartNumbers: [...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "partNumber"), ...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, "partNumber")], + funnelOrderPartNumbers: [ + ...getAllValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + "partNumber" + ), + ...getAllValuesOfPropertyInArrayOfObjects( + state.order.lineItems.otherParts, + "partNumber" + ), + ], - funnelOrderPartTypes: [...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType"), ...getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, "recalibrationType")], - } + funnelOrderPartTypes: [ + ...getAllValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + "recalibrationType" + ), + ...getAllValuesOfPropertyInArrayOfObjects( + state.order.lineItems.otherParts, + "recalibrationType" + ), + ], + }; }, - experimentSettings: (state) => state.applicationUser.experiments.map(x => x.settings).reduce((r, c) => Object.assign(r, c), {}) ?? {} -} + experimentSettings: (state) => + state.applicationUser.experiments + .map((x) => x.settings) + .reduce((r, c) => Object.assign(r, c), {}) ?? {}, + // gaClickInformation: (state) => state.gaClickInformation, +}; function getAllValuesOfPropertyInArrayOfObjects(array, propertyName) { - return (array ?? []).map(x => x[propertyName]).filter(x => x); + return (array ?? []).map((x) => x[propertyName]).filter((x) => x); } // Export Actions export const actions = { - // Vehicle API Actions getVehicleYears(context) { return globalMethods.callHttpClient({ @@ -448,11 +505,14 @@ export const actions = { endpoint: endpoints.LookupVinByPlate.url, payload: { licensePlate: licensePlate, - licenseState: licenseState + licenseState: licenseState, }, }); }, - lookupVinByAddress(context, { licenseLastName, licenseStreetAddress, licenseZip, licenseState }) { + lookupVinByAddress( + context, + { licenseLastName, licenseStreetAddress, licenseZip, licenseState } + ) { return globalMethods.callHttpClient({ method: endpoints.LookupVinByAddress.method, endpoint: endpoints.LookupVinByAddress.url, @@ -460,7 +520,7 @@ export const actions = { licenseLastName: licenseLastName, licenseStreetAddress: licenseStreetAddress, licenseZip: licenseZip, - licenseState: licenseState + licenseState: licenseState, }, }); }, @@ -494,10 +554,22 @@ export const actions = { }) .then((response) => { context.commit(storeMutations.UPDATE_CAR_ID, response.data.carId); - context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, response.data.category); - context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, response.data.imageUrl); - context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, response.data.imageVifNumber); - context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, response.data.imageVifColor); + context.commit( + storeMutations.UPDATE_VEHICLE_CATEGORY, + response.data.category + ); + context.commit( + storeMutations.UPDATE_VEHICLE_IMAGE_URL, + response.data.imageUrl + ); + context.commit( + storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, + response.data.imageVifNumber + ); + context.commit( + storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, + response.data.imageVifColor + ); return response; }); }, @@ -511,8 +583,8 @@ export const actions = { validateZip(context, { zip }) { return globalMethods.callHttpClient({ methods: endpoints.ValidateZip.method, - endpoint: `${endpoints.ValidateZip.url}/${zip}` - }) + endpoint: `${endpoints.ValidateZip.url}/${zip}`, + }); }, // Dependency Actions @@ -527,7 +599,7 @@ export const actions = { }, resetRegistrationAndDependencies(context) { context.commit(storeMutations.RESET_REGISTRATION_STATE); - context.commit(storeMutations.RESET_GLASS_PARTS_STATE) + context.commit(storeMutations.RESET_GLASS_PARTS_STATE); }, resetPartsAndDependencies(context) { context.commit(storeMutations.RESET_GLASS_PARTS_STATE); @@ -583,22 +655,48 @@ export const actions = { assignmentId: experiment.assignmentId, sessionKey: sessionKey, pageName: pageName, - } - } + }, + }, }); }, // Misc Actions - updateStoreWithSaveOrderResponse(context, { referralNumber, referralDate, referralCorrelationId, eon, accountNumber, savedSessionId, crmCustomerId }) { + updateStoreWithSaveOrderResponse( + context, + { + referralNumber, + referralDate, + referralCorrelationId, + eon, + accountNumber, + savedSessionId, + crmCustomerId, + } + ) { context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber); context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate); - context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId); + context.commit( + storeMutations.UPDATE_REFERRAL_CORRELATION_ID, + referralCorrelationId + ); context.commit(storeMutations.UPDATE_EON, eon); context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, accountNumber); context.commit(storeMutations.UPDATE_SAVED_SESSION_ID, savedSessionId); context.commit(storeMutations.UPDATE_CRM_CUSTOMER_ID, crmCustomerId); }, - logPageView(context, { userId, sessionKey, pageName, sessionId, action, event, shouldUseSessionId, experimentsForUser }) { + logPageView( + context, + { + userId, + sessionKey, + pageName, + sessionId, + action, + event, + shouldUseSessionId, + experimentsForUser, + } + ) { var payload = { userId: userId, sessionKey: sessionKey, @@ -608,17 +706,31 @@ export const actions = { action: action, event: event, shouldUseSessionId: shouldUseSessionId, - experimentsForUser: experimentsForUser + experimentsForUser: experimentsForUser, }; return globalMethods.callHttpClient({ method: endpoints.LogPageView.method, endpoint: endpoints.LogPageView.url, payload: payload, - logApiCall: false + logApiCall: false, }); }, - logCustomEvent(context, { userId, sessionKey, pageName, sessionId, category, action, label, value, shouldUseSessionId, experimentsForUser }) { + logCustomEvent( + context, + { + userId, + sessionKey, + pageName, + sessionId, + category, + action, + label, + value, + shouldUseSessionId, + experimentsForUser, + } + ) { var payload = { userId: userId, sessionKey: sessionKey, @@ -630,14 +742,14 @@ export const actions = { label: label, value: value, shouldUseSessionId: shouldUseSessionId, - experimentsForUser: experimentsForUser + experimentsForUser: experimentsForUser, }; return globalMethods.callHttpClient({ method: endpoints.LogCustomEvent.method, endpoint: endpoints.LogCustomEvent.url, payload: payload, - logApiCall: false + logApiCall: false, }); }, initializeSession(context, { userId, sessionId, userAgent, referrer }) { @@ -649,22 +761,28 @@ export const actions = { userAgent: userAgent, operatorId: "WEB", userName: "SafeliteConceptFunnel", - referrer: referrer + referrer: referrer, }; return globalMethods.callHttpClient({ method: endpoints.InitializeSession.method, endpoint: endpoints.InitializeSession.url, payload: payload, - logApiCall: false + logApiCall: false, }); }, // Misc Actions - setReferralInformation(context, { referralNumber, referralDate, referralCorrelationId, eon }) { + setReferralInformation( + context, + { referralNumber, referralDate, referralCorrelationId, eon } + ) { context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber); context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate); - context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId); + context.commit( + storeMutations.UPDATE_REFERRAL_CORRELATION_ID, + referralCorrelationId + ); context.commit(storeMutations.UPDATE_EON, eon); }, @@ -672,11 +790,14 @@ export const actions = { return globalMethods.callHttpClient({ method: endpoints.GetExperimentsByUser.method, endpoint: `${endpoints.GetExperimentsByUser.url}/${userId}`, - payload: {} + payload: {}, }); }, - async runExperimentsForTrigger(context, { userId, triggerEvent, triggerValue }) { + async runExperimentsForTrigger( + context, + { userId, triggerEvent, triggerValue } + ) { if (triggerEvent == experimentTriggers.SITE_ENTRY) { context.commit(storeMutations.UPDATE_TRIGGERED_SITE_ENTRY, true); } @@ -686,7 +807,7 @@ export const actions = { userId: userId, triggerEvent: triggerEvent, triggerValue: triggerValue, - experimentOrder: context.getters.experimentOrder + experimentOrder: context.getters.experimentOrder, }; const response = await globalMethods.callHttpClient({ @@ -695,7 +816,10 @@ export const actions = { payload: payload, }); - context.commit(storeMutations.UPDATE_EXPERIMENTS, response.data.experiments); + context.commit( + storeMutations.UPDATE_EXPERIMENTS, + response.data.experiments + ); }, getEvoxImage(context, { relativeUrl }) { @@ -724,7 +848,7 @@ export const actions = { carId: carId, glass: glassArray ?? [], zip: zipCode, - vin: vin + vin: vin, }, }); }, @@ -749,7 +873,7 @@ export const actions = { glass: glassArray, answerResults: resultsArray, zip: zipCode, - vin: vin + vin: vin, }, }); }, @@ -758,24 +882,31 @@ export const actions = { return globalMethods.callHttpClient({ method: endpoints.GetCapabilityQuestions.method, endpoint: `${endpoints.GetCapabilityQuestions.url}/${carId}/${partNumber}`, - }) + }); }, getPartFromCapabilityQuestionAnswer(context, glassLocation) { - const pageData = context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS); + const pageData = context.getters.pageData( + fmgPageValues.CAPABILITY_QUESTIONS + ); - const part = pageData.partsOrQuestions.find(x => x.glassLocation === glassLocation).parts[0]; - const capabilityQuestionAnswers = context.getters.damage.capabilityQuestionAnswers; - const capabilityQuestionAnswersForPart = capabilityQuestionAnswers.find(x => x.glassLocation === glassLocation); + const part = pageData.partsOrQuestions.find( + (x) => x.glassLocation === glassLocation + ).parts[0]; + const capabilityQuestionAnswers = + context.getters.damage.capabilityQuestionAnswers; + const capabilityQuestionAnswersForPart = capabilityQuestionAnswers.find( + (x) => x.glassLocation === glassLocation + ); return globalMethods.callHttpClient({ method: endpoints.GetPartFromCapabilityAnswer.method, endpoint: endpoints.GetPartFromCapabilityAnswer.url, payload: { part, - capabilityAnswerResults: capabilityQuestionAnswersForPart - } - }) + capabilityAnswerResults: capabilityQuestionAnswersForPart, + }, + }); }, // Order API Actions @@ -810,21 +941,21 @@ export const actions = { damage: { numberOfChips: damage.numberOfChips, glassToReplace: damage.glassToReplace, - isRepair: damage.isRepair + isRepair: damage.isRepair, }, customer: { emailAddress: order.customer.emailAddress, }, lineItems: { - glassParts: lineItems.glassParts + glassParts: lineItems.glassParts, }, serviceLocation: { streetAddress: order.serviceLocation.address, city: order.serviceLocation.city, state: order.serviceLocation.state, - zipCode: order.serviceLocation.zipCode + zipCode: order.serviceLocation.zipCode, }, - referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place + referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place referralDate: order.referralDate, accountNumber: order.accountNumber?.toString(), existingPromoCode: null, @@ -835,32 +966,42 @@ export const actions = { }, }); }, - loadOrder(context, { referralNumber, referralDate, referralCorrelationId, accountNumber }) { - return globalMethods.callHttpClient({ - method: endpoints.LoadOrder.method, - endpoint: endpoints.LoadOrder.url, - payload: { - referralNumber: referralNumber?.toString(), - referralDate: referralDate, - referralCorrelationId: referralCorrelationId, - accountNumber: accountNumber?.toString() - }, - }).then((response) => { - // clear the state if the existing EON does not equal what is returned from loadOrder - if (context.state.order.eon && context.state.order.eon != response.data.eon) { - context.commit(storeMutations.RESET_STATE); - } - context.commit(storeMutations.UPDATE_STATE_WITH_ORDER_INFORMATION, response.data); - return response; - }); + loadOrder( + context, + { referralNumber, referralDate, referralCorrelationId, accountNumber } + ) { + return globalMethods + .callHttpClient({ + method: endpoints.LoadOrder.method, + endpoint: endpoints.LoadOrder.url, + payload: { + referralNumber: referralNumber?.toString(), + referralDate: referralDate, + referralCorrelationId: referralCorrelationId, + accountNumber: accountNumber?.toString(), + }, + }) + .then((response) => { + // clear the state if the existing EON does not equal what is returned from loadOrder + if ( + context.state.order.eon && + context.state.order.eon != response.data.eon + ) { + context.commit(storeMutations.RESET_STATE); + } + context.commit( + storeMutations.UPDATE_STATE_WITH_ORDER_INFORMATION, + response.data + ); + return response; + }); }, // Business domain actions // Vehicle saveVehicleYear(context, year) { - - //Reset dependent state when changing + //Reset dependent state when changing if (context.state.order.vehicle.year !== year) { context.commit(storeMutations.UPDATE_MAKE, null); context.commit(storeMutations.UPDATE_MODEL, null); @@ -881,7 +1022,6 @@ export const actions = { } }, saveVehicleMake(context, make) { - //Reset dependent state when changing if (context.state.order.vehicle.make !== make) { context.commit(storeMutations.UPDATE_MODEL, null); @@ -902,8 +1042,7 @@ export const actions = { } }, saveVehicleModel(context, model) { - - //Reset dependent state when changing + //Reset dependent state when changing if (context.state.order.vehicle.model !== model) { context.commit(storeMutations.UPDATE_STYLE, null); context.commit(storeMutations.UPDATE_CAR_ID, null); @@ -922,7 +1061,7 @@ export const actions = { } }, saveVehicleStyle(context, style) { - //Reset dependent state when changing + //Reset dependent state when changing if (context.state.order.vehicle.style !== style) { context.commit(storeMutations.UPDATE_CAR_ID, null); context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null); @@ -939,20 +1078,35 @@ export const actions = { context.commit(storeMutations.UPDATE_STYLE, style); } }, - saveVehicleDamage(context, { isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }) { - + saveVehicleDamage( + context, + { isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount } + ) { const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort(); - const isGlassToReplaceTheSame = (context.state.order.damage.glassToReplace?.length === selectedGlassToReplace.length) - && context.state.order.damage.glassToReplace + const isGlassToReplaceTheSame = + context.state.order.damage.glassToReplace?.length === + selectedGlassToReplace.length && + context.state.order.damage.glassToReplace .slice() .sort() - .every((obj, index) => obj.glassLocation === selectedGlassPassedInSorted[index].glassLocation && obj.glassName === selectedGlassPassedInSorted[index].glassName); - const isWindshieldRepairTheSame = isWindshieldRepair === context.state.order.damage.isRepair; + .every( + (obj, index) => + obj.glassLocation === + selectedGlassPassedInSorted[index].glassLocation && + obj.glassName === selectedGlassPassedInSorted[index].glassName + ); + const isWindshieldRepairTheSame = + isWindshieldRepair === context.state.order.damage.isRepair; const isChipCountTheSame = Array.isArray(selectedWindshieldChipCount) //TODO: fix the underlying components so this is never an array - ? selectedWindshieldChipCount[0] === context.state.order.damage.numberOfChips - : selectedWindshieldChipCount === context.state.order.damage.numberOfChips; + ? selectedWindshieldChipCount[0] === + context.state.order.damage.numberOfChips + : selectedWindshieldChipCount === + context.state.order.damage.numberOfChips; - const isDamageChanging = !isGlassToReplaceTheSame || !isWindshieldRepairTheSame || (isWindshieldRepair && !isChipCountTheSame); + const isDamageChanging = + !isGlassToReplaceTheSame || + !isWindshieldRepairTheSame || + (isWindshieldRepair && !isChipCountTheSame); if (isDamageChanging) { //Reset dependent state when changing @@ -960,14 +1114,23 @@ export const actions = { // Save new values context.commit(storeMutations.UPDATE_IS_REPAIR, isWindshieldRepair); - context.commit(storeMutations.UPDATE_NUMBER_OF_CHIPS, isWindshieldRepair ? parseInt(selectedWindshieldChipCount) : null); - context.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, selectedGlassToReplace); + context.commit( + storeMutations.UPDATE_NUMBER_OF_CHIPS, + isWindshieldRepair ? parseInt(selectedWindshieldChipCount) : null + ); + context.commit( + storeMutations.UPDATE_GLASS_TO_REPLACE, + selectedGlassToReplace + ); } }, // Vin lookup - saveVinLookup(context, { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) { - //Reset dependent state when changing + saveVinLookup( + context, + { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo } + ) { + //Reset dependent state when changing if (vehicleInfo.vin !== context.state.order.vehicle.vin) { context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES); context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES); @@ -981,10 +1144,15 @@ export const actions = { context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo); } }, - saveRegistrationLicensePlateLookup(context, { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) { - //Reset dependent state when changing - if (registrationInfo?.licensePlate !== context.state.order.vehicle.registration?.licensePlate) { - + saveRegistrationLicensePlateLookup( + context, + { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo } + ) { + //Reset dependent state when changing + if ( + registrationInfo?.licensePlate !== + context.state.order.vehicle.registration?.licensePlate + ) { context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES); if (!isSelectedGlassAvailableForVehicle) { @@ -997,10 +1165,25 @@ export const actions = { context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo); } }, - saveRegistrationAddressLookup(context, { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) { - //Reset dependent state when changing - if (registrationInfo?.address !== context.state.order.vehicle.registration?.address || registrationInfo?.city !== context.state.order.vehicle.registration?.city || registrationInfo?.state !== context.state.order.vehicle.registration?.state || registrationInfo?.zipCode !== context.state.order.vehicle.registration?.zipCode || registrationInfo?.firstName !== context.state.order.vehicle.registration?.firstName || registrationInfo?.lastName !== context.state.order.vehicle.registration?.lastName) { - + saveRegistrationAddressLookup( + context, + { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo } + ) { + //Reset dependent state when changing + if ( + registrationInfo?.address !== + context.state.order.vehicle.registration?.address || + registrationInfo?.city !== + context.state.order.vehicle.registration?.city || + registrationInfo?.state !== + context.state.order.vehicle.registration?.state || + registrationInfo?.zipCode !== + context.state.order.vehicle.registration?.zipCode || + registrationInfo?.firstName !== + context.state.order.vehicle.registration?.firstName || + registrationInfo?.lastName !== + context.state.order.vehicle.registration?.lastName + ) { context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES); if (!isSelectedGlassAvailableForVehicle) { @@ -1015,72 +1198,141 @@ export const actions = { }, savePartQuestionAnswers(context, partQuestionAnswersArray) { // if part question answers have changed, reset subsequent question answers - const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(context.getters.damage.partQuestionAnswers, "result"); - const sortedPartQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(partQuestionAnswersArray, "result") - const havePartQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedPartQuestionAnswersArray.length || - !sortedPreviousResultsArray?.every((x, i) => x.result === sortedPartQuestionAnswersArray[i].result); + const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue( + context.getters.damage.partQuestionAnswers, + "result" + ); + const sortedPartQuestionAnswersArray = sortArrayOfObjectsByPropertyValue( + partQuestionAnswersArray, + "result" + ); + const havePartQuestionAnswersChanged = + sortedPreviousResultsArray?.length !== + sortedPartQuestionAnswersArray.length || + !sortedPreviousResultsArray?.every( + (x, i) => x.result === sortedPartQuestionAnswersArray[i].result + ); if (havePartQuestionAnswersChanged) { context.commit(storeMutations.UPDATE_GLASS_PARTS, null); context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, null); context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null); - context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.VEHICLE_PARTS, data: null }); - context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.MOLDING_QUESTIONS, data: null }); - context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.CAPABILITY_QUESTIONS, data: null }); + context.commit(storeMutations.UPDATE_PAGE_DATA, { + page: fmgPageValues.VEHICLE_PARTS, + data: null, + }); + context.commit(storeMutations.UPDATE_PAGE_DATA, { + page: fmgPageValues.MOLDING_QUESTIONS, + data: null, + }); + context.commit(storeMutations.UPDATE_PAGE_DATA, { + page: fmgPageValues.CAPABILITY_QUESTIONS, + data: null, + }); } //Save new values - context.commit(storeMutations.UPDATE_PART_QUESTION_ANSWERS, partQuestionAnswersArray); + context.commit( + storeMutations.UPDATE_PART_QUESTION_ANSWERS, + partQuestionAnswersArray + ); }, resetMoldingAndCapabilityQuestionAnswersIfNeeded(context, matchedParts) { - const partsOrQuestionsDataToCompareWith = context.getters.pageData(fmgPageValues.MOLDING_QUESTIONS)?.partsOrQuestions ?? context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS)?.partsOrQuestions ?? []; + const partsOrQuestionsDataToCompareWith = + context.getters.pageData(fmgPageValues.MOLDING_QUESTIONS) + ?.partsOrQuestions ?? + context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS) + ?.partsOrQuestions ?? + []; function getAllPartNumbers(partsOrQuestions) { return partsOrQuestions[0]?.parts - ? [...partsOrQuestions].map(glass => glass.parts).flat().map(part => part.partNumber).filter(partNumber => !partNumber.toUpperCase().includes("FEE")).sort().join(",") - : [] + ? [...partsOrQuestions] + .map((glass) => glass.parts) + .flat() + .map((part) => part.partNumber) + .filter((partNumber) => !partNumber.toUpperCase().includes("FEE")) + .sort() + .join(",") + : []; } - const previouslySelectedPartNumbers = getAllPartNumbers(partsOrQuestionsDataToCompareWith); + const previouslySelectedPartNumbers = getAllPartNumbers( + partsOrQuestionsDataToCompareWith + ); const currentlySelectedPartNumbers = getAllPartNumbers(matchedParts); - const haveSelectedVehiclePartsChanged = previouslySelectedPartNumbers !== currentlySelectedPartNumbers; + const haveSelectedVehiclePartsChanged = + previouslySelectedPartNumbers !== currentlySelectedPartNumbers; if (haveSelectedVehiclePartsChanged) { context.commit(storeMutations.UPDATE_GLASS_PARTS, null); context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, null); context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null); - context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.MOLDING_QUESTIONS, data: null }); - context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.CAPABILITY_QUESTIONS, data: null }); + context.commit(storeMutations.UPDATE_PAGE_DATA, { + page: fmgPageValues.MOLDING_QUESTIONS, + data: null, + }); + context.commit(storeMutations.UPDATE_PAGE_DATA, { + page: fmgPageValues.CAPABILITY_QUESTIONS, + data: null, + }); } }, saveMoldingQuestionAnswers(context, moldingQuestionAnswers) { - const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(context.getters.damage.moldingQuestionAnswers, "partNum"); - const sortedMoldingQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(moldingQuestionAnswers, "partNum"); - const haveMoldingQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedMoldingQuestionAnswersArray.length || - !sortedPreviousResultsArray?.every((x, i) => x.partNum === sortedMoldingQuestionAnswersArray[i].partNum); + const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue( + context.getters.damage.moldingQuestionAnswers, + "partNum" + ); + const sortedMoldingQuestionAnswersArray = sortArrayOfObjectsByPropertyValue( + moldingQuestionAnswers, + "partNum" + ); + const haveMoldingQuestionAnswersChanged = + sortedPreviousResultsArray?.length !== + sortedMoldingQuestionAnswersArray.length || + !sortedPreviousResultsArray?.every( + (x, i) => x.partNum === sortedMoldingQuestionAnswersArray[i].partNum + ); if (haveMoldingQuestionAnswersChanged) { context.commit(storeMutations.UPDATE_GLASS_PARTS, null); context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null); - context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.CAPABILITY_QUESTIONS, data: null }); + context.commit(storeMutations.UPDATE_PAGE_DATA, { + page: fmgPageValues.CAPABILITY_QUESTIONS, + data: null, + }); } //Save new values - context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, moldingQuestionAnswers); + context.commit( + storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, + moldingQuestionAnswers + ); }, saveCapabilityQuestionAnswers(context, capabilityQuestionAnswers) { - const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(context.getters.damage.capabilityQuestionAnswers, "result"); - const sortedCapabilityQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(capabilityQuestionAnswers, "result"); - const haveCapabilityQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedCapabilityQuestionAnswersArray.length || - !sortedPreviousResultsArray?.every((x, i) => x.result === sortedCapabilityQuestionAnswersArray[i].result); + const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue( + context.getters.damage.capabilityQuestionAnswers, + "result" + ); + const sortedCapabilityQuestionAnswersArray = + sortArrayOfObjectsByPropertyValue(capabilityQuestionAnswers, "result"); + const haveCapabilityQuestionAnswersChanged = + sortedPreviousResultsArray?.length !== + sortedCapabilityQuestionAnswersArray.length || + !sortedPreviousResultsArray?.every( + (x, i) => x.result === sortedCapabilityQuestionAnswersArray[i].result + ); if (haveCapabilityQuestionAnswersChanged) { context.commit(storeMutations.UPDATE_GLASS_PARTS, null); } //Save new values - context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, capabilityQuestionAnswers); + context.commit( + storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, + capabilityQuestionAnswers + ); }, // Misc order actions saveServiceLocation(context, serviceLocationInfo) { @@ -1092,7 +1344,6 @@ export const actions = { saveVin(context, { isSelectedGlassAvailableForVehicle, vehicleInfo }) { //Reset dependent state when changing if (vehicleInfo.vin !== context.state.order.vehicle.vin) { - if (!isSelectedGlassAvailableForVehicle) { context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES); @@ -1107,11 +1358,50 @@ export const actions = { }, clearVin(context) { context.commit(storeMutations.UPDATE_VEHICLE_VIN, null); - } -} + }, + + // START GA click event actions + // updateCurrentlySelectedValues(context, { groupName, value }) { + // context.commit( + // storeMutations.UPDATE_CURRENTLY_SELECTED_VALUES, + // groupName, + // value + // ); + // }, + // updateFiredGaClickEventValues(context, { groupName, value }) { + // context.commit( + // storeMutations.UPDATE_FIRED_GA_CLICK_EVENT_VALUES, + // groupName, + // value + // ); + // }, + // updateLastFocusedInputGroup(context, groupName) { + // context.commit(storeMutations.UPDATE_LAST_FOCUSED_INPUT_GROUP, groupName); + // }, + // updateWasLastFocusedInputMultiselect( + // context, + // wasLastFocusedInputMultiselect + // ) { + // context.commit( + // storeMutations.UPDATE_WAS_LAST_FOCUSED_INPUT_MULTISELECT, + // wasLastFocusedInputMultiselect + // ); + // }, + // END GA click event actions +}; + +// const store = new Store({ +// state, +// mutations, +// getters, +// actions, +// }); export default createStore({ plugins: [createPersistedState()], + modules: { + gaState, + }, // IMPORTANT: Be VERY careful when modifying these fields for at least a few reasons: // * The CMS can reference the fields by name @@ -1126,30 +1416,42 @@ export default createStore({ // Private Functions function getHasRecalibrationPart(state) { - var hasRequiresRecalibration = getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "requiresRecalibration")?.length > 0; - var hasRecalibrationType = getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType")?.length > 0; + var hasRequiresRecalibration = + getAllValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + "requiresRecalibration" + )?.length > 0; + var hasRecalibrationType = + getAllValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + "recalibrationType" + )?.length > 0; if (hasRequiresRecalibration) { - if (hasRecalibrationType) { // Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType' - return getAllValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType")[0].toLowerCase() != "unknown"; - } else { // Has 'requiresRecalibration' but no 'recalibrationType' at all + if (hasRecalibrationType) { + // Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType' + return ( + getAllValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + "recalibrationType" + )[0].toLowerCase() != "unknown" + ); + } else { + // Has 'requiresRecalibration' but no 'recalibrationType' at all return true; } - } else { // Does not have 'requiresRecalibration' + } else { + // Does not have 'requiresRecalibration' return false; } - } function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) { if (!arrayOfObjects) return null; return arrayOfObjects.sort((a, b) => { - if (a[propertyName] < b[propertyName]) - return -1; - else if (a[propertyName] > b[propertyName]) - return 1; - else - return 0; - }) -} \ No newline at end of file + if (a[propertyName] < b[propertyName]) return -1; + else if (a[propertyName] > b[propertyName]) return 1; + else return 0; + }); +} From 0e628a485041c5f13d4ddcc2e2849ed5e6e8313b Mon Sep 17 00:00:00 2001 From: Katie Date: Thu, 29 Sep 2022 15:25:01 -0400 Subject: [PATCH 03/20] CSR-762 Make sure gaState isn't persisted --- .../base-input-button/base-input-button.vue | 16 +++------------- src/store/index.js | 7 ++++++- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index d3574fef2..225363401 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -90,7 +90,7 @@ export default { this.groupName, false ); - // window.lastFocusedInputGroup = this.groupName; + this.pushClickEventToGA(); break; } @@ -126,17 +126,14 @@ export default { this.valueToEmit = this.value; } - // window.currentlySelectedValues = - // window.currentlySelectedValues ?? {}; this.dispatchStoreAction( gaStoreActions.UPDATE_CURRENTLY_SELECTED_VALUES, { groupName: this.groupName, value: this.value, }, - // false ); - // window.currentlySelectedValues[this.groupName] = this.value; + this.handleChange(this.valueToEmit); }, handleClick(e) { @@ -144,8 +141,6 @@ export default { this.$emit("buttonClicked", this.valueToEmit); }, pushClickEventToGA(value) { - // window.firedGaClickEventValues = - // window.firedGaClickEventValues ?? {}; const lastFocusedInputGroup = store.getters.gaClickInformation.lastFocusedInputGroup; this.dispatchStoreAction( @@ -154,10 +149,7 @@ export default { groupName: lastFocusedInputGroup, value: value ?? this.value, }, - // false ); - // window.firedGaClickEventValues[window.lastFocusedInputGroup] = - // value ?? this.value; this.pushEventToGA( this.$route.query[queryStrings.FMG_PAGE], @@ -178,8 +170,6 @@ export default { this.isMultiSelect, false ); - // window.lastFocusedInputGroup = this.groupName; - // window.wasLastFocusedInputMultiselect = this.isMultiSelect; }, handleKeyboardNavigation(key) { this.test(key); @@ -223,7 +213,7 @@ export default { this.groupName, false ); - // window.lastFocusedInputGroup = this.groupName; + if ( firedGaClickEventValues[lastFocusedInputGroup] != currentlySelectedValues[lastFocusedInputGroup] diff --git a/src/store/index.js b/src/store/index.js index 34bba86c0..cd2122ba9 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1398,7 +1398,12 @@ export const actions = { // }); export default createStore({ - plugins: [createPersistedState()], + plugins: [createPersistedState({ + reducer: state => { + const { gaState, ...rest } = state + return rest + } + })], modules: { gaState, }, From 62e3e2dfebe722eadea633f84110637085e442ee Mon Sep 17 00:00:00 2001 From: Katie Date: Thu, 29 Sep 2022 15:44:30 -0400 Subject: [PATCH 04/20] CSR-762 Fix radio click bug --- .../base-input-button/base-input-button.vue | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index 225363401..968259c80 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -28,6 +28,7 @@ import { toRef } from "vue"; import { gaStoreActions } from "../../constants/store-actions"; import store from "../../store"; +// TODO KO Bug: select a chip via radio button, hit continue - doesn't fire the chip number export default { name: "base-input-button", emits: ["change"], @@ -215,13 +216,13 @@ export default { ); if ( - firedGaClickEventValues[lastFocusedInputGroup] != - currentlySelectedValues[lastFocusedInputGroup] + firedGaClickEventValues[this.groupName] != + currentlySelectedValues[this.groupName] ) { this.pushClickEventToGA( - currentlySelectedValues[lastFocusedInputGroup] + currentlySelectedValues[this.groupName] ); - } + } } }, }, From 14bed5524c40d2fa2080048146dbe0aa7a5fe8ee Mon Sep 17 00:00:00 2001 From: Katie Date: Fri, 30 Sep 2022 09:20:15 -0400 Subject: [PATCH 05/20] CSR-762 Wrap up GA events --- .../base-input-button/base-input-button.vue | 14 ++-- .../button-back/button-back.vue | 1 + src/mixins/base-mixin.js | 66 +++++++++++++++---- src/ux-components/button-main/button-main.vue | 30 ++++++--- src/ux-components/text-link/text-link.vue | 10 +-- 5 files changed, 87 insertions(+), 34 deletions(-) diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index 968259c80..e6861a638 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -26,9 +26,9 @@ import { queryStrings } from "@/constants/query-strings"; import { useField } from "vee-validate"; import { toRef } from "vue"; import { gaStoreActions } from "../../constants/store-actions"; -import store from "../../store"; -// TODO KO Bug: select a chip via radio button, hit continue - doesn't fire the chip number +// TODO KO Bug: select crack via keyboard, continue - doesn't fire +// TODO KO Bug: select a chip via keyboard, hit continue - doesn't fire the chip number export default { name: "base-input-button", emits: ["change"], @@ -100,7 +100,7 @@ export default { case eventTypes.CLICK: case eventTypes.KEYPRESS_SUBMIT: this.handleClick(e); - this.test(); + this.pushClickEventToGAIfReady(); break; case eventTypes.CHANGE: this.selectOnKeypress @@ -143,7 +143,7 @@ export default { }, pushClickEventToGA(value) { const lastFocusedInputGroup = - store.getters.gaClickInformation.lastFocusedInputGroup; + this.$store.getters.gaClickInformation.lastFocusedInputGroup; this.dispatchStoreAction( gaStoreActions.UPDATE_FIRED_GA_CLICK_EVENT_VALUES, { @@ -173,10 +173,10 @@ export default { ); }, handleKeyboardNavigation(key) { - this.test(key); + this.pushClickEventToGAIfReady(key); }, - test(event) { - const gaClickInformation = store.getters.gaClickInformation; + pushClickEventToGAIfReady(event) { + const gaClickInformation = this.$store.getters.gaClickInformation; const firedGaClickEventValues = gaClickInformation.firedGaClickEventValues; const currentlySelectedValues = diff --git a/src/common-components/funnel-sub-header/button-back/button-back.vue b/src/common-components/funnel-sub-header/button-back/button-back.vue index cf3a630bf..6112806bb 100644 --- a/src/common-components/funnel-sub-header/button-back/button-back.vue +++ b/src/common-components/funnel-sub-header/button-back/button-back.vue @@ -1,6 +1,7 @@ + diff --git a/src/common-components/button-question/button-question.vue b/src/common-components/button-question/button-question.vue index 8d3abb287..7099e6227 100644 --- a/src/common-components/button-question/button-question.vue +++ b/src/common-components/button-question/button-question.vue @@ -125,7 +125,8 @@ export default { data() { return { primaryValue: "", - lastFocusedInputGroup: "", + // lastFocusedInputGroup: "", + lastPushedGaEventValue: null, }; }, computed: { @@ -197,6 +198,9 @@ export default { }) ); }, + isValueSelectedOnClick() { + return this.isMultiSelect || this.selectingInitiatesLoad; + }, }, methods: { formatString(str) { @@ -222,31 +226,46 @@ export default { }, handleAnswerChange(primaryAnswerValue) { this.primaryValue = primaryAnswerValue; - console.log("hAC: ", primaryAnswerValue) + + this.pushClickEventToGA(null, primaryAnswerValue); + this.$emit("buttonQuestionChange", primaryAnswerValue); this.$emit("update:modelValue", primaryAnswerValue); }, pushClickEventToGA(e, value) { - this.pushEventToGA( - this.$route.query[queryStrings.FMG_PAGE], - this.GaActions.CLICKED, - value?.toString() ?? this.primaryValue?.toString(), - true, - this.valueToLogType - ); + const valueToPushToGa = + value?.toString() ?? this.primaryValue?.toString(); + console.log({ + valueToPushToGa, + lastPushedGaEventValue: this.lastPushedGaEventValue, + }); + if (valueToPushToGa !== this.lastPushedGaEventValue) { + this.lastPushedGaEventValue = valueToPushToGa; + this.pushEventToGA( + this.$route.query[queryStrings.FMG_PAGE], + this.GaActions.CLICKED, + valueToPushToGa, + true, + this.valueToLogType + ); + } }, - handleFocus() { - this.$root.handleFocus({ - groupName: this.groupName, - value: this.primaryValue - }) + onFocusCallbackForRoot() { + if (!this.isValueSelectedOnClick) { + this.pushClickEventToGA(); + } }, - handleBlur() { - this.$root.handleBlur({ + handleFocus(e) { + this.$root.handleInputFocus({ groupName: this.groupName, - value: this.primaryValue - }) - } + }); + }, + handleBlur(e) { + this.$root.handleInputBlur({ + groupName: this.groupName, + onFocusCallback: this.onFocusCallbackForRoot, + }); + }, }, components: { listButton, diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js index 9e99307ee..d6a8ced7e 100644 --- a/src/mixins/base-mixin.js +++ b/src/mixins/base-mixin.js @@ -61,39 +61,39 @@ export default { state: serviceZipValidationResponse.data.state, }; }, - pushRadioClickEventIfNecessary() { - const { - firedGaClickEventValues, - currentlySelectedValues, - lastFocusedInputGroup, - wasLastFocusedInputMultiselect, - } = this.$store.getters.gaClickInformation; + // pushRadioClickEventIfNecessary() { + // const { + // firedGaClickEventValues, + // currentlySelectedValues, + // lastFocusedInputGroup, + // wasLastFocusedInputMultiselect, + // } = this.$store.getters.gaClickInformation; - // Keyboard navigation - if ( - !wasLastFocusedInputMultiselect && - currentlySelectedValues[lastFocusedInputGroup] && - firedGaClickEventValues[lastFocusedInputGroup] != - currentlySelectedValues[lastFocusedInputGroup] - ) { - const value = - currentlySelectedValues[lastFocusedInputGroup]?.toString(); - // this.dispatchStoreAction( - // gaStoreActions.UPDATE_FIRED_GA_CLICK_EVENT_VALUES, - // { - // groupName: lastFocusedInputGroup, - // value: value, - // } - // ); + // // Keyboard navigation + // if ( + // !wasLastFocusedInputMultiselect && + // currentlySelectedValues[lastFocusedInputGroup] && + // firedGaClickEventValues[lastFocusedInputGroup] != + // currentlySelectedValues[lastFocusedInputGroup] + // ) { + // const value = + // currentlySelectedValues[lastFocusedInputGroup]?.toString(); + // // this.dispatchStoreAction( + // // gaStoreActions.UPDATE_FIRED_GA_CLICK_EVENT_VALUES, + // // { + // // groupName: lastFocusedInputGroup, + // // value: value, + // // } + // // ); - this.pushEventToGA( - this.$route.query[queryStrings.FMG_PAGE], - this.GaActions.CLICKED, - value, - true - ); - } - }, + // this.pushEventToGA( + // this.$route.query[queryStrings.FMG_PAGE], + // this.GaActions.CLICKED, + // value, + // true + // ); + // } + // }, }, computed: { storeActions() { From fe9602200ccf3a082ca0abd5ae0bef07f3e1644f Mon Sep 17 00:00:00 2001 From: Katie Date: Wed, 5 Oct 2022 14:22:25 -0400 Subject: [PATCH 11/20] CSR-762 Add tests --- .../base-input-button.spec.js | 523 ++++++++++++++++++ .../base-input-button/base-input-button.vue | 39 +- .../button-question/button-question.vue | 24 +- src/mixins/input-button-wrapper-mixin.js | 13 +- src/mixins/input-button-wrapper-mixin.spec.js | 81 +++ .../list-button-horizontal.vue | 2 +- src/ux-components/list-button/list-button.vue | 2 +- src/ux-components/list-card/list-card.vue | 2 +- src/ux-components/radio/radio.vue | 2 +- 9 files changed, 656 insertions(+), 32 deletions(-) create mode 100644 src/common-components/base-input-button/base-input-button.spec.js create mode 100644 src/mixins/input-button-wrapper-mixin.spec.js diff --git a/src/common-components/base-input-button/base-input-button.spec.js b/src/common-components/base-input-button/base-input-button.spec.js new file mode 100644 index 000000000..9a6e7c168 --- /dev/null +++ b/src/common-components/base-input-button/base-input-button.spec.js @@ -0,0 +1,523 @@ +import { shallowMount, mount } from "@vue/test-utils"; +import baseInputButton from "./base-input-button"; + +describe("baseInputButton.vue", () => { + describe("general", () => { + describe("checkbox", () => { + test("isMultiSelect => baseInputButton is a checkbox", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(inputElement.attributes().type).toEqual("checkbox"); + }); + }); + + describe("radio", () => { + test("!isMultiSelect => baseInputButton is a radio button", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(inputElement.attributes().type).toEqual("radio"); + }); + }); + + // tests in here should be test.each + describe("shared", () => { + const isMultiSelectOptions = [true, false]; + test.each(isMultiSelectOptions)("groupName", (isMultiSelect) => { + const { wrapper } = setupMocks({ + mockData: { + propsData: { + groupName: "boogly", + isMultiSelect: isMultiSelect, + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + const inputElementAttributes = inputElement.attributes(); + expect(inputElementAttributes.name).toEqual("boogly"); + }); + }); + }); + + describe("mouse clicks", () => { + describe("checkbox", () => { + test("clicked => correct event and value are emitted", async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + value: "X", + }, + }, + }); + + // Act + await wrapper.trigger("mousedown.left"); + await wrapper.trigger("click"); + + // Assert + expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual([ + "X", + ]); + }); + }); + + describe("radio", () => { + test("clicked => correct event and value are emitted", async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + value: "X", + }, + }, + }); + + // Act + await wrapper.trigger("mousedown.left"); + await wrapper.trigger("click"); + + // Assert + expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual( + "X" + ); + }); + }); + }); + + describe("keyboard navigation and events", () => { + describe("checkbox", () => { + test.todo( + "focus on a checkbox => inputButtonClicked is not emitted" + ); + + test.todo( + "blur from a checkbox => inputButtonClicked is not emitted" + ); + + test("change event fired from checkbox => inputButtonClicked is emitted with correct value", async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + value: "Hi", + }, + }, + }); + + const input = wrapper.find("input"); + + // Act + await input.trigger("change"); + + // Assert + expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual([ + "Hi", + ]); + }); + + test("focus and click space on a checkbox => inputButtonClicked is not emitted", async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + value: "Hi", + }, + }, + }); + + const input = wrapper.find("input"); + + // Act + await input.trigger("keypress", { key: "space" }); + + // Assert + expect(wrapper.emitted()).not.toHaveProperty( + "inputButtonClicked" + ); + }); + + test("focus and click enter on a checkbox => inputButtonClicked is emitted with correct value", async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + value: "Hi", + }, + }, + }); + + const input = wrapper.find("input"); + + // Act + await input.trigger("keypress", { key: "enter" }); + + // Assert + expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual([ + "Hi", + ]); + }); + }); + + describe("radio", () => { + test.todo( + "focus on a radio button => inputButtonClicked is not emitted" + ); + + test.todo( + "blur from a radio button => inputButtonClicked is not emitted" + ); + + test("focus and click space on a radio button => inputButtonClicked is emitted with correct value", async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + value: "Hi", + }, + }, + }); + + const input = wrapper.find("input"); + + // Act + await input.trigger("keypress", { key: "space" }); + + // Assert + expect(wrapper.emitted()).toHaveProperty("inputButtonClicked"); + expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual( + "Hi" + ); + }); + + test( + "focus and click enter on a radio button => inputButtonClicked is emitted with correct value", + async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + value: "Hi", + }, + }, + }); + + const input = wrapper.find("input"); + + // Act + await input.trigger("keypress", { key: "enter" }); + + // Assert + expect(wrapper.emitted()).toHaveProperty( + "inputButtonClicked" + ); + expect( + wrapper.emitted()["inputButtonClicked"][0][0] + ).toEqual("Hi"); + } + ); + }); + }); + + describe("methods", () => { + describe("handleEventAction", () => {}); + + describe("handleSelectionChange", () => { + describe("checkbox", () => { + test.todo("modelValue is null => inputButtonClicked is emitted with correct") + }) + + describe("radio", () => { + + }) + }); + + describe("handleClick", () => { + test.todo("handleSelectChange is also called") + + test.todo("inputButtonClicked is emitted with valueToEmit") + }); + }); + + describe("computed", () => { + describe("isChecked", () => { + describe("checkbox", () => { + const falsyModelValues = [[], null, undefined]; + test.each(falsyModelValues)( + "modelValue is falsy/empty => checkbox isn't checked", + (modelValue) => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + modelValue, + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.isChecked).toEqual(false); + expect(inputElement.element.checked).toBe(false); + } + ); + + test("modelValue doesn't contain this button's value => checkbox isn't checked", async () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + modelValue: ["Aaa", "Bbb", "Ccc"], + value: "Ddd", + }, + }, + }); + + await wrapper.vm.$nextTick(); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.isChecked).toEqual(false); + expect(inputElement.element.checked).toBe(false); + }); + + test("modelValue contains this button's value => checkbox is checked", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + modelValue: ["Aaa", "Bbb", "Ddd", "Ccc"], + value: "Ddd", + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.isChecked).toEqual(true); + expect(inputElement.element.checked).toBe(true); + }); + }); + + describe("radio", () => { + const falsyModelValues = ["", null, undefined, []]; + test.each(falsyModelValues)( + "modelValue is falsy/empty => radio button isn't checked", + (modelValue) => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + modelValue, + value: "Aaa", + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.isChecked).toEqual(false); + expect(inputElement.element.checked).toBe(false); + } + ); + + test("modelValue equals this button's value => radio button is checked", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + modelValue: "Ddd", + value: "Ddd", + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.isChecked).toEqual(true); + expect(inputElement.element.checked).toBe(true); + }); + + test("modelValue doesn't equal this button's value => radio button isn't checked", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + modelValue: "Aaa", + value: "Ddd", + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.isChecked).toEqual(false); + expect(inputElement.element.checked).toBe(false); + }); + }); + }); + + describe("buttonId", () => { + test("groupName and value combo yield correct id for input button with string value", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + groupName: "my test-name", + value: "Aaa-BBB CcC", + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.buttonId).toBe("my-test-name-Aaa-BBB-CcC"); + expect(inputElement.attributes().id).toBe( + "my-test-name-Aaa-BBB-CcC" + ); + }); + + test("groupName and value combo yield correct id for input button with number value", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + groupName: "my test-name", + value: 2, + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.buttonId).toBe("my-test-name-2"); + expect(inputElement.attributes().id).toBe("my-test-name-2"); + }); + }); + + describe("inputType", () => { + test("isMultiSelect is true => inputType is 'checkbox'", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: true, + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.inputType).toEqual("checkbox"); + expect(inputElement.attributes().type).toBe("checkbox"); + }); + + test("isMultiSelect is false => inputType is 'radio'", () => { + // Arrange/Act + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + }, + }, + }); + + // Assert + const inputElement = wrapper.find("input"); + expect(wrapper.vm.inputType).toEqual("radio"); + expect(inputElement.attributes().type).toBe("radio"); + }); + }); + }); +}); + +// TODO KO look at how I tested groups of these in SFA (making sure selecting one radio changes the value, etc, that this acts like a regular input aside from a different emitted event) + +function setupMocks({ mockData = {}, shouldShallowMount = true }) { + const baseInputButtonWrapper = { + components: { baseInputButton }, + template: '', + data() { + return { + myValue: "", + }; + }, + }; + const mountMockData = { + ...mockData, + propsData: { + // to get rid of some annoying warnings + groupName: "groupName", + modelValue: mockData.propsData?.isMultiSelect ? [] : "", + value: "5", + // should override the above if they exist + ...mockData.propsData, + }, + }; + + const wrapper = shouldShallowMount + ? shallowMount(baseInputButton, mountMockData) + : mount(baseInputButton, mountMockData); + + return { wrapper }; +} + +function setupBaseInputButtonWrapper({ mockData = {} }) { + const baseInputButtonWrapper = { + components: { baseInputButton }, + template: + '
', + data() { + return { + myValue: "", + isMultiSelect: mockData.isMultiSelect, + }; + }, + + // const parentComponent = mount({ + // data() { + // return { + // value: "value1", + // } + // }, + // template: '
', + // components: { baseInputButton } + // }) + }; + + const wrapper = mount(baseInputButtonWrapper, {}); + + return { wrapper }; +} diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index 1a2e51fcc..e82f7438f 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -21,14 +21,14 @@ diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index 12f2743b2..3473ee179 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -5,6 +5,8 @@ @focusin="handleFocus" @focusout="handleBlur" @mousedown.left="handleEventAction('click', $event)"> + lastValuePushedToGa: {{ lastValuePushedToGa }}
+ go to another button > go back to original > tab out + // shouldn't do anything, but it does because wasThisValueJustPushedToGa gets set to false? + // console.log("---inputButtonClicked: ", { + // value: this.value, + // // wasThisValueJustPushedToGa: this.wasThisValueJustPushedToGa + // }); + // const lastValuePushedToGa = this.wasThisValueJustPushedToGa ? this.value : null; + // this.wasThisValueJustPushedToGa = false; + + this.$emit("inputButtonClicked", this.valueToEmit); }, onFocusCallbackForRoot() { // console.log("onFocusCallbackForRoot: ", { @@ -200,19 +214,41 @@ export default { onFocusCallback: this.onFocusCallbackForRoot, }); }, - pushClickEventToGA(eventType) { - if (this.isMultiSelect || !eventType) { - console.log("PUSHING: ", this.value); + + // TODO KO NOTES + // base-input-button has the value to push to GA and the click vs focus events + // but button-question would have to keep track of the button group's last held value + // is there a way to make each individual button hold the group's last held value + // WITHOUT listening to an event on each component that uses the button? + + pushClickEventToGA(source) { + if (source == "test") { + // this.wasThisValueJustPushedToGa = true; + // this.$emit("update:lastValuePushedToGa", this.value) + console.log("------------------PUSHING 1: ", this.value); + // this.$emit("gaClickEventPushed", this.value) + this.setLastValuePushedToGa(this.value) + + // this.wasPushedToGa = true } else { - if (eventType === this.eventTypes.CLICK) { - console.log("PUSHING: ", this.value); - } else { - if ( - this.isChecked && - this.lastValuePushedToGa != this.value - ) { - console.log("PUSHING: ", this.value); - } + // console.log("PCETGA: ", { + // lastValuePushedToGa: this.lastValuePushedToGa, + // isChecked: this.isChecked, + // value: this.value, + // // wasThisValueJustPushedToGa: this.wasThisValueJustPushedToGa + // }); + if ( + !this.isValueSelectedOnClick && + this.isChecked && + // !this.wasThisValueJustPushedToGa && + this.lastValuePushedToGa != this.value + ) { + // this.$emit("update:lastValuePushedToGa", this.value) + // this.wasPushedToGa = true + // this.wasThisValueJustPushedToGa = true; + console.log("------------------PUSHING 2: ", this.value); + // this.$emit("gaClickEventPushed", this.value) + this.setLastValuePushedToGa(this.value) } } diff --git a/src/common-components/button-question/button-question.vue b/src/common-components/button-question/button-question.vue index 2f4d1ec43..fbf819cd2 100644 --- a/src/common-components/button-question/button-question.vue +++ b/src/common-components/button-question/button-question.vue @@ -34,7 +34,6 @@ }}
- lastValuePushedToGa: {{ lastValuePushedToGa }}
@@ -130,8 +130,8 @@ export default { return { selectedValues: "", // lastFocusedInputGroup: "", - lastPushedGaEventValue: null, - mostRecentlySelectedValue: null, + lastValuePushedToGa: null, + // mostRecentlySelectedValue: null, }; }, computed: { @@ -229,9 +229,12 @@ export default { : this.formatString(answer.toString()); } }, - handleAnswerChange({ selectedAnswers, mostRecentlySelectedValue }) { + handleAnswerChange(selectedAnswers) { this.selectedValues = selectedAnswers; - this.mostRecentlySelectedValue = mostRecentlySelectedValue; + // if (lastValuePushedToGa) { + // this.lastValuePushedToGa = lastValuePushedToGa; + // // console.log("BQ lastValuePushedToGa: ", lastValuePushedToGa); + // } // if (this.isValueSelectedOnClick) { // this.pushClickEventToGA(); @@ -240,7 +243,10 @@ export default { this.$emit("buttonQuestionChange", selectedAnswers); this.$emit("update:modelValue", selectedAnswers); }, -///////////////////////////// + ///////////////////////////// + setLastValuePushedToGa(lastValuePushedToGa) { + this.lastValuePushedToGa = lastValuePushedToGa; + }, // onFocusCallbackForRoot() { // console.log("onFocusCallbackForRoot: ", { // isValueSelectedOnClick: this.isValueSelectedOnClick, @@ -297,7 +303,7 @@ export default { // this.valueToLogType // ); // }, -////////////////////////////////// + ////////////////////////////////// // pushClickEventToGA() { // // const valueToPushToGa = // // value?.toString() ?? this.selectedValues?.toString(); diff --git a/src/mixins/input-button-wrapper-mixin.js b/src/mixins/input-button-wrapper-mixin.js index fdf5b3fd1..cfda08c27 100644 --- a/src/mixins/input-button-wrapper-mixin.js +++ b/src/mixins/input-button-wrapper-mixin.js @@ -9,7 +9,7 @@ export default { buttonImage: String, altText: { type: String, - default: "" + default: "", }, textPosition: String, screenReaderOnlyText: String, @@ -18,22 +18,25 @@ export default { isWide: Boolean, isRequired: { type: Boolean, - default: true + default: true, }, // pushClickEventToGA: Function, - lastValuePushedToGa: [String, Number] + lastValuePushedToGa: [String, Number], + setLastValuePushedToGa: Function }, methods: { handleAnswerChange(e) { if (this.preHandleAnswerChange) { - this.preHandleAnswerChange(e.selectedAnswers) + this.preHandleAnswerChange(e); } - - this.$emit("change", e.selectedAnswers); - // this.$emit("update:lastValuePushedToGa", e.lastValuePushedToGa); + + // console.log("IBWM: ", e) + this.$emit("change", e); + // if (e.lastValuePushedToGa) { + // console.log("sup") + // this.$emit("update:lastValuePushedToGa", e.lastValuePushedToGa); + // } }, - - }, // computed: { // selectedValueHandler: { From 9b95effca5624a4b8cc9b50ec4eb387cd4ff4853 Mon Sep 17 00:00:00 2001 From: Katie Date: Fri, 7 Oct 2022 15:48:17 -0400 Subject: [PATCH 16/20] CSR-762 GA Cleanup --- src/common-components/base-input-button/base-input-button.vue | 3 +-- src/common-components/button-question/button-question.vue | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index 76948d4f6..c487b9702 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -23,7 +23,6 @@ diff --git a/src/layouts/vehicle-parts/vehicle-parts.vue b/src/layouts/vehicle-parts/vehicle-parts.vue index e3a5fa7cf..dd03be1c4 100644 --- a/src/layouts/vehicle-parts/vehicle-parts.vue +++ b/src/layouts/vehicle-parts/vehicle-parts.vue @@ -204,9 +204,7 @@ export default { const partNumber = this.alreadyPopulatedPartsData[key].partNumber; g.parts.forEach((p) => { if (p.partNumber === partNumber) { - this.glassParts[g.glassLocation + "-" + g.glassName] = { - [g.glassLocation]: [partNumber], - }; + this.glassParts[g.glassLocation + "-" + g.glassName] = p; } }); }); From afa94625f70b2a0170361e59191a73051180dd8a Mon Sep 17 00:00:00 2001 From: Katie Date: Tue, 11 Oct 2022 16:52:07 -0400 Subject: [PATCH 20/20] CSR-762 Fix tests --- .../base-input-button.spec.js | 78 ++++++++++--------- .../base-input-button/base-input-button.vue | 2 +- .../replace-options-question.spec.js | 2 +- .../vehicle-parts/vehicle-parts.spec.js | 13 +++- src/ux-components/list-card/list-card.spec.js | 8 ++ src/ux-components/radio/radio.spec.js | 36 +++++---- 6 files changed, 86 insertions(+), 53 deletions(-) diff --git a/src/common-components/base-input-button/base-input-button.spec.js b/src/common-components/base-input-button/base-input-button.spec.js index 37e6ccc19..190448df9 100644 --- a/src/common-components/base-input-button/base-input-button.spec.js +++ b/src/common-components/base-input-button/base-input-button.spec.js @@ -215,33 +215,28 @@ describe("baseInputButton.vue", () => { ); }); - test( - "focus and click enter on a radio button => inputButtonClicked is emitted with correct value", - async () => { - // Arrange - const { wrapper } = setupMocks({ - mockData: { - propsData: { - isMultiSelect: false, - value: "Hi", - }, + test("focus and click enter on a radio button => inputButtonClicked is emitted with correct value", async () => { + // Arrange + const { wrapper } = setupMocks({ + mockData: { + propsData: { + isMultiSelect: false, + value: "Hi", }, - }); + }, + }); - const input = wrapper.find("input"); + const input = wrapper.find("input"); - // Act - await input.trigger("keypress", { key: "enter" }); + // Act + await input.trigger("keypress", { key: "enter" }); - // Assert - expect(wrapper.emitted()).toHaveProperty( - "inputButtonClicked" - ); - expect( - wrapper.emitted()["inputButtonClicked"][0][0] - ).toEqual("Hi"); - } - ); + // Assert + expect(wrapper.emitted()).toHaveProperty("inputButtonClicked"); + expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual( + "Hi" + ); + }); }); }); @@ -249,27 +244,33 @@ describe("baseInputButton.vue", () => { describe("handleEventAction", () => {}); describe("handleSelectionChange", () => { - test.todo("handleChange is called with valueToEmit") + test.todo("handleChange is called with valueToEmit"); describe("checkbox", () => { - test.todo("modelValue is null => valueToEmit is correct value") + test.todo("modelValue is null => valueToEmit is correct value"); - test.todo("modelValue is undefined => valueToEmit is correct value") - test.todo("modelValue is empty => valueToEmit is correct value") + test.todo( + "modelValue is undefined => valueToEmit is correct value" + ); + test.todo( + "modelValue is empty => valueToEmit is correct value" + ); - test.todo("modelValue is not empty and does not contain this button's value => valueToEmit is correct value") - test.todo("modelValue is not empty and does contain this button's value => valueToEmit is correct value") - }) + test.todo( + "modelValue is not empty and does not contain this button's value => valueToEmit is correct value" + ); + test.todo( + "modelValue is not empty and does contain this button's value => valueToEmit is correct value" + ); + }); - describe("radio", () => { - - }) + describe("radio", () => {}); }); describe("handleClick", () => { - test.todo("handleSelectChange is also called") + test.todo("handleSelectChange is also called"); - test.todo("inputButtonClicked is emitted with valueToEmit") + test.todo("inputButtonClicked is emitted with valueToEmit"); }); }); @@ -490,6 +491,7 @@ function setupMocks({ mockData = {}, shouldShallowMount = true }) { groupName: "groupName", modelValue: mockData.propsData?.isMultiSelect ? [] : "", value: "5", + setLastValuePushedToGa: () => {}, // should override the above if they exist ...mockData.propsData, }, @@ -499,6 +501,12 @@ function setupMocks({ mockData = {}, shouldShallowMount = true }) { ? shallowMount(baseInputButton, mountMockData) : mount(baseInputButton, mountMockData); + wrapper.vm.pushEventToGA = jest.fn(); + wrapper.vm.$route = { + query: {}, + }; + wrapper.vm.GaActions = {} + return { wrapper }; } diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index c17d6c6d3..8cd50278e 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -185,7 +185,7 @@ export default { }, buttonId() { return `${this.groupName?.replace(" ", "-")}-${this.value - .toString() + ?.toString() ?.replace(" ", "-")}`; }, isValueSelectedOnClick() { diff --git a/src/layouts/vehicle-damage/replace-options-question/replace-options-question.spec.js b/src/layouts/vehicle-damage/replace-options-question/replace-options-question.spec.js index 411bf4e90..aa6ecb06d 100644 --- a/src/layouts/vehicle-damage/replace-options-question/replace-options-question.spec.js +++ b/src/layouts/vehicle-damage/replace-options-question/replace-options-question.spec.js @@ -56,7 +56,7 @@ describe("replace-options-question.vue", () => { //Act wrapper.vm.$options.methods.updateSelectedValues.call(wrapper.vm); - expect(wrapper.vm.selectedReplaceOptions).toEqual([]); + expect(wrapper.vm.selectedValues).toEqual([]); }); }); diff --git a/src/layouts/vehicle-parts/vehicle-parts.spec.js b/src/layouts/vehicle-parts/vehicle-parts.spec.js index d1eaa8df6..62d54c71f 100644 --- a/src/layouts/vehicle-parts/vehicle-parts.spec.js +++ b/src/layouts/vehicle-parts/vehicle-parts.spec.js @@ -183,7 +183,16 @@ describe("vehicle-parts.vue", () => { await nextTick(); //Assert - expect(wrapper.vm.glassParts).toEqual({ "Rear-Stationary": { "Rear": ['DB12209YPYNOEM'] } }); + expect(wrapper.vm.glassParts).toEqual({ + "Rear-Stationary": { + partNumber: "DB12209YPYNOEM", + description: "heated glass, solar, 1 hole", + color: "Gray Tint Privacy", + requiresRecalibration: false, + requiresCapabilityQuestions: false, + childParts: null + } + }); }); test("User had part questions > BackButtonAction triggers a router.navigateWithoutSaving change with correct scenario", async () => { @@ -509,6 +518,8 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {} wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent; wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); wrapper.vm.$refs.loadingModal.showModal = jest.fn(); + // wrapper.vm.$refs.onSubmit = jest.fn(); + // wrapper.vm.$refs.onInvalidSubmit = jest.fn(); return { wrapper, apiPromise }; } diff --git a/src/ux-components/list-card/list-card.spec.js b/src/ux-components/list-card/list-card.spec.js index 19c5d01c2..41d3555e2 100644 --- a/src/ux-components/list-card/list-card.spec.js +++ b/src/ux-components/list-card/list-card.spec.js @@ -14,6 +14,7 @@ describe("list-card.vue", () => { groupID: "checkbox-demo-1", groupName: "Checkbox 1", buttonImage: "windshield-damage.svg", + value: "test value", }, }); @@ -32,6 +33,7 @@ describe("list-card.vue", () => { groupID: "radio-demo-1", groupName: "radio 1", buttonImage: "windshield-damage.svg", + value: "test value", }, }); @@ -51,6 +53,7 @@ describe("list-card.vue", () => { groupName: "radio 1", buttonImage: "windshield-damage.svg", buttonLabelSubCopy: "Test", + value: "test value", }, }); @@ -70,6 +73,7 @@ describe("list-card.vue", () => { groupName: "radio 1", buttonImage: "windshield-damage.svg", buttonLabelSubCopy: "Test", + value: "test value", }, }); @@ -89,6 +93,7 @@ describe("list-card.vue", () => { groupName: "radio 1", buttonImage: "windshield-damage.svg", isRequired: true, + value: "test value", }, }); @@ -110,6 +115,7 @@ describe("list-card.vue", () => { isRequired: true, isWide: true, buttonLabelSubCopy: "", + value: "test value", }, }); @@ -134,6 +140,7 @@ describe("list-card.vue", () => { isRequired: true, isWide: true, buttonLabelSubCopy: "Button Subcopy", + value: "test value", }, }); @@ -159,6 +166,7 @@ describe("list-card.vue", () => { buttonImage: "windshield-damage.svg", isRequired: true, isWide: false, + value: "test value", }, }); diff --git a/src/ux-components/radio/radio.spec.js b/src/ux-components/radio/radio.spec.js index 520fd9daf..83cc22b5a 100644 --- a/src/ux-components/radio/radio.spec.js +++ b/src/ux-components/radio/radio.spec.js @@ -6,12 +6,16 @@ import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin"; describe("radio.vue", () => { it("Should have correct group name", async () => { // Arrange - let { wrapper } = setupMocks({}); + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: { + groupName: "radio-button-test", + value: "test value", + }, + }, + }); // Act - await wrapper.setProps({ - groupName: "radio-button-test", - }); const input = wrapper.find("input"); // Assert @@ -20,12 +24,16 @@ describe("radio.vue", () => { it("Should have correct label text", async () => { // Act - let { wrapper } = setupMocks({}); + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: { + buttonLabel: "label text", + value: "test value", + }, + }, + }); // Arrange - await wrapper.setProps({ - buttonLabel: "label text", - }); const paragraph = wrapper.find("p"); // Assert @@ -39,6 +47,7 @@ describe("radio.vue", () => { // Arrange await wrapper.setProps({ screenReaderOnlyText: "screenreader text", + value: "test value", }); const paragraph = wrapper.find(".sr-only"); @@ -48,13 +57,10 @@ describe("radio.vue", () => { }); function setupMocks({ mountOptionsMockData = {} }) { - const wrapper = mount( - radio, - getMountOptions({ - ...mountOptionsMockData, - mixins: [inputButtonWrapperMixin], - }) - ); + const wrapper = mount(radio, { + ...mountOptionsMockData, + mixins: [inputButtonWrapperMixin], + }); return { wrapper }; }