diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 263f153df..177211ae0 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -11,9 +11,12 @@ const storeActions = { GET_EVOX_IMAGE: "getEvoxImage", LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms", LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin", - // EVENT BUS - ADD_EVENT_TO_BUS: "addEventToBus", - REMOVE_EVENT_FROM_BUS: "removeEventFromBus", + + // DEPENDENCY MUTATIONS + RESET_VEHICLE_AND_DEPS: "resetVehicleAndDependencies", + RESET_DAMAGE_AND_DEPS: "resetDamageAndDependencies", + RESET_REGISTRATION_AND_DEPS: "resetRegistrationAndDependencies", + RESET_PARTS_AND_DEPS: "resetPartsAndDependencies", }; export { storeActions }; diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index 61882b691..c52c955f0 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -1,9 +1,24 @@ 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: "updateVehicle", + + // EVENT BUS MUTATIONS + ADD_EVENT_TO_BUS: "addEventToBus", + REMOVE_EVENT_FROM_BUS: "removeEventFromBus", + + // DEPENDENCY MUTATIONS + RESET_VEHICLE_AND_DEPS: "resetVehicleAndDependencies", + RESET_DAMAGE_AND_DEPS: "resetDamageAndDependencies", + RESET_REGISTRATION_AND_DEPS: "resetRegistrationAndDependencies", + RESET_PARTS_AND_DEPS: "resetPartsAndDependencies", + }; export { storeMutations }; diff --git a/src/helpers/event-bus/event-bus.js b/src/helpers/event-bus/event-bus.js index 47f229210..19b30870c 100644 --- a/src/helpers/event-bus/event-bus.js +++ b/src/helpers/event-bus/event-bus.js @@ -1,10 +1,10 @@ import store from "@/store"; -import { storeActions } from "@/constants/store-actions.js"; +import { storeMutations } from "@/constants/store-mutations.js"; export default { // Adds event to the bus given its category, subcategory, and eventValue; addEventToBus(category, subCategory, eventValue) { - store.commit(storeActions.ADD_EVENT_TO_BUS, { + store.commit(storeMutations.ADD_EVENT_TO_BUS, { category: category, subCategory: subCategory, eventValue: eventValue, @@ -15,7 +15,7 @@ export default { readAndPopEventFromBus(category, subCategory) { const event = store.getters.eventBusItem(category, subCategory); - store.commit(storeActions.REMOVE_EVENT_FROM_BUS, { + store.commit(storeMutations.REMOVE_EVENT_FROM_BUS, { category: category, subCategory: subCategory, }); diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index ba46df331..b27259e49 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -18,9 +18,10 @@ import replaceOptionsQuestion from"@/layouts/vehicle-damage/replace-options-ques // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; +import { storeActions } from "@/constants/store-actions"; import store from "@/store"; import baseMixin from "@/mixins/base-mixin"; -import { storeActions } from "@/constants/store-actions"; + export default { name: "vehicle-damage", @@ -69,6 +70,10 @@ export default { arePagePrerequisitesValid() { return store.getters.vehicle.carId !== null; }, + resetDependentState() { + // Invokes + store.dispatch(storeActions.RESET_PARTS_AND_DEPS); + }, }, components: { funnelHeader, diff --git a/src/layouts/vehicle-make/vehicle-make.spec.js b/src/layouts/vehicle-make/vehicle-make.spec.js index 146dd6318..b3a006c20 100644 --- a/src/layouts/vehicle-make/vehicle-make.spec.js +++ b/src/layouts/vehicle-make/vehicle-make.spec.js @@ -153,7 +153,7 @@ describe("vehicle-make.vue", () => { pageHeaderWidgetHeaderText: "Select a make to get started", mountOptionsMockData: { router: { - navigate: jest.fn(), + navigateForward: jest.fn(), }, }, }); @@ -170,7 +170,7 @@ describe("vehicle-make.vue", () => { //Assert apiPromise.finally(() => { - expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled(); done(); }); }); diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue index 111b16e5f..f95172547 100644 --- a/src/layouts/vehicle-make/vehicle-make.vue +++ b/src/layouts/vehicle-make/vehicle-make.vue @@ -25,7 +25,10 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; +import { storeMutations } from "@/constants/store-mutations"; +import { storeActions } from "@/constants/store-actions"; import store from "@/store"; + export default { name: "vehicle-make", data() { @@ -75,17 +78,31 @@ export default { methods: { backButtonAction() { // route to move backwards - this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); + this.$router.navigateForward( + this.navigationScenarios.CLICKED_BACK, + this.$route + ); }, arePagePrerequisitesValid() { return store.getters.vehicle.year !== null; }, + resetDependentState() { + // Set + store.commit(storeMutations.UPDATE_MODEL, null); + store.commit(storeMutations.UPDATE_STYLE, null); + store.commit(storeMutations.UPDATE_CAR_ID, null); + store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null); + + // Invokes + store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS); + store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS); + }, }, watch: { selectedMake(make) { this.$store.commit(this.storeMutations.UPDATE_MAKE, make); - this.$router.navigate( + this.$router.navigateAfterSave( this.navigationScenarios.SELECTED_MAKE, this.$route ); diff --git a/src/layouts/vehicle-model/vehicle-model.spec.js b/src/layouts/vehicle-model/vehicle-model.spec.js index 4c61215ba..b1e240288 100644 --- a/src/layouts/vehicle-model/vehicle-model.spec.js +++ b/src/layouts/vehicle-model/vehicle-model.spec.js @@ -141,7 +141,7 @@ describe("vehicle-model.vue", () => { pageHeaderWidgetHeaderText: "Select a model to get started", mountOptionsMockData: { router: { - navigate: jest.fn(), + navigateForward: jest.fn(), }, }, }); @@ -156,7 +156,7 @@ describe("vehicle-model.vue", () => { await nextTick(); //Assert apiPromise.finally(() => { - expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled(); done(); }); }); diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue index b27b98d40..06794e9a2 100644 --- a/src/layouts/vehicle-model/vehicle-model.vue +++ b/src/layouts/vehicle-model/vehicle-model.vue @@ -24,6 +24,8 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { storeMutations } from "@/constants/store-mutations"; +import { storeActions } from "@/constants/store-actions"; import { settleAllPromises } from "@/helpers/layout-helper"; import store from "@/store"; @@ -77,17 +79,30 @@ export default { methods: { backButtonAction() { // route to move backwards - this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); + this.$router.navigateForward( + this.navigationScenarios.CLICKED_BACK, + this.$route + ); }, arePagePrerequisitesValid() { return store.getters.vehicle.make !== null; }, + resetDependentState() { + // Set + store.commit(storeMutations.UPDATE_STYLE, null); + store.commit(storeMutations.UPDATE_CAR_ID, null); + store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null); + + // Invokes + store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS); + store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS); + }, }, watch: { selectedModel(model) { this.$store.commit(this.storeMutations.UPDATE_MODEL, model); - this.$router.navigate( + this.$router.navigateAfterSave( this.navigationScenarios.SELECTED_MODEL, this.$route ); diff --git a/src/layouts/vehicle-style/vehicle-style.spec.js b/src/layouts/vehicle-style/vehicle-style.spec.js index 183b22d57..e52818cf6 100644 --- a/src/layouts/vehicle-style/vehicle-style.spec.js +++ b/src/layouts/vehicle-style/vehicle-style.spec.js @@ -154,7 +154,7 @@ describe("vehicle-style.vue", () => { pageHeaderWidgetHeaderText: "Select a style to get started", mountOptionsMockData: { router: { - navigate: jest.fn(), + navigateForward: jest.fn(), }, }, }); @@ -171,7 +171,7 @@ describe("vehicle-style.vue", () => { //Assert apiPromise.finally(() => { - expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled(); done(); }); }); diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue index 7193c9e39..ec1cd4598 100644 --- a/src/layouts/vehicle-style/vehicle-style.vue +++ b/src/layouts/vehicle-style/vehicle-style.vue @@ -25,6 +25,7 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; +import { storeActions } from "@/constants/store-actions"; import store from "@/store"; export default { @@ -77,7 +78,10 @@ export default { methods: { backButtonAction() { // route to move backwards - this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); + this.$router.navigateForward( + this.navigationScenarios.CLICKED_BACK, + this.$route + ); }, setVehicle() { return this.dispatchNonBlockingStoreAction( @@ -93,13 +97,18 @@ export default { arePagePrerequisitesValid() { return store.getters.vehicle.model !== null; }, + resetDependentState() { + // Invokes + store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS); + store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS); + }, }, watch: { selectedStyle(style) { this.$store.commit(this.storeMutations.UPDATE_STYLE, style); this.setVehicle().then(() => { - this.$router.navigate( + this.$router.navigateAfterSave( this.navigationScenarios.SELECTED_STYLE, this.$route ); diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index ddef0d5a8..aeeaecf94 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -20,7 +20,9 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; -import eventBus from "@/helpers/event-bus/event-bus"; +import { storeMutations } from "@/constants/store-mutations"; +import { storeActions } from "@/constants/store-actions"; +import store from "@/store"; export default { name: "vehicle-year", @@ -71,8 +73,9 @@ export default { watch: { selectedYear(year) { + this.$store.commit(this.storeMutations.UPDATE_YEAR, year); - this.$router.navigate( + this.$router.navigateAfterSave( this.navigationScenarios.SELECTED_YEAR, this.$route ); @@ -82,6 +85,19 @@ export default { arePagePrerequisitesValid() { return true; }, + resetDependentState() { + + // Set + store.commit(storeMutations.UPDATE_MAKE, null); + store.commit(storeMutations.UPDATE_MODEL, null); + store.commit(storeMutations.UPDATE_STYLE, null); + store.commit(storeMutations.UPDATE_CAR_ID, null); + store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null); + + // Invokes + store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS); + store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS); + } }, components: { yearQuestion, diff --git a/src/router/index.js b/src/router/index.js index eb4942d6a..ac31a1c6d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -45,16 +45,16 @@ const routes = [ // If we already have our route, go to it. if (router.hasRoute(to.query.fmgPage)) { // Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function. - const arePagePrerequisitesValid = router + const component = router .getRoutes() - .filter((x) => x.name === to.query.fmgPage)[0] - .components.default.methods.arePagePrerequisitesValid(); + .filter((x) => x.name === to.query.fmgPage)[0].components; - if (!arePagePrerequisitesValid) { + if (!arePagePrerequisitesValid(component)) { await GoToFunnelStartOn404(next); } - return next({ name: to.query.fmgPage, query: to.query, params: to.params }); + + return next({ name: to.query.fmgPage, query: to.query, params: to.params }); } // Get route info for the given url. Names will have a 1:1 relationship with names in the Cms. @@ -74,7 +74,7 @@ const routes = [ .filter((x) => x.name === routeData[0].name)[0] .components.default(); - if (!nextComponent.default.methods.arePagePrerequisitesValid()) { + if (!arePagePrerequisitesValid(nextComponent)) { await GoToFunnelStartOn404(next); } @@ -102,23 +102,36 @@ const router = createRouter({ //---------------------------------------------------------- Router Functions ---------------------------------------------------------- +router.navigateForward = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => { + navigate(scenario, currentRoute, false, optionalQuery, optionalParams); +} + +router.navigateAfterSave = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => { + navigate(scenario, currentRoute, true, optionalQuery, optionalParams); +} + +// PRIVATE FUNCTIONS + // Navigate to the next route, depending on the scenario. -router.navigate = ( - scenario, - currentRoute, - optionalQuery = {}, - optionalParams = {} -) => { +function navigate(scenario, currentRoute, invalidateOnSave, optionalQuery = {}, optionalParams = {}) { if (!scenario) { console.error("No scenario provided. Please review the routing table."); return; } // Match our maps up and navigate if we have a destination. - const matchingScenarioMap = router.getNavigationMap(scenario, currentRoute); + const matchingScenarioMap = getNavigationMap(scenario, currentRoute); if (matchingScenarioMap.destinationFmgPageValue !== undefined) { // We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one. + + // If we need to do invalidation + const currentComponent = currentRoute.matched[0].components; + + if (invalidateOnSave) { + resetDependentState(currentComponent); + } + router.push({ name: "root", query: Object.assign(optionalQuery, { @@ -132,7 +145,7 @@ router.navigate = ( }; // Get navigation map depending on the scenario and the current 'page' you're on. -router.getNavigationMap = (scenario, currentRoute) => { +function getNavigationMap(scenario, currentRoute) { const fmgPageValue = currentRoute.query.fmgPage; const matchedQueryValue = routingTable .filter( @@ -197,4 +210,14 @@ async function GoToFunnelStartOn404(next) { }); } +// Checks arePagePrerequisitesValid on the component passed in. +function arePagePrerequisitesValid(component) { + return component.default.methods.arePagePrerequisitesValid(); +} + +// Reset dependant state on route change. +function resetDependentState(component) { + return component.default.methods.resetDependentState(); +} + export default router; diff --git a/src/store/index.js b/src/store/index.js index 9d5078f74..22107ab76 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,7 +3,7 @@ import { endpoints } from "@/constants/endpoints.js"; import { storeMutations } from "@/constants/store-mutations"; import createPersistedState from "vuex-persistedstate"; import globalMethods from "@/global-methods"; -import eventBus from "../helpers/event-bus/event-bus"; + export default createStore({ plugins: [createPersistedState()], @@ -35,6 +35,8 @@ export default createStore({ // See IMPORTANT note at top of "state" declaration. mutations: { + + // VEHICLE MUTATIONS updateYear(state, year) { state.order.vehicle.year = year; }, @@ -47,10 +49,18 @@ export default createStore({ updateStyle(state, style) { state.order.vehicle.style = style; }, + updateCarId(state, carId) { + state.order.vehicle.carId = carId; + }, + updateVehicleCategory(state, category) { + state.order.vehicle.category = category; + }, updateVehicle(state, data) { state.order.vehicle.carId = data.carId; state.order.vehicle.category = data.category; }, + + // EVENT BUS MUTATIONS addEventToBus(state, event) { state.applicationUser.eventBus.push(event); }, @@ -67,6 +77,31 @@ export default createStore({ state.applicationUser.eventBus.splice(itemIndex, 1); } }, + + // DEPENDENCY MUTATIONS + resetVehicleAndDependencies(state) { + state.order.vehicle.year = null; + state.order.vehicle.make = null; + state.order.vehicle.model = null; + state.order.vehicle.style = null; + state.order.vehicle.carId = null; + state.order.vehicle.category = null; + }, + resetDamageAndDependencies(state) { + state.order.vehicle.damage.isRepair = null; + state.order.vehicle.damage.numberOfChips = null; + state.order.vehicle.damage.windshieldGlassToReplace = null; + state.order.vehicle.damage.driverSideGlassToReplace = null; + state.order.vehicle.damage.passengerSideGlassToReplace = null; + state.order.vehicle.damage.rearGlassToReplace = null; + + }, + resetRegistrationAndDependencies(state) { + + }, + resetPartsAndDependencies(state) { + + } }, getters: { vehicle: (state) => state.order.vehicle, @@ -146,6 +181,24 @@ export default createStore({ }); }, + // DEPENDENCY ACTIONS + resetVehicleAndDependencies(context) { + context.commit(storeMutations.RESET_VEHICLE_AND_DEPS); + context.commit(storeMutations.RESET_DAMAGE_AND_DEPS); + context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS); + }, + resetDamageAndDependencies(context) { + context.commit(storeMutations.RESET_DAMAGE_AND_DEPS); + context.commit(storeMutations.RESET_PARTS_AND_DEPS); + }, + resetRegistrationAndDependencies(context) { + context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS); + context.commit(storeMutations.RESET_PARTS_AND_DEPS) + }, + resetPartsAndDependencies(context) { + context.commit(storeMutations.RESET_PARTS_AND_DEPS); + }, + // Content API Actions getRouteInfo(context, { pageName }) { return globalMethods.callHttpClient({