Checking in, most save and navigation logic in place may need tweaks

This commit is contained in:
Leah Schumann 2022-04-28 10:22:43 -04:00
parent 14f6174a76
commit 624bf4501b
6 changed files with 206 additions and 72 deletions

View file

@ -9,32 +9,38 @@
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage=false />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
<customerQuestions ref="customerQuestions" v-model="customerQuestions" @change="addressChanged" />
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
<alert ref="alertVinNotFound" v-show="displayVinNotFoundAlert"
class="my-3"
cmsWidgetName="AlertVinNotFoundWidget"
alertClass="alert-danger"
v-bind:isDismissible="false"
/>
<alert ref="alertMatchedDifferentVehicle" v-show="displayMatchedDifferentVehicleAlert"
cmsWidgetName="AlertMatchedDifferentVehicleWidget"
alertClass="alert-danger"
class="my-3"
:manualHeadline="AlertMatchedDifferentVehicleHeader"
:manualCopy="AlertMatchedDifferentVehicleBody"
alertClass="alert-warning"
v-bind:isDismissible="false"
/>
<alert ref="alertNonServiceableZip" v-show="displayNonServiceableZipAlert"
cmsWidgetName="AlertNonServiceableZipWidget"
class="my-3"
alertClass="alert-danger"
:manualHeadline="AlertNonServiceableZipHeader"
:manualCopy="AlertNonServiceableZipBody"
v-bind:isDismissible="false"
/>
<alert ref="alertVinLookupsByHomeAddressNotAllowed" v-show="displayVinLookupByHomeAddressNotAllowedAlert"
class="my-3"
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
alertClass="alert-danger"
v-bind:isDismissible="false"
/>
<transition name="fade" mode="out-in">
<div class="service-zip-field" v-show="showServiceZipField" aria-live="polite">
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
<div class="row my-4">
<div class="col">
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZip" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" disableAutoFill validationRules="street-address-required" />
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZip" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" mask="#####" disableAutoFill validationRules="service-zip-required|service-zip-format" />
</div>
</div>
</div>
@ -59,6 +65,9 @@ import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
import alert from "@/ux-components/alert/alert";
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
import { Form } from "vee-validate";
import { defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
@ -72,6 +81,8 @@ import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import baseMixin from "@/mixins/base-mixin";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { getDamageString, compareGlassOptions } from "@/helpers/damage-helper";
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
defineRule("service-zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
@ -110,7 +121,13 @@ export default {
lastName: "",
emailAddress: "",
},
serviceZip: "",
serviceZip: "",
displayNonServiceableZipAlert: false,
displayVinNotFoundAlert: false,
displayMatchedDifferentVehicleAlert: false,
displayVinLookupByHomeAddressNotAllowedAlert: false,
previousCarIdFound: "",
customAlertData: {},
}
},
methods: {
@ -129,14 +146,9 @@ export default {
);
},
async forwardButtonAction() {
this.resetWarningsAndErrors();
// Validate if the original zip provided is serviceable
const zipValidation = this.serviceZip ? await this.validateZip(this.serviceZip) : await this.validateZip(this.customerQuestions.addressQuestions.zip);
if (!zipValidation.data.isServiceable) {
this.displayNonServiceableZipAlert = true;
}
// Look-up VIN by address
// Lookup VIN(s) with the provided address
const vinLookup = await this.lookupVin(
this.customerQuestions.lastName,
this.customerQuestions.addressQuestions.streetAddress,
@ -144,50 +156,108 @@ export default {
this.customerQuestions.addressQuestions.state
);
// Lookup VIN(s) with the provided address
if (vinLookup.vinVehicles.length == 0) {
// No VINs found
this.displayVinNotFoundAlert = true;
} else if (!vinLookup.isStatePermissable) {
if (!vinLookup.data.isStatePermissible) {
// State Restrictions forbid lookup by address
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
} else if (vinLookup.vinVehicles.length == 1) {
// Car found does not match entered carId
if (vinLookup.data.vehicle.carId !== store.getters.vehicle.carId) {
// Alert Copy changes ("We found a <...>")
this.$refs.funnelFooter.updateButtonText(`Continue with ${vinLookup.data.vin} ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`);
this.displayMatchedDifferentVehicleAlert = true;
}
} else if (vinLookup.vinVehicles.length > 1) {
this.$refs.funnelFooter.removeLoader();
return;
}
// Validate if the original or service zip provided is serviceable
const zipValidation = this.serviceZip ? await this.validateZip(this.serviceZip) : await this.validateZip(this.customerQuestions.addressQuestions.zip);
if (!zipValidation.data.isServiceable) {
this.displayNonServiceableZipAlert = true;
this.showServiceZipField = true;
this.$refs.funnelFooter.removeLoader();
}
const carEntered = store.getters.vehicle;
const carsFound = vinLookup.data.vinVehicles;
if (carsFound.length == 0) {
// No VINs found
this.displayVinNotFoundAlert = true;
this.$refs.funnelFooter.removeLoader();
return;
} else if (carsFound.length == 1) {
var carFound = carsFound[0].vehicle;
if (carEntered.carId == carFound.carId || carFound.carId == this.previousCarIdFound) {
// update data
this.updateVehicleInfo(carFound.vin, carFound);
// navigate forward
this.navigateForward(carEntered, carsFound);
} else {
// Display Alert
this.customAlertData.vehicleInfo = carFound;
this.displayMatchedDifferentVehicleAlert = true;
// Update button "Continue with..."
this.$refs.funnelFooter.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`);
this.$refs.funnelFooter.removeLoader();
}
this.previousCarIdFound = carFound.carId;
} else if (vinLookup.data.vinVehicles.length > 1) {
this.updateCustomerInfo();
// navigate forward
this.navigateForward(carEntered, carsFound);
}
this.$refs.funnelFooter.removeLoader();
// const partsData = await baseMixin.methods.dispatchNonBlockingStoreAction(
// this.storeActions.GET_PARTS_OR_QUESTIONS,
// {
// carId: store.getters.vehicle.carId,
// glassArray: store.getters.damage.glassToReplace,
// zipCode: this.zip,
// vin: vinLookup.vin
// }, false
// );
// this.navigateForward(partsData);
},
// navigateForward(partsData){
// if(partsData.data.partsOrQuestions[0].partQuestions && partsData.data.partsOrQuestions[0].partQuestions.length > 0){
// this.$router.navigateAfterSave(this.navigationScenarios.CONTINUING_WITH_PARTS_QUESTION, this.$route, {}, {}, partsData.data);
// return;
// } else if((!partsData.data.partsOrQuestions[0].partQuestions || partsData.data.partsOrQuestions[0].partQuestions.length < 1) && partsData.data.partsOrQuestions[0].parts.length > 1) {
// this.$router.navigateAfterSave(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_PARTS, this.$route, {}, {}, partsData.data);
// return;
// } else {
// this.$router.navigate(this.navigationScenarios.CONTINUING_WITH_SINGLE_PART, this.$route);
// }
// },
resetWarningsAndErrors() {
this.displayVinNotFoundAlert = false;
this.displayNonServiceableZipAlert = false;
this.displayMatchedDifferentVehicleAlert = false;
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
},
async navigateForward(carEntered, carsFound) {
if (carsFound.length == 1) {
// get the damage options for the car that was found
const carFound = carsFound[0].vehicle;
const glassOptions = await baseMixin.methods.dispatchNonBlockingStoreAction(
storeActions.GET_DAMAGE_OPTIONS,
{ carId: carFound.carId }
);
// if the car entered is the same as the car found OR the glass options for the found car match the users damage selections
console.log(glassOptions.data);
console.log(store.getters.damage.glassToReplace);
if (carEntered.carId == carFound.carId || !compareGlassOptions(glassOptions.data, store.getters.damage.glassToReplace)) {
console.log("navigating to heritage funnel");
//navigateToHeritageFunnel();
} else {
const partsData = await baseMixin.methods.dispatchNonBlockingStoreAction(
this.storeActions.GET_PARTS_OR_QUESTIONS,
{
carId: carFound.carId,
glassArray: store.getters.damage.glassToReplace ? store.getters.damage.glassToReplace : [],
zipCode: this.serviceZip ? this.serviceZip : this.zip,
vin: carsFound[0].vin
}, false
);
console.log("navigating to vehicle-damage page");
// if not then navigate to the "vehicle-damage" page
//this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { displayVehicleChangeAlert: true }, partsData.data);
}
} else if (carsFound.length > 1) {
// if multiple cars were found
if (carsFound.find(car => car.carId === carEntered.carId)) {
console.log("navigating to heritage funnel");
// and one of them matches the car id entered
//navigateToHeritageFunnel();
} else {
console.log("navigating to address-vehicle page");
// and there is no match, navigate to "address-vehicle" page
//this.$router.navigateAfterSave(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, this.$route, {}, {}, carsFound);
}
}
},
validateZip(zip) {
return baseMixin.methods.dispatchNonBlockingStoreAction(
storeActions.VALIDATE_ZIP,
@ -203,16 +273,73 @@ export default {
licenseState: state
}, false
);
},
updateVehicleInfo(vin, vehicleInfo) {
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
store.commit(storeMutations.UPDATE_MAKE, vehicleInfo.make);
store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicleInfo.category);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicleInfo.imageUrl);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicleInfo.imageVifNumber);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicleInfo.imageColor);
},
updateCustomerInfo() {
store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, this.customerQuestions.addressQuestions.streetAddress);
store.commit(storeMutations.UPDATE_REGISTRATION_CITY, this.customerQuestions.addressQuestions.city);
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, this.customerQuestions.addressQuestions.state);
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.customerQuestions.addressQuestions.zipCode);
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, this.customerQuestions.firstName);
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, this.customerQuestions.lastName);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP, this.serviceZip);
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.customerQuestions.email);
},
},
computed: {
AlertNonServiceableZipHeader(){
let zip = this.serviceZip ? this.serviceZip : this.customerQuestions.addressQuestions.zip;
let text = this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zip);
return text;
},
AlertNonServiceableZipBody(){
return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
},
AlertMatchedDifferentVehicleHeader(){
let text = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:glassText}", getDamageString());
return text;
},
AlertMatchedDifferentVehicleBody(){
let content = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText");
content = content.replaceAll("{custom:glassText}", getDamageString());
let vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
let vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`;
content = content.replaceAll("{custom:vinYmmFound}", vinYmmFound);
content = content.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
return content;
},
},
watch: {
customerQuestions: {
handler(newValue) {
// if they modify one of the lookup fields (address, city, state, zip, or lastName), then modify the button text back to Get my personalized quote
// TODO
this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
this.showServiceZipField = false;
this.resetWarningsAndErrors();
},
deep: true
},
serviceZip: {
handler(newValue) {
// if they modify the service zip, then hide the error message
this.displayNonServiceableZipAlert = false;
},
}
},
components: {
funnelHeader,
@ -220,6 +347,8 @@ export default {
vehicleBanner,
funnelSubHeader,
customerQuestions,
textboxQuestion,
alert,
Form
},
};

View file

@ -159,7 +159,7 @@ export default ({
{
componentRestrictions: { country: ["us"] },
fields: ["address_components"],
types: ["address"],
types: ["geocode"],
}
);
@ -168,7 +168,6 @@ export default ({
addressField1.onblur = function() {
const hover = document.querySelector(".pac-container .pac-item:hover");
// if an item has been clicked, do nothing, otherwise get first solution and use Geocoder to get the place
if (hover === null) {
const item = document.querySelector(".pac-container .pac-item");
@ -210,7 +209,7 @@ export default ({
switch (componentType) {
case "street_number": {
self.addressModel.streetAddress = component.long_name;
self.addressModel.streetAddress = component.long_name;
break;
}
case "route": {
@ -254,10 +253,7 @@ export default ({
watch: {
addressModel: {
handler(newValue){
if (newValue.streetAddress && newValue.city && newValue.state && newValue.zip)
{
this.displayNoMatchWarning = false;
}
this.displayNoMatchWarning = false;
},
deep: true
}

View file

@ -1,5 +1,5 @@
<template>
<addressQuestions ref="addressQuestions" v-model="customerModel.addressQuestions" :alertNotifications="alertNotifications" @update:modelValue="emitAddressChange" />
<addressQuestions ref="addressQuestions" v-model="customerModel.addressQuestions" :alertNotifications="alertNotifications" />
<div class="row my-4">
<div class="col">
<textboxQuestion cmsWidgetName="FirstNameQuestionWidget" v-model="customerModel.firstName" ref="firstName" inputId="08497a2efd9a4a73a70360ab47b4838d" disableAutoFill validationRules="first-name-required" />

View file

@ -13,7 +13,8 @@ const navigationScenarios = {
SELECTED_DAMAGE_WITH_PART_QUESTIONS: "SELECTED_DAMAGE_WITH_PART_QUESTIONS",
CONTINUING_WITH_PARTS_QUESTION: "CONTINUING_WITH_PARTS_QUESTION",
CONTINUING_WITH_MULTIPLE_PARTS: "CONTINUING_WITH_MULTIPLE_PARTS",
CONTINUING_WITH_SINGLE_PART: "CONTINUING_WITH_SINGLE_PART"
CONTINUING_WITH_SINGLE_PART: "CONTINUING_WITH_SINGLE_PART",
CONTINUING_WITH_MULTIPLE_VEHICLES: "CONTINUING_WITH_MULTIPLE_VEHICLES"
};
export { navigationScenarios };

View file

@ -157,17 +157,13 @@ const routingTable = [
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
{
scenario: navigationScenarios.CONTINUING_WITH_PARTS_QUESTION,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
scenario: navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES,
destinationFmgPageValue: fmgPageValues.ADDRESS_VEHICLES,
},
{
scenario: navigationScenarios.CONTINUING_WITH_MULTIPLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CONTINUING_WITH_SINGLE_PART,
destinationFmgPageValue: fmgPageValues.REVEAL,
},
scenario: navigationScenarios.CLICKED_FORWARD,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
],
},
];

View file

@ -135,11 +135,23 @@ export const mutations = {
updateRegistrationLicensePlate(state, licensePlate){
state.order.vehicle.registration.licensePlate = licensePlate;
},
updateRegistrationAddress(state, registrationStreetAddress){
state.order.vehicle.registration.streetAddress = registrationStreetAddress;
},
updateRegistrationCity(state, registrationCity){
state.order.vehicle.registration.city = registrationCity;
},
updateRegistrationState(state, registrationState){
state.order.vehicle.registration.state = registrationState;
},
updateRegistrationZipCode(state, reistrationZipCode){
state.order.vehicle.registration.zipCode = reistrationZipCode;
updateRegistrationZipCode(state, registrationZipCode){
state.order.vehicle.registration.zipCode = registrationZipCode;
},
updateRegistrationFirstName(state, registrationFirstName){
state.order.vehicle.registration.firstName = registrationFirstName;
},
updateRegistrationLastName(state, registrationLastName){
state.order.vehicle.registration.lastName = registrationLastName;
},
updateServiceLocationZip(state, serviceLocationZip){
state.order.serviceLocation.zip = serviceLocationZip;