Merge remote-tracking branch 'origin/CSR-101-vin-lookup' into feature/CSR-85

This commit is contained in:
FrankRua 2022-04-19 10:44:42 -04:00
commit 7a6c87dff7
6 changed files with 282 additions and 52 deletions

View file

@ -1,5 +1,8 @@
<template> <template>
<div class="textbox-question" :class="(errors.length > 0 || hasError) ? 'has-error' : ''"> <div class="textbox-question" :class="[
errors.length > 0 ? 'has-error' : '',
hasError ? 'has-error' : '',
]">
<label :for="inputId" :aria-label="questionText" class="form-label" v-html="labelText"></label> <label :for="inputId" :aria-label="questionText" class="form-label" v-html="labelText"></label>
<input v-model="value" <input v-model="value"
v-maska="mask" v-maska="mask"
@ -64,7 +67,8 @@ export default {
handleBlur, handleBlur,
handleChange, handleChange,
meta, meta,
validate validate,
errors,
} = useField(props.inputId, props.validationRules, fieldOptions); } = useField(props.inputId, props.validationRules, fieldOptions);
return { return {
@ -73,6 +77,7 @@ export default {
handleChange, handleChange,
validate, validate,
meta, meta,
errors,
}; };
}, },
computed: { computed: {

View file

@ -16,6 +16,8 @@ const errorMessages = {
LAST_NAME_REQUIRED: "Please enter your last name", LAST_NAME_REQUIRED: "Please enter your last name",
EMAIL_ADDRESS_REQUIRED: "Please enter your email address", EMAIL_ADDRESS_REQUIRED: "Please enter your email address",
EMAIL_ADDRESS_FORMAT: "Please enter a valid email address", EMAIL_ADDRESS_FORMAT: "Please enter a valid email address",
VIN_REQUIRED: "Please enter your VIN",
VIN_FORMAT: "Please enter a valid VIN",
}; };
export { errorMessages }; export { errorMessages };

View file

@ -1,44 +1,267 @@
<template> <template>
<div class="container-fluid shadow rounded-3 px-5 position-relative make-tall"> <Form
<funnelHeader ref="funnelHeader" /> @submit="onSubmit"
<vehicleBanner ref="vehicleBanner" /> @invalid-submit="onInvalidSubmit"
<funnelSubHeader ref="funnelSubHeader" /> ref="theForm"
<vinInformation class="mb-5" /> v-slot="{ meta }"
<funnel-footer ref="funnelFooter" :isForwardActionDisabled=true @back-clicked="backButtonAction" @ForwardClicked="forwardButtonAction" /> >
</div> <div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
<div class="row my-2">
<div class="col">
<textboxQuestion cmsWidgetName="VinNumber" v-model="vin" inputId="vin" disableAutoFill validationRules="vin-required|vin-format" />
</div>
</div>
<div class="row my-2">
<div class="col">
<vinInformation />
</div>
</div>
<div class="row my-2">
<div class="col">
<textboxQuestion cmsWidgetName="ServiceZIP" v-model="zip" inputId="zip" mask="#####" disableAutoFill validationRules="zip-required" />
</div>
</div>
<div class="row my-2">
<div class="col">
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" inputId="email" disableAutoFill validationRules="email-address-required|email-address-format" />
</div>
</div>
<alert
class="my-3"
v-model="customAlertData"
v-if="matchedDifferentVehicle"
alertClass="alert-danger"
cmsWidgetName="MatchedDifferentVehicle"
/>
<alert
class="my-3"
v-model="customAlertData"
v-if="noMatchAlert"
alertClass="alert-warning"
cmsWidgetName="NoMatchAlertWidget"
/>
<alert
class="my-3"
v-model="customAlertData"
v-if="noServiceZip"
alertClass="alert-warning"
cmsWidgetName="NoServiceZipWidget"
/>
<alert
class="my-3"
v-model="customAlertData"
v-if="vinFound"
alertClass="alert-warning"
cmsWidgetName="VinFoundWidget"
/>
<alert
class="my-3"
v-model="customAlertData"
v-if="vinFoundReadOnly"
alertClass="alert-warning"
cmsWidgetName="VinFoundReadOnlyWidget"
/>
<alert
class="my-3"
v-model="customAlertData"
v-if="foundWindshieldAlert"
alertClass="alert-warning"
cmsWidgetName="FoundWindshieldAlert"
/>
<alert
class="my-3"
v-model="customAlertData"
v-if="vinNotFound"
alertClass="alert-warning"
cmsWidgetName="VinNotFound"
/>
<alert
class="my-3"
v-model="customAlertData"
v-if="perfectMatchNewVinAlert"
alertClass="alert-warning"
cmsWidgetName="PerfectMatchNewVinAlert"
/>
<funnelFooter
cmsWidgetName="FunnelFooterWidget"
ref="funnelFooter"
:isDisabled="!meta.valid"
@back-clicked="backButtonAction"
@ForwardClicked="forwardButtonAction"
/>
</div>
</Form>
</template> </template>
<script> <script>
// Components // Components
import funnelHeader from "@/common-components/funnel-header/funnel-header"; import funnelHeader from "@/common-components/funnel-header/funnel-header";
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
import funnelFooter from "@/common-components/funnel-footer/funnel-footer"; import alert from "@/ux-components/alert/alert";
import textboxQuestion from "@/common-components/textbox-question/textbox-question"; import textboxQuestion from "@/common-components/textbox-question/textbox-question";
import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information"; import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin.js";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { errorMessages } from "@/constants/error-messages";
import { required, regex } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate";
// DEFINE VALIDATION RULES
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
defineRule("email-address-format", regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT));
defineRule("vin-required", required(errorMessages.VIN_REQUIRED));
defineRule("vin-format", regex(/^[A-HJ-NPR-Z0-9]{17}$/, errorMessages.VIN_FORMAT));
export default { export default {
name: "vin-lookup", name: "vin-lookup",
components: { async beforeRouteEnter(to, from, next) {
funnelHeader, // Call APIs
vehicleBanner, const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
funnelSubHeader,
vinInformation,
funnelFooter, // Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
props: {
validationRules: String,
},
data() {
return {
matchedDifferentVehicle: false,
noMatchAlert: false,
noServiceZip: false,
vinFound: false,
vinFoundReadOnly: false,
foundWindshieldAlert: false,
vinNotFound: false,
perfectMatchNewVinAlert: false,
vin: '',
zip: '',
email: '',
customAlertData: {},
};
},
methods: {
arePagePrerequisitesValid() {
return store.getters.vehicle.carId !== null;
}, },
methods: { resetDependentState() {
arePagePrerequisitesValid() { store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, null);
return true; store.commit(storeMutations.UPDATE_REGISTRATION_CITY, null);
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, null);
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, null);
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
},
backButtonAction() {
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {
const zipValidation = await this.validateZip(this.zip);
if (!zipValidation.data.isServiceable) {
this.customAlertData.zip = this.zip;
this.$refs.funnelFooter.removeLoader();
this.noServiceZip = true;
return;
}
const vinLookup = await this.lookupVin(this.vin).catch(() => {
this.$refs.funnelFooter.removeLoader();
this.noMatchAlert = true;
return;
});
if (vinLookup.data.carId !== store.getters.vehicle.carId) {
this.customAlertData.vehicleInfo = vinLookup.data.vehicle;
this.$refs.funnelFooter.removeLoader();
this.foundWindshieldAlert = true;
return;
}
const carInfo = this.vinDoesNotMatchCarId ? vinLookup.data : store.getters.vehicle;
this.updateStore(carInfo)
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
}, },
backButtonAction() { false
if (this.$store.getters.vehicle.vin) { );
this.$router.navigate(this.navigationScenarios.CLICKED_BACK_WITH_VIN, this.$route) 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);
} }
} },
validateZip(zip) {
return baseMixin.methods.dispatchNonBlockingStoreAction(
storeActions.VALIDATE_ZIP,
{ zip }
);
},
lookupVin(vin) {
return baseMixin.methods.dispatchNonBlockingStoreAction(
storeActions.LOOKUP_VEHICLE_BY_VIN,
{ vin }
);
},
updateStore(carInfo) {
// if(vehicleDamage){
// store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
// }
store.commit(storeMutations.UPDATE_VEHICLE_VIN, this.vin);
store.commit(storeMutations.UPDATE_YEAR, carInfo.year);
store.commit(storeMutations.UPDATE_MAKE, carInfo.make);
store.commit(storeMutations.UPDATE_MODEL, carInfo.model);
store.commit(storeMutations.UPDATE_STYLE, carInfo.style);
store.commit(storeMutations.UPDATE_CAR_ID, carInfo.carId);
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, carInfo.category);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, carInfo.imageUrl);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, carInfo.imageVifNumber);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, carInfo.imageColor);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP, this.zip);
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
},
},
components: {
Form,
funnelHeader,
vehicleBanner,
funnelSubHeader,
textboxQuestion,
alert,
funnelFooter,
vinInformation,
},
}; };
</script> </script>
<style lang="scss">
</style>

