From d53b7e276c0f01c2ac913457f0e909e227114d02 Mon Sep 17 00:00:00 2001 From: Jason Wheeler Date: Tue, 10 Jan 2023 09:07:35 -0500 Subject: [PATCH 1/9] check in so I can pull develop into this branch. --- src/constants/application-config.js | 1 + src/constants/error-messages.js | 4 +- .../address-lookup/address-lookup.spec.js | 730 ++++++++++++++++++ src/layouts/address-lookup/address-lookup.vue | 531 +++++++++++-- .../address-questions.spec.js | 590 ++++++++++++++ .../address-questions/address-questions.vue | 403 ++++++++++ .../customer-questions.spec.js | 33 + .../customer-questions/customer-questions.vue | 102 +++ src/mixins/vin-pages-mixin.js | 15 + src/mixins/vin-pages-mixin.spec.js | 70 ++ src/store/index.js | 3 + vue.config.js | 2 + 12 files changed, 2404 insertions(+), 80 deletions(-) create mode 100644 src/layouts/address-lookup/address-lookup.spec.js create mode 100644 src/layouts/address-lookup/customer-questions/address-questions/address-questions.spec.js create mode 100644 src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue create mode 100644 src/layouts/address-lookup/customer-questions/customer-questions.spec.js create mode 100644 src/layouts/address-lookup/customer-questions/customer-questions.vue create mode 100644 src/mixins/vin-pages-mixin.js create mode 100644 src/mixins/vin-pages-mixin.spec.js diff --git a/src/constants/application-config.js b/src/constants/application-config.js index 51496b9f..a3baacb2 100644 --- a/src/constants/application-config.js +++ b/src/constants/application-config.js @@ -8,6 +8,7 @@ const applicationConfig = { SITE_ENTRY_TRIGGER_VALUE: "SelfService", APPLICATION_ABBREVIATION: "iss", PAGE_QUERYSTRING: 'issPage', + GOOGLE_PLACES_API_KEY: process.env.VUE_APP_GOOGLE_PLACES_API_KEY, }; export { applicationConfig }; \ No newline at end of file diff --git a/src/constants/error-messages.js b/src/constants/error-messages.js index 19dda7e8..6c206946 100644 --- a/src/constants/error-messages.js +++ b/src/constants/error-messages.js @@ -18,8 +18,8 @@ const errorMessages = { LAST_NAME_REQUIRED: "Please enter your last name", EMAIL_ADDRESS_REQUIRED: "Please enter your email address", EMAIL_ADDRESS_FORMAT: "Please enter a valid email address", - SERVICE_ZIP_REQUIRED: "Please enter your service ZIP", - SERVICE_ZIP_FORMAT: "Please enter a valid service ZIP", + SERVICE_ZIP_REQUIRED: "Please enter your ZIP", + SERVICE_ZIP_FORMAT: "Please enter a valid ZIP", VIN_REQUIRED: "Please enter your VIN", VIN_FORMAT: "Invalid VIN. Please make sure that you entered the correct 17-digit, alpha-numeric number. VINs do not contain the letters I, O, or Q", OPTION_REQUIRED: "Please select an option", diff --git a/src/layouts/address-lookup/address-lookup.spec.js b/src/layouts/address-lookup/address-lookup.spec.js new file mode 100644 index 00000000..2c4b4495 --- /dev/null +++ b/src/layouts/address-lookup/address-lookup.spec.js @@ -0,0 +1,730 @@ +// Components +import addressLookup from "@/layouts/address-lookup/address-lookup.vue"; + +// Supporting Files +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { storeActions } from "@/constants/store-actions"; +import { storeMutations } from "@/constants/store-mutations"; +import { navigationScenarios } from "@/router/router-constants/navigation-scenarios"; +import store from "@/store"; +import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; + +jest.mock("@/helpers/damage-helper", () => ({ + isGlassAvailableForCarId: jest.fn().mockImplementation(() => true), + getDamageString: jest.fn(), +})); + +jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({ + navigateToHeritageFunnel: jest.fn(), +})); + +// Mock our module for promises. +jest.mock("@/helpers/layout-helper.js", () => ({ + settleAllPromises: jest.fn(), +})); + +describe("address-lookup.vue", () => { + describe("page level alerts", () => { + test("if the address is not serviceable display the Non-Serviceable Zip Alert", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipValid: true, + isZipServiceable: false, + vinVehicles: [ + { + vin: "TEST_VIN", + vehicle: { + carId: "C0000", + }, + }, + ], + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.findComponent({ ref: "alertNonServiceableZip" }).isVisible()).toBe(true); + }); + + test("if the address matches a different vehicle display the Matched Different VehicleAlert", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: true, + vinVehicles: [ + { + vehicle: { + carId: "C00000", + }, + }, + ], + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID2"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.findComponent({ ref: "alertMatchedDifferentVehicle" }).isVisible()).toBe( + true + ); + }); + + test("if the looking up VIN by address is not allowed in the state selected display the Vin Lookup By HomeAddress Not Allowed Alert", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: true, + isStatePermissible: false, + lookupVinbyAddressResponse: { + isStatePermissible: false, + vinVehicles: [ + { + vin: "TEST_VIN", + vehicle: { + carId: "CARID", + }, + }, + { + vin: "TEST_VIN2", + vehicle: { + carId: "CARID2", + }, + }, + ], + }, + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect( + wrapper.findComponent({ ref: "alertVinLookupsByHomeAddressNotAllowed" }).isVisible() + ).toBe(true); + }); + + test("if no vehicles found, display Vin Not Found alert", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: true, + lookupVinbyAddressResponse: { + isStatePermissible: true, + vinVehicles: [], // Return no vehicles + }, + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + wrapper.vm.navigateForward = jest.fn(); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.findComponent({ ref: "alertVinNotFound" }).isVisible()).toBe(true); + }); + }); + + describe("navigation", () => { + test("if the back button is clicked, navigate back", async () => { + // Arrange + const { wrapper } = setupMocks({ + isZipServiceable: true, + }); + + // Act + await wrapper.vm.backButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled(); + }); + + test("if the car entered matches one of the vehicles found and the zip is serviceable, navigate forward", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: true, + vinVehicles: [ + { + vehicle: { + carId: "C11111", + }, + }, + ], + }); + + await wrapper.setData({ + previouslyEnteredCarId: "C11111", + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + wrapper.vm.navigateForward = jest.fn(); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.navigateForward).toHaveBeenCalled(); + }); + + test("if the car entered does not match any of the multiple vehicles found, navigate to address-vehicles page", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: true, + isStatePermissible: true, + vinVehicles: [ + { + vin: "TEST_VIN", + vehicle: { + carId: "CARID", + }, + }, + { + vin: "TEST_VIN2", + vehicle: { + carId: "CARID2", + }, + }, + ], + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID_A"); + + const carsFound = [ + { + vin: "TEST_VIN", + vehicle: { + carId: "CARID", + }, + }, + { + vin: "TEST_VIN2", + vehicle: { + carId: "CARID2", + }, + }, + ]; + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + wrapper.vm.updateVehicleInfo = jest.fn(); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES, + undefined, + {}, + {}, + carsFound + ); + }); + + test("if the car entered matches one of the vehicles found but the zip is NOT serviceable, do not navigate forward", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: false, + isStatePermissible: true, + vinVehicles: [ + { + vin: "TEST_VIN", + vehicle: { + carId: "CARID", + }, + }, + { + vin: "TEST_VIN2", + vehicle: { + carId: "CARID2", + }, + }, + ], + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + wrapper.vm.navigateForward = jest.fn(); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.navigateForward).toHaveBeenCalledTimes(0); + }); + + test("if a different vehicle is found than the one entered and the selected glass is not available for that vehicle, navigate back to vehicle-damage page", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: true, + isStatePermissible: true, + }); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + isCarIdDifferent: true, + isSelectedGlassAvailableForVehicle: false, + }); + + let carsFound = [ + { + vin: "TEST_VIN2", + vehicle: { + carId: "C0000", + }, + }, + ]; + + // Act + await wrapper.vm.navigateForward(carsFound); + + // Assert + expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith( + navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS, + undefined, + {}, + { displayVehicleChangeAlert: true } + ); + }); + + test("single car was found and matches entered vehicle => navigateForwardWithSingleCarMatch", async () => { + // Arrange + + const carsFound = [ + { + vin: "TEST_VIN_2", + vehicle: { + carId: "C0000", + }, + }, + ]; + + const { wrapper } = setupMocks({}, {}); + wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn(); + + // Act + wrapper.vm.navigateForward(carsFound); + + // Assert + expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1); + }); + + test("multiple cars were found and one matches entered vehicle => navigateForwardWithSingleCarMatch", async () => { + // Arrange + const carsFound = [ + { + vin: "TEST_VIN_1", + vehicle: { + carId: "C0000", + }, + }, + { + vin: "TEST_VIN_2", + vehicle: { + carId: "CARID2", + }, + }, + { + vin: "TEST_VIN_3", + vehicle: { + carId: "CARID3", + }, + }, + ]; + + const { wrapper } = setupMocks({}); + wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn(); + + // Act + wrapper.vm.navigateForward(carsFound); + + // Assert + expect(wrapper.vm.navigateForwardWithSingleCarMatch).toHaveBeenCalledTimes(1); + }); + }); + + describe("registration and service zips", () => { + describe("if registration zip is serviceable", () => { + test("if registration address is provided => update service address on successful continue", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: true, + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalledWith( + "lookupVinByAddress", + { + licenseLastName: undefined, + licenseState: "OH", + licenseStreetAddress: "1234 Main St", + licenseZip: "43215", + }, + false + ); + + expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalledWith("validateZip", { + zip: "43215", + }); + }); + }); + + describe("if registration zip is not serviceable", () => { + test("if registration address is provided and user clicks continue => show non-serviceable zip alert", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipValid: true, + isZipServiceable: false, + vinVehicles: [ + { + vin: "TEST_VIN", + vehicle: { + carId: "C0000", + }, + }, + ], + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + expect(wrapper.findComponent({ ref: "alertNonServiceableZip" }).exists()).toBe( + false + ); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.displayNonServiceableZipAlert).toBe(true); + expect(wrapper.findComponent({ ref: "alertNonServiceableZip" }).exists()).toBe( + true + ); + expect(wrapper.findComponent({ ref: "alertNonServiceableZip" }).isVisible()).toBe( + true + ); + }); + + test("if registration address, service zip are provided, and user clicks continue => don't update service address", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({ + isZipServiceable: false, + }); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + // Act + await wrapper.vm.forwardButtonAction(); + + //FIX THIS + // Assert + expect(wrapper.vm.dispatchStoreAction).not.toHaveBeenCalledWith( + storeActions.UPDATE_SERVICE_LOCATION_WITH_VEHICLE_REGISTRATION + ); + }); + + test("if registration address, service zip are provided, and user clicks continue => both zips are saved and are different", async () => { + // Arrange + const mockRegistrationAddress = { + streetAddress: "1234 Main St", + city: "Columbus", + state: "OH", + zipCode: "43215", + }; + + const { wrapper } = setupMocks({}); + wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn(); + + store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); + + wrapper.vm.dispatchStoreAction = jest.fn(); + wrapper.vm.dispatchStoreAction.mockImplementation((actionName, value) => { + let data = {}; + if (actionName == storeActions.VALIDATE_ZIP) { + if (value == "43215") { + data = { + isServiceable: false, + }; + } else { + data = { + isServiceable: true, + }; + } + } else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) { + data = { + isStatePermissible: true, + vinVehicles: [ + { + vin: "TEST_VIN", + vehicle: { + carId: "CARID", + }, + }, + ], + }; + } + + return Promise.resolve({ data }); + }); + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress, + }, + }); + + await wrapper.vm.forwardButtonAction(); + await wrapper.setData({ + serviceZipCode: "12345", + }); + + // // Act + await wrapper.vm.forwardButtonAction(); + + // // Assert + expect(wrapper.vm.$store.getters.order.serviceLocation.zipCode).not.toEqual( + wrapper.vm.$store.getters.vehicle.registration.zipCode + ); + expect(wrapper.vm.$store.getters.vehicle.registration.zipCode).toEqual("12345"); + expect(wrapper.vm.$store.getters.order.serviceLocation.zipCode).toEqual("11111"); + }); + }); + }); +}); + +function setupMocks({ + isZipValid = true, + isZipServiceable = true, + lookupVinbyAddressResponse, + partsOrQuestions = [], + isStatePermissible = true, + vinVehicles = [], + carId = "C0000", +}) { + store.commit(storeMutations.RESET_STATE); + const wrapper = shallowMount( + addressLookup, + getMountOptions({ + actionList: [ + { + actionName: storeActions.VALIDATE_ZIP, + data: { + isValid: isZipValid, + isServiceable: isZipServiceable, + }, + }, + { + actionName: storeActions.LOOKUP_VIN_BY_ADDRESS, + data: lookupVinbyAddressResponse + ? lookupVinbyAddressResponse + : { + isStatePermissible: true, + vinVehicles: [ + { + vin: "TEST_VIN", + vehicle: { + carId: "CARID", + }, + }, + ], + }, + }, + { + actionName: storeActions.GET_PARTS_OR_QUESTIONS, + data: { + partsOrQuestions: partsOrQuestions, + }, + }, + ], + router: { + navigate: jest.fn(), + navigate: jest.fn(), + navigateWithSaving: jest.fn(), + navigateWithoutSaving: jest.fn(), + }, + store: { + getters: { + vehicle: { + carId: carId, + registration: { + licensePlate: "TESTPLATE", + zipCode: "12345", + }, + }, + order: { + customer: { + emailAddress: "test@test.com", + }, + serviceLocation: { + zipCode: "11111", + }, + }, + }, + }, + }) + ); + + const apiResponses = { + serviceZipValidationResponse: { + isValid: isZipValid, + isServiceable: isZipServiceable, + }, + vinLookupResponse: { + isStatePermissible: isStatePermissible, + vinVehicles: vinVehicles, + }, + }; + + settleAllPromises.mockImplementation(() => apiResponses); + + wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); + wrapper.vm.setCmsContent = jest.fn(); + wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); + wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); + + return { wrapper }; +} diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index 4dff1016..de93f09f 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -1,90 +1,465 @@ - diff --git a/src/main.js b/src/main.js index 3a666d55..d7e9ef55 100644 --- a/src/main.js +++ b/src/main.js @@ -7,6 +7,7 @@ import { useMainStore } from '@/store'; import baseMixin from "@/mixins/base-mixin.js"; import { createPinia } from 'pinia'; import Maska from "maska"; +import LoadScript from "vue-plugin-load-script"; import analyticsMixin from "@/mixins/analytics-mixin.js"; import experimentMixin from "@/mixins/experiment-mixin.js"; @@ -31,6 +32,7 @@ useMainStore().populateInitialState(); // Additional Vue items to setup vueApp.use(router); vueApp.use(Maska); +vueApp.use(LoadScript); vueApp.mixin(baseMixin); vueApp.mixin(analyticsMixin); vueApp.mixin(experimentMixin); diff --git a/src/mixins/vin-pages-mixin.js b/src/mixins/vin-pages-mixin.js index 1549ed4b..9b9de2e1 100644 --- a/src/mixins/vin-pages-mixin.js +++ b/src/mixins/vin-pages-mixin.js @@ -6,7 +6,7 @@ export default { async navigateForwardWithSingleCarMatch() { const store = useMainStore(); - const result = await store.getParts(); + const result = await store.getPartsOrQuestions(); const partsOrQuestions = result.data.partsOrQuestions; vehicleQuestionsMixin.methods.navigateForward(partsOrQuestions, this); From c3d164cc2ca03fabf65bd59f306fd99c03725d42 Mon Sep 17 00:00:00 2001 From: Jason Wheeler Date: Tue, 10 Jan 2023 17:16:39 -0500 Subject: [PATCH 3/9] updates --- src/constants/endpoints.js | 4 + src/layouts/address-lookup/address-lookup.vue | 94 +++++++++--------- src/store/index.js | 96 ++++++++++++++++++- 3 files changed, 141 insertions(+), 53 deletions(-) diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 8512c417..b2df065d 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -75,6 +75,10 @@ const endpoints = { url: "/experiments/api/v1/experiments/run", method: "POST", }, + ValidateZip: { + url: "/location/api/v1/location/zip", + method: "GET", + }, }; export { endpoints }; diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index 19e18fa1..8558f182 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -111,7 +111,7 @@ defineRule( export default { name: "address-lookup", - //mixins: [vinPagesMixin], + mixins: [vinPagesMixin], async beforeRouteEnter(to, from, next) { // Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); @@ -135,16 +135,16 @@ export default { return { customerQuestions: { addressQuestions: { - streetAddress: this.getRegistrationAddressFromStore(), - city: this.getRegistrationCityFromStore(), - state: this.getRegistrationStateFromStore(), - zipCode: this.getRegistrationZipFromStore(), + streetAddress: this.registrationAddress, + city: this.registrationCity, + state: this.registrationState, + zipCode: this.registrationZip, }, - firstName: this.getRegistrationFirstNameFromStore(), - lastName: this.getRegistrationLastNameFromStore(), - emailAddress: this.getEmailFromStore(), + firstName: this.registrationFirstName, + lastName: this.registrationLastName, + emailAddress: this.getEmailFromStore, }, - serviceZipCode: this.getServiceZipFromStore(), + serviceZipCode: this.serviceZip, displayNonServiceableZipAlert: false, displayVinNotFoundAlert: false, displayMatchedDifferentVehicleAlert: false, @@ -154,13 +154,39 @@ export default { isSelectedGlassAvailableForVehicle: true, customAlertData: {}, displayInvalidZipAlert: false, - showServiceZipField: this.getServiceZipFromStore(), + showServiceZipField: this.serviceZip, isZipServiceable: false, }; }, + computed: { + registrationAddress() { + return this.mainStore.order.vehicle.registration.address; + }, + registrationCity() { + return this.mainStore.order.vehicle.registration.city; + }, + registrationState() { + return this.mainStore.order.vehicle.registration.state; + }, + registrationZip() { + return this.mainStore.order.vehicle.registration.zipCode; + }, + registrationFirstName() { + return this.mainStore.order.vehicle.registration.firstName; + }, + registrationLastName() { + return this.mainStore.order.vehicle.registration.lastName; + }, + getEmailFromStore() { + return this.mainStore.order.customer.emailAddress; + }, + serviceZip() { + return this.mainStore.order.serviceLocation.zipCode; + } + }, methods: { arePagePrerequisitesValid() { - return this.mainStore.order.vehicle.carId !== null; + return useMainStore().order.vehicle.carId !== null; }, backButtonAction() { // route to move backwards @@ -176,30 +202,7 @@ export default { ); }); }, - getRegistrationAddressFromStore() { - return useMainStore().order.vehicle.registration.address; - }, - getRegistrationCityFromStore() { - return useMainStore().order.vehicle.registration.city; - }, - getRegistrationStateFromStore() { - return useMainStore().order.vehicle.registration.state; - }, - getRegistrationZipFromStore() { - return useMainStore().order.vehicle.registration.zipCode; - }, - getRegistrationFirstNameFromStore() { - return useMainStore().order.vehicle.registration.firstName; - }, - getRegistrationLastNameFromStore() { - return useMainStore().order.vehicle.registration.lastName; - }, - getEmailFromStore() { - return useMainStore().order.customer.emailAddress; - }, - getServiceZipFromStore() { - return useMainStore().order.serviceLocation.zipCode; - }, + async forwardButtonAction() { this.resetWarningsAndErrors(); @@ -229,12 +232,8 @@ export default { { resultKey: "serviceZipValidationResponse", promise: this.serviceZipCode - ? this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { - zip: this.serviceZipCode, - }) - : this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { - zip: this.customerQuestions.addressQuestions.zipCode, - }), + ? useMainStore().validateZip({zip: this.serviceZipCode}) + : useMainStore().validateZip({zip: this.customerQuestions.addressQuestions.zipCode}) }, ]; @@ -314,8 +313,7 @@ export default { } // Save vehicle, customer, service and registration information - await this.dispatchStoreAction( - storeActions.SAVE_REGISTRATION_ADDRESS_LOOKUP, + await useMainStore().saveRegistrationAddressLookup( { isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle, vehicleInfo: @@ -334,13 +332,7 @@ export default { false ); - await this.dispatchStoreAction( - storeActions.SAVE_EMAIL, - this.customerQuestions.emailAddress, - false - ); - await this.dispatchStoreAction( - storeActions.SAVE_SERVICE_LOCATION, + await useMainStore().saveServiceLocation( { address: this.customerQuestions.addressQuestions.streetAddress, city: this.customerQuestions.addressQuestions.city, @@ -416,7 +408,7 @@ export default { }, AlertMatchedDifferentVehicleBody() { const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`; - const vinYmmExpected = `${useMainStore().order.vehicle.year} ${useMainStore().order.vehicle.make} ${useMainStore().order.vehicle.model}`; + const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`; return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText") .replaceAll("{custom:glassText}", getDamageString()) diff --git a/src/store/index.js b/src/store/index.js index ddb2facd..211781b4 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -49,10 +49,13 @@ const getDefaultState = () => { city: null, state: null, zipCode: null, + zipCodeCtu: null }, lineItems: { glassParts: null, - otherParts: null + otherParts: null, + supportingItems: null, + vaps: null }, payment: { isInsurance: true, @@ -358,7 +361,43 @@ export const useMainStore = defineStore({ this.updateNumberOfChips(isWindshieldRepair ? parseInt(selectedWindshieldChipCount) : null); this.updateGlassToReplace(selectedGlassToReplace); } - }, + }, + + updateRegistration(registrationInfo) { + this.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate; + this.order.vehicle.registration.address = registrationInfo?.address; + this.order.vehicle.registration.city = registrationInfo?.city; + this.order.vehicle.registration.state = registrationInfo?.state; + this.order.vehicle.registration.zipCode = registrationInfo?.zipCode; + this.order.vehicle.registration.firstName = registrationInfo?.firstName; + this.order.vehicle.registration.lastName = registrationInfo?.lastName; + }, + + updateServiceLocation(serviceLocationInfo) { + this.order.serviceLocation.address = serviceLocationInfo.address; + this.order.serviceLocation.city = serviceLocationInfo.city; + this.order.serviceLocation.state = serviceLocationInfo.state; + this.order.serviceLocation.zipCode = serviceLocationInfo.zipCode; + this.order.serviceLocation.zipCodeCtu = serviceLocationInfo.zipCodeCtu; + }, + + resetRegistrationState() { + this.order.vehicle.registration.licensePlate = null; + this.order.vehicle.registration.address = null; + this.order.vehicle.registration.city = null; + this.order.vehicle.registration.state = null; + this.order.vehicle.registration.zipCode = null; + this.order.vehicle.registration.firstName = null; + this.order.vehicle.registration.lastName = null; + }, + + updateSupportingItems(partsData) { + this.order.lineItems.supportingItems = partsData; + }, + + updateVaps(partsData) { + this.order.lineItems.vaps = partsData; + }, updateVehicle(vehicle) { this.order.vehicle.carId = vehicle.carId; @@ -697,6 +736,59 @@ export const useMainStore = defineStore({ this.updateExperiments(response.data.experiments); }, + async validateZip({ zip }) { + return await globalMethods.callHttpClient({ + methods: endpoints.ValidateZip.method, + endpoint: `${endpoints.ValidateZip.url}/${zip}`, + }); + }, + + saveServiceLocation(serviceLocationInfo) { + this.updateServiceLocation(serviceLocationInfo); + }, + + saveRegistrationAddressLookup({ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) { + //Reset dependent state when changing + if + ( + registrationInfo?.address !== this.order.vehicle.registration?.address || + registrationInfo?.city !== this.order.vehicle.registration?.city || + registrationInfo?.state !== this.order.vehicle.registration?.state || + registrationInfo?.zipCode !== this.order.vehicle.registration?.zipCode || + registrationInfo?.firstName !== this.order.vehicle.registration?.firstName || + registrationInfo?.lastName !== this.order.vehicle.registration?.lastName + ) + { + this.resetRegistrationAndDependencies(); + + if (!isSelectedGlassAvailableForVehicle) { + this.resetDamageAndDependencies(); + this.resetPartsAndDependencies(); + } + + //Save new values + this.updateVehicle(vehicleInfo); + this.updateRegistration(registrationInfo); + } + }, + + resetRegistrationAndDependencies() { + this.resetRegistrationState(); + this.resetGlassPartsState(); + this.updateSupportingItems(null); + }, + + resetDamageAndDependencies() { + this.resetDamageState(); + this.resetGlassPartsState(); + this.updateSupportingItems(null); + this.updateVaps(null); + }, + + resetPartsAndDependencies() { + this.resetGlassPartsState(); + this.updateSupportingItems(null); + }, }, persist: true }); From b0bef5b5e235dd91e67f9b6c94db91d67518d9c9 Mon Sep 17 00:00:00 2001 From: Jason Wheeler Date: Wed, 11 Jan 2023 16:01:31 -0500 Subject: [PATCH 4/9] everything is converted over but it needs tested now --- src/constants/endpoints.js | 7 ++++ src/layouts/address-lookup/address-lookup.vue | 20 ++++----- .../address-questions/address-questions.vue | 7 ++-- src/router/router-constants/routing-table.js | 41 ++++++++++++++++++- src/store/index.js | 16 +++++++- 5 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index b2df065d..b469bb67 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -63,6 +63,10 @@ const endpoints = { url: "/vehicle/api/v1/vehicle/lookup", method: "POST", }, + LookupVinByAddress: { + url: "/vehicle/api/v1/vehicle/lookup-vin-by-address", + method: "POST", + }, InitializeSession: { url: "/analytics/api/v1/analytics/initialize", method: "POST", @@ -79,6 +83,9 @@ const endpoints = { url: "/location/api/v1/location/zip", method: "GET", }, + GooglePlaces: { + url: "https://maps.googleapis.com/maps/api/js?key={apiKey}&libraries=places" + } }; export { endpoints }; diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index 8558f182..761863a9 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -193,6 +193,7 @@ export default { this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); }, attachCustomEvents() { + this.prependActionToMethod(this, this.forwardButtonAction, () => { this.pushEventToGA( this.$route.query[this.queryStrings.ISS_PAGE], @@ -201,6 +202,7 @@ export default { true ); }); + }, async forwardButtonAction() { @@ -209,19 +211,13 @@ export default { // Vehicle info change in the flow, use a variable to keep track and commit to state at the end. let vehicleInfoToCommit = {}; - //Todo: Look up VIN by address - /* - const vinLookupResponse = this.dispatchStoreAction( - storeActions.LOOKUP_VIN_BY_ADDRESS, - { + const vinLookupResponse = useMainStore().lookupVinByAddress ({ licenseLastName: this.customerQuestions.lastName, licenseStreetAddress: this.customerQuestions.addressQuestions.streetAddress, licenseZip: this.customerQuestions.addressQuestions.zipCode, licenseState: this.customerQuestions.addressQuestions.state, - }, - false + } ); - */ // Settle promises and get results const promiseResultMap = [ @@ -260,7 +256,7 @@ export default { // Single VIN found const carFound = carsFound[0].vehicle; - this.isCarIdDifferent = carFound.carId !== this.mainStore.order.vehicle.carId; + this.isCarIdDifferent = carFound.carId !== useMainStore().order.vehicle.carId; if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) { // Display Alert this.previouslyEnteredCarId = carFound.carId; @@ -348,7 +344,7 @@ export default { async navigateForward(carsFound) { // Match vehicles found to vehicles in state. const matchingCars = carsFound.filter( - (car) => car.vehicle.carId === this.mainStore.order.vehicle.carId + (car) => car.vehicle.carId === useMainStore().order.vehicle.carId ); // If a different vehicle is found than the one entered and the selected glass is not available for that vehicle then navigate back to "vehicle-damage" @@ -358,7 +354,7 @@ export default { !this.isSelectedGlassAvailableForVehicle && matchingCars.length === 1 ) { - this.$router.navigateWithSaving( + this.$router.navigate( this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS, this.$route, {}, @@ -367,7 +363,7 @@ export default { } else if (matchingCars.length === 1) { await this.navigateForwardWithSingleCarMatch(); } else { - this.$router.navigateWithSaving( + this.$router.navigate( this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES, this.$route, {}, diff --git a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue index 3b05fc33..633d20bb 100644 --- a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue +++ b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue @@ -78,7 +78,8 @@ import { applicationConfig } from "@/constants/application-config.js"; import { defineRule } from "vee-validate"; import { required, regex } from "@/helpers/validation-rules"; import { errorMessages } from "@/constants/error-messages"; -import { states } from "@/constants/states" +import { states } from "@/constants/states"; +import { endpoints } from '@/constants/endpoints'; // DEFINE VALIDATION RULES defineRule("street-address-required", required(errorMessages.STREET_ADDRESS_REQUIRED)); @@ -147,10 +148,10 @@ export default { const addressField1 = document.getElementById("autocomplete"); const self = this; - const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY; + const url = endpoints.GooglePlaces.url.replace("{apiKey}", applicationConfig.GOOGLE_PLACES_API_KEY) this.$loadScript( - `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places` + url ) .then(() => { // Script is loaded, initialize the autocomplete textbox diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 3d15d67b..ac0b0d95 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -222,7 +222,44 @@ const routingTable = function(store) { destinationIssPageValue: issPageValues.QUOTE, }, ], - }, + }, + { + issPageValue: issPageValues.ADDRESS_LOOKUP, + maps: [ + { + scenario: navigationScenarios.CLICKED_BACK, + destinationIssPageValue: issPageValues.VEHICLE_LOOKUP, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES, + destinationIssPageValue: issPageValues.ADDRESS_VEHICLES, + }, + { + scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS, + destinationIssPageValue: issPageValues.VEHICLE_DAMAGE, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS, + destinationIssPageValue: issPageValues.PART_QUESTIONS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE, + destinationIssPageValue: issPageValues.VEHICLE_PARTS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS, + destinationIssPageValue: issPageValues.MOLDING_QUESTIONS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS, + destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS, + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS, + destinationIssPageValue: issPageValues.QUOTE, + }, + ], + }, { issPageValue: issPageValues.WELCOME_PAGE, maps: [ @@ -236,7 +273,7 @@ const routingTable = function(store) { } ] }, - + ]; }; diff --git a/src/store/index.js b/src/store/index.js index 211781b4..32fe6bc3 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -172,7 +172,21 @@ export const useMainStore = defineStore({ }, actions: { - // Content API Actions + // Content API Actions + + lookupVinByAddress({ licenseLastName, licenseStreetAddress, licenseZip, licenseState }) { + return globalMethods.callHttpClient({ + method: endpoints.LookupVinByAddress.method, + endpoint: endpoints.LookupVinByAddress.url, + payload: { + licenseLastName: licenseLastName, + licenseStreetAddress: licenseStreetAddress, + licenseZip: licenseZip, + licenseState: licenseState, + }, + }); + }, + getRouteInfo(pageName) { return globalMethods.callHttpClient({ method: endpoints.GetRouteInfo.method, From 73776f5f6e96a816c4abc3b0eacc15a8d9797752 Mon Sep 17 00:00:00 2001 From: Johan Gunawan Date: Wed, 11 Jan 2023 22:11:52 -0500 Subject: [PATCH 5/9] Add baseFormMixin --- src/layouts/address-lookup/address-lookup.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index 761863a9..9b87c937 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -81,6 +81,7 @@ diff --git a/src/router/router-constants/issPage-values.js b/src/router/router-constants/issPage-values.js index c8200c6a..d9ac70c4 100644 --- a/src/router/router-constants/issPage-values.js +++ b/src/router/router-constants/issPage-values.js @@ -7,6 +7,7 @@ export const issPageValues = { VEHICLE_DAMAGE: "vehicle-damage", VEHICLE_LOOKUP: "vehicle-lookup", ADDRESS_LOOKUP: "address-lookup", + ADDRESS_VEHICLES: "address-vehicles", LICENSE_PLATE_LOOKUP: "license-plate-lookup", VIN_LOOKUP: "vin-lookup", VEHICLE_PARTS: "vehicle-parts", From ac1bad19ad330b5ed03e5359c0875f1ed8b61478 Mon Sep 17 00:00:00 2001 From: Jason Wheeler Date: Mon, 16 Jan 2023 11:21:52 -0500 Subject: [PATCH 9/9] everything seems to be working, still need to update tests --- src/layouts/address-lookup/address-lookup.vue | 2 +- src/store/index.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index b4af4dc2..05e50102 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -12,7 +12,7 @@ ref="vehicleBanner" :displayGenericVehicleImage="false" /> -
+