diff --git a/src/layouts/address-lookup/address-lookup.spec.js b/src/layouts/address-lookup/address-lookup.spec.js index 7fb064b00..77f154e45 100644 --- a/src/layouts/address-lookup/address-lookup.spec.js +++ b/src/layouts/address-lookup/address-lookup.spec.js @@ -38,7 +38,14 @@ describe("address-lookup.vue", () => { } const { wrapper } = setupMocks({ - isZipServiceable: false + isZipValid: true, + isZipServiceable: false, + vinVehicles: [{ + vin: "TEST_VIN", + vehicle: { + carId: "C0000" + } + }] }); store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); @@ -54,6 +61,7 @@ describe("address-lookup.vue", () => { // Assert expect(wrapper.findComponent({ ref: "alertNonServiceableZip" }).isVisible()).toBe(true); + }); test("if the address matches a different vehicle display the Matched Different VehicleAlert", async () => { @@ -462,7 +470,14 @@ describe("address-lookup.vue", () => { } const { wrapper } = setupMocks({ - isZipServiceable: false + isZipValid: true, + isZipServiceable: false, + vinVehicles: [{ + vin: "TEST_VIN", + vehicle: { + carId: "C0000" + } + }] }); store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); @@ -612,13 +627,14 @@ describe("address-lookup.vue", () => { }); }); -function setupMocks({ isZipServiceable = true, lookupVinbyAddressResponse, partsOrQuestions = [], isStatePermissible = true, vinVehicles =[], carId = 'C0000'}) { +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 } }, @@ -667,7 +683,8 @@ function setupMocks({ isZipServiceable = true, lookupVinbyAddressResponse, parts })); const apiResponses = { - serviceZipValidationResponse:{ + serviceZipValidationResponse: { + isValid: isZipValid, isServiceable: isZipServiceable }, vinLookupResponse: { diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index 74ebd43de..394eb0cc8 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -7,15 +7,42 @@
- - - - - - - - - + + + + +
@@ -42,20 +69,21 @@ import alert from "@/ux-components/alert/alert"; import textboxQuestion from "@/common-components/textbox-question/textbox-question"; import loadingModal from '@/common-components/loading-modal/loading-modal.vue'; -import {Form,defineRule} from "vee-validate"; -import {required,regex} from "@/helpers/validation-rules"; -import {errorMessages} from "@/constants/error-messages"; +import { Form, defineRule } from "vee-validate"; +import { required, regex } from "@/helpers/validation-rules"; +import { errorMessages } from "@/constants/error-messages"; // Supporting files -import {fetchCmsContentForPage} from "@/helpers/cms-content-helper"; -import {settleAllPromises} from "@/helpers/layout-helper"; -import {storeActions} from "@/constants/store-actions"; -import {routerParams} from "@/router/router-constants/router-params"; -import {getDamageString,isGlassAvailableForCarId} from "@/helpers/damage-helper"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { settleAllPromises } from "@/helpers/layout-helper"; +import { storeActions } from "@/constants/store-actions"; +import { routerParams } from "@/router/router-constants/router-params"; +import { getDamageString, isGlassAvailableForCarId} from "@/helpers/damage-helper"; import store from "@/store"; import vinPagesMixin from "@/mixins/vin-pages-mixin"; +// DEFINE VALIDATION RULES - Note: Additional rules are defined in Customer Questions and Address Questions components defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED)); defineRule("service-zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT)); @@ -98,8 +126,10 @@ export default { displayMatchedDifferentVehicleAlert: false, displayVinLookupByHomeAddressNotAllowedAlert: false, previouslyEnteredCarId: "", + isCarIdDifferent: false, isSelectedGlassAvailableForVehicle: false, customAlertData: {}, + displayInvalidZipAlert: false, showServiceZipField: this.getServiceZipFromStore(), isZipServiceable: false, } @@ -171,44 +201,38 @@ 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}) + this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { zip: this.serviceZipCode }) : + this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { zip: this.customerQuestions.addressQuestions.zipCode }) } ]; const resultMap = await settleAllPromises(promiseResultMap); - - // Verify if the service zip code or registration zip code provided is serviceable + // If VIN Lookup by address is forbidden by State Restrictions then show an alert if (!resultMap.vinLookupResponse.isStatePermissible) { // State Restrictions forbid lookup by address this.displayVinLookupByHomeAddressNotAllowedAlert = true; return this.$refs.funnelFooter.removeLoader(); } - // If the neither the registration zip code or service zip code are not serviceable - this.isZipServiceable = resultMap.serviceZipValidationResponse.isServiceable; - if (!this.isZipServiceable) { - this.displayNonServiceableZipAlert = true; - this.showServiceZipField = true; - return this.$refs.funnelFooter.removeLoader(); - } - - // If the registration zip code is serviceable and nothing was entered for the service zip code - // then set the service zip code to the registration zip code - if (!this.serviceZipCode) { - this.serviceZipCode = this.customerQuestions.addressQuestions.zipCode; - } + // If a Service Zip is entered and it is an invalid zip code (ex. 11111) then show an alert + const isZipValid = resultMap.serviceZipValidationResponse.isValid; + if (this.serviceZipCode && !isZipValid) { + this.displayInvalidZipAlert = true; + return this.$refs.funnelFooter.removeLoader(); + } + this.displayInvalidZipAlert = false; const carsFound = resultMap.vinLookupResponse.vinVehicles; // Handle cases for different amounts of VINS found for the address. if (carsFound.length == 1) { - // Single VIN found const carFound = carsFound[0].vehicle; this.isCarIdDifferent = carFound.carId !== this.$store.getters.vehicle.carId; - +console.log(this.isCarIdDifferent); +console.log(carFound.carId); +console.log(this.$store.getters.vehicle.carId); if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) { // Display Alert this.previouslyEnteredCarId = carFound.carId; @@ -220,21 +244,13 @@ export default { // Update button "Continue with..." this.$refs.funnelFooter.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`); return this.$refs.funnelFooter.removeLoader(); - } - if (!this.isZipServiceable) { - return; } // update data if the zip or service zip is serviceable vehicleInfoToCommit = Object.assign(carFound, { vin: carsFound[0].vin }); + } else if (carsFound.length > 1) { - - // Multiple VINS found - if (!this.isZipServiceable) { - return; - } - // If multiple cars were found and one and only one of them matches the carId entered, save the vehicle info // so we can go to the Heritage Funnel directly const matchingCars = carsFound.filter(vin => vin.vehicle.carId === this.$store.getters.vehicle.carId); @@ -242,11 +258,27 @@ export default { if (matchingCars.length === 1) { vehicleInfoToCommit = Object.assign(matchingCars[0].vehicle, {vin: matchingCars[0].vin}); } - } else { + } else { // No VINS found. + console.log("no vins"); this.displayVinNotFoundAlert = true; return this.$refs.funnelFooter.removeLoader(); + + } + + // If the either the registration zip code or service zip code are not serviceable + this.isZipServiceable = resultMap.serviceZipValidationResponse.isServiceable; + if (!this.isZipServiceable) { + this.displayNonServiceableZipAlert = true; + this.showServiceZipField = true; + return this.$refs.funnelFooter.removeLoader(); + } + + // If the registration zip code is serviceable and nothing was entered for the service zip code + // then set the service zip code to the registration zip code + if (!this.serviceZipCode) { + this.serviceZipCode = this.customerQuestions.addressQuestions.zipCode; } // Save vehicle, customer, service and registration information @@ -272,6 +304,7 @@ export default { }, false); return await this.navigateForward(carsFound); + }, async navigateForward(carsFound) { // Match vehicles found to vehicles in state. @@ -279,7 +312,6 @@ export default { // 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" // display vehicle changed alert on that page. - if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle && matchingCars.length === 1) { this.$router.navigate(this.navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, this.$route, {}, {[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true}); } else if (matchingCars.length === 1) { @@ -287,12 +319,14 @@ export default { } else { this.$router.navigate(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, this.$route, {}, {}, carsFound); } + }, resetWarningsAndErrors() { this.displayVinNotFoundAlert = false; this.displayNonServiceableZipAlert = false; this.displayMatchedDifferentVehicleAlert = false; this.displayVinLookupByHomeAddressNotAllowedAlert = false; + }, }, mounted() { diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js index b1150e5cf..2e83c3103 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js +++ b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js @@ -312,7 +312,7 @@ describe("license-plate-lookup.vue", () => { //Act await wrapper.setData({ - registrationZip: "55555" + registrationZipCode: "55555" }) wrapper.vm.getCmsContent = jest.fn(); await wrapper.vm.$nextTick(); @@ -328,7 +328,7 @@ describe("license-plate-lookup.vue", () => { //Act await wrapper.setData({ - serviceZip: "55555" + serviceZipCode: "55555" }) wrapper.vm.getCmsContent = jest.fn(); await wrapper.vm.$nextTick(); @@ -344,9 +344,17 @@ describe("license-plate-lookup.vue", () => { const { wrapper } = setupMocks({}); wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); - await wrapper.setData({ registrationZip: "00000" }); + await wrapper.setData({ registrationZipCode: "00000" }); navigateToHeritage.navigateToHeritageFunnel = jest.fn(); + wrapper.vm.dispatchStoreAction = jest.fn().mockImplementation(() => Promise.resolve({ + data: { + vehicle: { + carId: "C00000" + } + } + })); + // Act await wrapper.vm.forwardButtonAction(); @@ -366,11 +374,19 @@ describe("license-plate-lookup.vue", () => { await wrapper.setData({ registrationZip: "00000" }); navigateToHeritage.navigateToHeritageFunnel = jest.fn(); + wrapper.vm.dispatchStoreAction = jest.fn().mockImplementation(() => Promise.resolve({ + data: { + vehicle: { + carId: "C00000" + } + } + })); + // Act await wrapper.vm.forwardButtonAction(); // Assert - const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZip']"); + const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZipQuestionWidget']"); expect(serviceZipField.exists()).toBe(true); expect(serviceZipField.isVisible()).toBe(true); }) @@ -382,8 +398,17 @@ describe("license-plate-lookup.vue", () => { return { data: { isServiceable: false, state: "XX" } }; }); - await wrapper.setData({ registrationZip: "00000" }); + await wrapper.setData({ registrationZipCode: "00000" }); navigateToHeritage.navigateToHeritageFunnel = jest.fn(); + + wrapper.vm.dispatchStoreAction = jest.fn().mockImplementation(() => Promise.resolve({ + data: { + vehicle: { + carId: "C00000" + } + } + })); + await wrapper.vm.forwardButtonAction(); wrapper.vm.$router.navigate = jest.fn(); // At this point, serviceZip field is shown @@ -393,7 +418,7 @@ describe("license-plate-lookup.vue", () => { await wrapper.vm.forwardButtonAction(); // Assert - const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZip']"); + const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZipQuestionWidget']"); expect(serviceZipField.exists()).toBe(true); expect(serviceZipField.isVisible()).toBe(true); 3 expect(navigateToHeritage.navigateToHeritageFunnel).not.toHaveBeenCalled(); @@ -415,11 +440,11 @@ describe("license-plate-lookup.vue", () => { } })); - await wrapper.setData({ registrationZip: registrationZip }); + await wrapper.setData({ registrationZipCode: registrationZip }); await wrapper.vm.forwardButtonAction(); // At this point, serviceZip field is shown - await wrapper.setData({ serviceZip: serviceZip }); + await wrapper.setData({ serviceZipCode: serviceZip }); // Act @@ -427,7 +452,7 @@ describe("license-plate-lookup.vue", () => { await wrapper.vm.forwardButtonAction(); // Assert - const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZip']"); + const serviceZipField = wrapper.findComponent("[cmsWidgetName='ServiceZipQuestionWidget']"); expect(serviceZipField.exists()).toBe(true); expect(serviceZipField.isVisible()).toBe(true); }); @@ -447,7 +472,7 @@ describe("license-plate-lookup.vue", () => { } })); - await wrapper.setData({ registrationZip: registrationZip }); + await wrapper.setData({ registrationZipCode: registrationZip }); await wrapper.vm.forwardButtonAction(); // At this point, serviceZip field is shown @@ -512,6 +537,7 @@ function setupMocks({ }, }, serviceZipValidationResponse: { + isValid: true, isServiceable: isServiceable }, registrationZipValidationResponse: { diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue index 3e9240719..0db677496 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.vue +++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue @@ -17,7 +17,7 @@
+
{ @@ -159,46 +155,33 @@ export default { }, data() { return { - isRegistrationZipServiceable: true, - isVinValid: true, - isCarIdDifferent: false, licensePlate: this.getLicensePlateFromStore(), - registrationZip: this.getRegistrationZipFromStore(), - email: this.getEmailFromStore(), - serviceZip: this.getServiceZipFromStore(), + registrationZipCode: this.getRegistrationZipFromStore(), + email: this.getEmailFromStore(), + serviceZipCode: this.getServiceZipFromStore(), + displayNonServiceableZipAlert: false, + displayVinNotFoundAlert: false, + displayMatchedDifferentVehicleAlert: false, previouslyEnteredCarId: "", + isSelectedGlassAvailableForVehicle: false, + isCarIdDifferent: false, customAlertData: {}, - isSelectedGlassAvailableForVehicle: true, - zipToDisplay: this.getRegistrationZipFromStore(), + displayInvalidZipAlert: false, + showServiceZipField: this.getServiceZipFromStore(), + isZipServiceable: false, }; }, - mounted() { - this.attachCustomEvents(); - }, - computed: { - MatchedDifferentVehicleAlertHeader() { - return this.getCmsContent("MatchedDifferentVehicleAlertWidget","HeadlineText").replaceAll("{custom:damage}", getDamageString()); - }, - MatchedDifferentVehicleAlertBody() { - return this.getCmsContent("MatchedDifferentVehicleAlertWidget","BodyText") - .replaceAll("{custom:damage}", getDamageString()) - .replaceAll("{custom:plateLookupYear}",this.customAlertData?.vehicleInfo?.year) - .replaceAll("{custom:plateLookupMake}",this.customAlertData?.vehicleInfo?.make) - .replaceAll("{custom:plateLookupModel}",this.customAlertData?.vehicleInfo?.model); - }, - NoServiceZipHeader() { - return this.getCmsContent("NoServiceZipWidget","HeadlineText") - .replaceAll("{custom:zip}", this.zipToDisplay); - - }, - NoServiceZipBody() { - return this.getCmsContent("NoServiceZipWidget", "BodyText"); - }, - }, methods: { arePagePrerequisitesValid() { return store.getters.vehicle.carId !== null; }, + backButtonAction() { + // route to move backwards + this.$router.navigate( + this.navigationScenarios.CLICKED_BACK, + this.$route + ); + }, attachCustomEvents() { this.prependActionToMethod(this, this.forwardButtonAction, () => { this.pushEventToGA( @@ -221,11 +204,10 @@ export default { getServiceZipFromStore() { return this.$store.getters.order.serviceLocation.zipCode; }, - backButtonAction() { - this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); - }, async forwardButtonAction() { - const registrationZipValidationResponse = this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.registrationZip }); + this.resetWarningsAndErrors(); + + const registrationZipValidationResponse = this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { zip: this.registrationZipCode }); // Settle promises and get results const promiseResultMap = [ @@ -235,73 +217,121 @@ export default { }, { resultKey: "serviceZipValidationResponse", - promise: this.serviceZip ? this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.serviceZip }) : registrationZipValidationResponse, + promise: this.serviceZipCode ? this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { zip: this.serviceZipCode }) : registrationZipValidationResponse, } ]; const resultMap = await settleAllPromises(promiseResultMap); + + // Lookup vin + const vinLookup = await this.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_PLATE, {licensePlate: this.licensePlate, licenseState: resultMap.registrationZipValidationResponse.state}, false) + .catch(() => { + // No VIN found. + this.displayVinNotFoundAlert = true; + return this.$refs.funnelFooter.removeLoader(); - //Handle service zip validations - if (!resultMap.serviceZipValidationResponse.isServiceable) { - this.isVinValid = true; - this.isRegistrationZipServiceable = false; - this.isCarIdDifferent = false; - this.zipToDisplay = this.serviceZip ? this.serviceZip : this.registrationZip; - return this.$refs.funnelFooter.removeLoader(); - } - - if (!this.serviceZip) { - this.serviceZip = this.registrationZip; + }); + // If no VIN was found, stop processing after displaying alert + if (!vinLookup) { + return; } - //Lookup vin - const vinLookup = await this.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_PLATE, {licensePlate: this.licensePlate, licenseState: resultMap.registrationZipValidationResponse.state}, false) - .catch(() => { - this.isVinValid = false; - this.isCarIdDifferent = false; + // If a Service Zip is entered and it is an invalid zip code (ex. 11111) then show an alert + const isZipValid = resultMap.serviceZipValidationResponse.isValid; + if (this.serviceZipCode && !isZipValid) { + this.displayInvalidZipAlert = true; return this.$refs.funnelFooter.removeLoader(); - }); + } + this.displayInvalidZipAlert = false; // Check if the CarId has changed. this.isCarIdDifferent = vinLookup.data.vehicle.carId !== this.$store.getters.vehicle.carId; - //Handle changing car + // Handle changing car if (this.isCarIdDifferent && vinLookup.data.vehicle.carId !== this.previouslyEnteredCarId) { - this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.vehicle.carId); - this.$refs.funnelFooter.updateButtonText(`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`); - + // Display Alert this.previouslyEnteredCarId = vinLookup.data.vehicle.carId; this.customAlertData.vehicleInfo = vinLookup.data.vehicle; - this.isVinValid = true; + this.displayMatchedDifferentVehicleAlert = true; + this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.vehicle.carId); + + // Update button "Continue with..." + this.$refs.funnelFooter.updateButtonText(`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`); + return this.$refs.funnelFooter.removeLoader(); + + } + + // If the either the registration zip code or service zip code are not serviceable + this.isZipServiceable = resultMap.serviceZipValidationResponse.isServiceable; + if (!this.isZipServiceable) { + this.displayNonServiceableZipAlert = true; + this.showServiceZipField = true; return this.$refs.funnelFooter.removeLoader(); } - // Save vin, vehicle, customer, service and registration information - await this.dispatchStoreAction(storeActions.SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP, { - isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle, - vehicleInfo: Object.assign(vinLookup.data.vehicle, { vin: vinLookup.data.vin }), - registrationInfo: { - licensePlate: this.licensePlate, - state: resultMap.registrationZipValidationResponse.state, - zipCode: this.registrationZip, - } - }, false); + // If the registration zip code is serviceable and nothing was entered for the service zip code + // then set the service zip code to the registration zip code + if (!this.serviceZipCode) { + this.serviceZipCode = this.registrationZipCode; + } - await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.email, false); - await this.dispatchStoreAction(storeActions.SAVE_SERVICE_LOCATION, { - zipCode: this.serviceZip, - state: resultMap.serviceZipValidationResponse.state, - }, false); + // Save vin, vehicle, customer, service and registration information + await this.dispatchStoreAction(storeActions.SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP, { + isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle, + vehicleInfo: Object.assign(vinLookup.data.vehicle, { vin: vinLookup.data.vin }), + registrationInfo: { + licensePlate: this.licensePlate, + state: resultMap.registrationZipValidationResponse.state, + zipCode: this.registrationZipCode, + } + }, false); + + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.email, false); + await this.dispatchStoreAction(storeActions.SAVE_SERVICE_LOCATION, { + zipCode: this.serviceZipCode, + state: resultMap.serviceZipValidationResponse.state, + }, false); return await this.navigateForward(); + }, async navigateForward() { if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) { - this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,this.$route,{}, {[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }); + this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }); } else { await this.navigateForwardWithSingleCarMatch(); } + + }, + resetWarningsAndErrors() { + this.displayVinNotFoundAlert = false; + this.displayNonServiceableZipAlert = false; + this.displayMatchedDifferentVehicleAlert = false; + this.displayVinLookupByHomeAddressNotAllowedAlert = false; + + }, + }, + mounted() { + this.attachCustomEvents(); + }, + computed: { + AlertNonServiceableZipHeader() { + const zipCode = this.serviceZipCode ? this.serviceZipCode : this.registrationZipCode; + return this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zipCode); + }, + AlertNonServiceableZipBody() { + return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText"); + }, + AlertMatchedDifferentVehicleHeader() { + return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:damage}", getDamageString()); + }, + AlertMatchedDifferentVehicleBody() { + return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText") + .replaceAll("{custom:damage}", getDamageString()) + .replaceAll("{custom:plateLookupYear}", this.customAlertData?.vehicleInfo?.year) + .replaceAll("{custom:plateLookupMake}", this.customAlertData?.vehicleInfo?.make) + .replaceAll("{custom:plateLookupModel}", this.customAlertData?.vehicleInfo?.model); }, }, watch: { @@ -310,26 +340,28 @@ export default { this.getCmsContent("FunnelFooterWidget", "ForwardButtonText") ); }, - registrationZip() { + registrationZipCode() { this.$refs.funnelFooter.updateButtonText( this.getCmsContent("FunnelFooterWidget", "ForwardButtonText") ); }, - serviceZip() { + serviceZipCode() { + // If they modify the service zip code, then hide the error message. + this.displayNonServiceableZipAlert = false; this.$refs.funnelFooter.updateButtonText( this.getCmsContent("FunnelFooterWidget", "ForwardButtonText") ); }, }, components: { - Form, funnelHeader, + funnelFooter, vehicleBanner, funnelSubHeader, textboxQuestion, - alert, - funnelFooter, - loadingModal, + alert, + loadingModal, + Form }, }; diff --git a/src/layouts/vin-lookup/vin-lookup.spec.js b/src/layouts/vin-lookup/vin-lookup.spec.js index 241619942..d71b1fd1f 100644 --- a/src/layouts/vin-lookup/vin-lookup.spec.js +++ b/src/layouts/vin-lookup/vin-lookup.spec.js @@ -224,7 +224,8 @@ function setupMocks({ customMountOptions }) { function mockOutPromises(carId = 'C00000') { const apiResponses = { - validateZipResponse: { + serviceZipValidationResponse: { + isValid: true, isServiceable: true }, vehicleLookupResponse: { diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index fef6b0a68..371004dd5 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -6,18 +6,15 @@ v-slot="{ meta }" >
- + - +
+ 0, - isSelectedGlassAvailableForVehicle: true + isSelectedGlassAvailableForVehicle: false, + displayInvalidZipAlert: false, + displayNonServiceableZipAlert: false, + displayVinNotFoundAlert: false, + displayMatchedDifferentVehicleAlert: false, }; }, - mounted() { - this.attachCustomEvents(); - }, - watch: { - vin() { - this.vinNotFound = false; - this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")); - }, - zip() { - this.noServiceZip = false; - }, - }, - computed: { - MatchedDifferentVehicleAlertHeader(){ - const text = this.getCmsContent("MatchedDifferentVehicle", - "HeadlineText").replaceAll("{custom:damage}", getDamageString()); - - return text; - }, - MatchedDifferentVehicleAlertBody(){ - const text = this.getCmsContent("MatchedDifferentVehicle", - "BodyText").replaceAll("{custom:damage}", getDamageString()).replaceAll("{custom:vinlookupYear}", this.customAlertData?.vehicleInfo?.year).replaceAll("{custom:vinlookupMake}", this.customAlertData?.vehicleInfo?.make).replaceAll("{custom:vinlookupModel}", - this.customAlertData?.vehicleInfo?.model); - - return text; - }, - NoServiceZipHeader(){ - const text = this.getCmsContent("NoServiceZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", this.invalidZip); - return text; - }, - NoServiceZipBody(){ - return this.getCmsContent("NoServiceZipWidget", "BodyText"); - }, - PerfectMatchInsuranceNotVerifiedAlertHeader() { - return this.getCmsContent("PerfectMatchInsuranceNotVerifiedAlert", "HeadlineText"); - }, - PerfectMatchInsuranceNotVerifiedAlertBody() { - return this.getCmsContent("PerfectMatchInsuranceNotVerifiedAlert", "BodyText").replaceAll("{custom:damage}", - getDamageString()) - }, - PerfectMatchInsuranceVerifiedAlertHeader () { - return this.getCmsContent("PerfectMatchInsuranceVerifiedAlert", "HeadlineText"); - }, - PerfectMatchInsuranceVerifiedAlertBody () { - return this.getCmsContent("PerfectMatchInsuranceVerifiedAlert", "BodyText").replaceAll("{custom:damage}", - getIsWindshieldOnly()) - }, - isInsuranceVerified() { - return store.getters.payment.insuranceCoverage.isVerified || getFunnelCookie().HasDelayedClaimRegistration; - }, - vinMask() { - if (this.vinPopulatedOnPageLoad) { - const lastSixChars = this.vin.substring(11, this.vin.length); - return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`; - } - else { - return 'XXXXXXXXXXXXXXXXX'; - } - }, - }, methods: { arePagePrerequisitesValid() { return store.getters.vehicle.carId !== null; @@ -262,11 +207,7 @@ export default { true ); }); - }, - updateIsCarIdDifferent(isVinPerfectMatch){ - if (isVinPerfectMatch) { - this.isCarIdDifferent = false; - } + }, backButtonAction() { if (this.$store.getters.vehicle.vin) { @@ -275,18 +216,19 @@ export default { else { this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); } + }, async forwardButtonAction() { // If this is a new VIN Lookup, do both a Vehicle Lookup and a Zip Validation if (!this.vinPopulatedOnPageLoad) { - const validateZipResponse = this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.zip}); + const serviceZipValidationResponse = this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { zip: this.serviceZipCode }); const vehicleLookupResponse = this.dispatchStoreAction(storeActions.LOOKUP_VEHICLE_BY_VIN, { vin: this.vin }); // Settle promises and get results const promiseResultMap = [ { - resultKey: "validateZipResponse", - promise: validateZipResponse, + resultKey: "serviceZipValidationResponse", + promise: serviceZipValidationResponse, }, { resultKey: "vehicleLookupResponse", @@ -295,38 +237,46 @@ export default { ]; const resultMap = await settleAllPromises(promiseResultMap); + + // If a Service Zip is entered and it is an invalid zip code (ex. 11111) then show an alert + const isZipValid = resultMap.serviceZipValidationResponse.isValid; + if (this.serviceZipCode && !isZipValid) { + this.displayInvalidZipAlert = true; + return this.$refs.funnelFooter.removeLoader(); + } + this.displayInvalidZipAlert = false; // If either lookup fails, remove the loader and stop processing the page. - if (!resultMap.vehicleLookupResponse || !resultMap.validateZipResponse.isServiceable) { + if (!resultMap.vehicleLookupResponse || !resultMap.serviceZipValidationResponse.isServiceable) { + // If the vehicle result is undefined, the vin entered was invalid. + if(!resultMap.vehicleLookupResponse) { + this.displayVinNotFoundAlert = true; + } - // If the vehicle result is undefined, the vin entered was invalid. - if(!resultMap.vehicleLookupResponse) { - this.vinNotFound = true; - } + // Check if Service Zip entered is serviceable, if not display an alert + if (!resultMap.serviceZipValidationResponse.isServiceable) { + this.displayNonServiceableZipAlert = true; + } - // Check if Service Zip entered is serviceable, if not display an alert - if (!resultMap.validateZipResponse.isServiceable) { - this.setupUiForNonServiceableZip(this.zip); - } + // Remove loader and stop processing the page. + return this.$refs.funnelFooter.removeLoader(); - // Remove loader and stop processing the page. - return this.$refs.funnelFooter.removeLoader(); } - // Check if the CarId is different from the lookup vs what is in state currently. this.isCarIdDifferent = resultMap.vehicleLookupResponse.carId !== this.$store.getters.vehicle.carId; if (this.isCarIdDifferent && (resultMap.vehicleLookupResponse.carId !== this.previouslyEnteredCarId)) { - this.previouslyEnteredCarId = resultMap.vehicleLookupResponse.carId; this.customAlertData.vehicleInfo = resultMap.vehicleLookupResponse; - this.$refs.funnelFooter.updateButtonText(`Continue with ${resultMap.vehicleLookupResponse.year} ${resultMap.vehicleLookupResponse.make} ${resultMap.vehicleLookupResponse.model}`); + this.displayMatchedDifferentVehicleAlert = true; + this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(resultMap.vehicleLookupResponse.carId); - this.noServiceZip = false; - this.isVinValid = true; + // Update button "Continue with..." + this.$refs.funnelFooter.updateButtonText(`Continue with ${resultMap.vehicleLookupResponse.year} ${resultMap.vehicleLookupResponse.make} ${resultMap.vehicleLookupResponse.model}`); return this.$refs.funnelFooter.removeLoader(); + } // Save vin, vehicle, customer and service information @@ -335,62 +285,113 @@ export default { vehicleInfo: Object.assign(resultMap.vehicleLookupResponse, { vin: this.vin }) }, false); - await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.email, false); + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false); await this.dispatchStoreAction(storeActions.SAVE_SERVICE_LOCATION, { - zipCode: this.zip, - state: resultMap.validateZipResponse.state, + zipCode: this.serviceZipCode, + state: resultMap.serviceZipValidationResponse.state, }, false); return await this.navigateForward(); + } // If a VIN has already been found. Validate the Service Zip (in case of changes) - const zipValidationResponse = await this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.zip}); + const zipValidationResponse = await this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.serviceZipCode}); // Check if Service Zip entered is serviceable if (zipValidationResponse.data.isServiceable) { - // If the Service Zip entered is serviceable then save the Zip Info and Email Address and navigate forward - if (this.$store.getters.order.serviceLocation.zipCode != this.zip) { + if (this.$store.getters.order.serviceLocation.zipCode != this.serviceZipCode) { await this.dispatchStoreAction(storeActions.SAVE_SERVICE_LOCATION, { - zipCode: this.zip, + zipCode: this.serviceZipCode, state: zipValidationResponse.data.state }, false); } - await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.email, false); + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false); return await this.navigateForward(); + } // If the Service Zip is NOT serviceable then show an alert - this.setupUiForNonServiceableZip(this.zip); + this.displayNonServiceableZipAlert = true; return this.$refs.funnelFooter.removeLoader(); + }, async navigateForward(){ - if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) { - this.$router.navigate(this.navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, this.$route, {}, { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }); - } else { - await this.navigateForwardWithSingleCarMatch(); - } + if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) { + this.$router.navigate(this.navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, this.$route, {}, { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }); + } else { + await this.navigateForwardWithSingleCarMatch(); + } + }, - setupUiForNonServiceableZip(zip) { - this.customAlertData.zip = zip; - this.invalidZip = zip; - this.noServiceZip = true; + }, + mounted() { + this.attachCustomEvents(); + }, + computed: { + AlertMatchedDifferentVehicleHeader(){ + return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:damage}", getDamageString()); + }, + AlertMatchedDifferentVehicleBody(){ + return this.getCmsContent("AlertMatchedDifferentVehicleWidget", + "BodyText").replaceAll("{custom:damage}", getDamageString()).replaceAll("{custom:vinlookupYear}", this.customAlertData?.vehicleInfo?.year).replaceAll("{custom:vinlookupMake}", this.customAlertData?.vehicleInfo?.make).replaceAll("{custom:vinlookupModel}", + this.customAlertData?.vehicleInfo?.model); + }, + AlertNonServiceableZipHeader(){ + return this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", this.serviceZipCode); + }, + AlertNonServiceableZipBody(){ + return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText"); + }, + AlertPerfectMatchInsuranceNotVerifiedHeader() { + return this.getCmsContent("AlertPerfectMatchInsuranceNotVerified", "HeadlineText"); + }, + AlertPerfectMatchInsuranceNotVerifiedBody() { + return this.getCmsContent("AlertPerfectMatchInsuranceNotVerified", "BodyText").replaceAll("{custom:damage}", getDamageString()) + }, + AlertPerfectMatchInsuranceVerifiedHeader () { + return this.getCmsContent("AlertPerfectMatchInsuranceVerified", "HeadlineText"); + }, + AlertPerfectMatchInsuranceVerifiedBody () { + return this.getCmsContent("AlertPerfectMatchInsuranceVerified", "BodyText").replaceAll("{custom:damage}", + getIsWindshieldOnly()) + }, + isInsuranceVerified() { + return store.getters.payment.insuranceCoverage.isVerified || getFunnelCookie().HasDelayedClaimRegistration; + }, + vinMask() { + if (this.vinPopulatedOnPageLoad) { + const lastSixChars = this.vin.substring(11, this.vin.length); + return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`; + } + else { + return 'XXXXXXXXXXXXXXXXX'; + } + }, + }, + watch: { + vin() { + this.displayVinNotFoundAlert = false; + this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")); + }, + serviceZipCode() { + this.displayNonServiceableZipAlert = false; }, }, components: { - Form, funnelHeader, + funnelFooter, vehicleBanner, funnelSubHeader, textboxQuestion, - alert, - funnelFooter, + alert, vinInformation, loadingModal, + Form, }, };