View file

@ -63,7 +63,7 @@ const routingTable = [
}, },
{ {
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_SINGLE_PART, scenario: navigationScenarios.SELECTED_DAMAGE_WITH_SINGLE_PART,
destinationFmgPageValue: fmgPageValues.REVEAL destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
}, },
{ {
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_MULTIPLE_PARTS, scenario: navigationScenarios.SELECTED_DAMAGE_WITH_MULTIPLE_PARTS,
@ -71,7 +71,7 @@ const routingTable = [
}, },
{ {
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_PART_QUESTIONS, scenario: navigationScenarios.SELECTED_DAMAGE_WITH_PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS, destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,//This might be temporary
}, },
], ],
}, },
@ -110,7 +110,7 @@ const routingTable = [
maps: [ maps: [
{ {
scenario: navigationScenarios.CLICKED_BACK, scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE, destinationFmgPageValue: fmgPageValues.REVEAL,
}, },
{ {
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN, scenario: navigationScenarios.CLICKED_BACK_WITH_VIN,

View file

@ -5,7 +5,7 @@
:class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]" :class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]"
> >
<p class="m-0 fw-bold small alert-heading">{{ alertHeadline }}</p> <p class="m-0 fw-bold small alert-heading">{{ alertHeadline }}</p>
<p class="m-0 text-body small" v-html="alertCopy"></p> <p class="m-0 text-body small">{{ alertCopy }}</p>
<button <button
type="button" type="button"
class="btn-close p-2" class="btn-close p-2"