369 lines
13 KiB
Vue
369 lines
13 KiB
Vue
<template>
|
|
<Form
|
|
@submit="onSubmit"
|
|
@invalid-submit="onInvalidSubmit"
|
|
ref="theForm"
|
|
v-slot="{ meta }"
|
|
>
|
|
<div class="page-container-grouped-styles">
|
|
<loadingModal ref="loadingModal"/>
|
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
|
<vehicleBanner
|
|
cmsWidgetName="VehicleBannerWidget"
|
|
:displayGenericVehicleImage="false"
|
|
/>
|
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
|
<div class="fade-on-route-transition sub-container make-tall">
|
|
<div class="row mt-2">
|
|
<div class="col">
|
|
<textboxQuestion
|
|
cmsWidgetName="VinNumber"
|
|
v-model="vin"
|
|
inputId="vin"
|
|
isRequired
|
|
disableAutoFill
|
|
validationRules="vin-required|vin-format"
|
|
:isDisabled="isVinFieldReadOnly"
|
|
maxLength="17"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-2">
|
|
<div class="col">
|
|
<vinInformation />
|
|
</div>
|
|
</div>
|
|
<div class="row my-2">
|
|
<div class="col">
|
|
<textboxQuestion
|
|
cmsWidgetName="ServiceZIP"
|
|
v-model="zip"
|
|
inputId="zip"
|
|
mask="#####"
|
|
isRequired
|
|
disableAutoFill
|
|
validationRules="zip-required|zip-format"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="row my-2">
|
|
<div class="col">
|
|
<textboxQuestion
|
|
cmsWidgetName="EmailAddress"
|
|
v-model="email"
|
|
inputId="email"
|
|
isRequired
|
|
disableAutoFill
|
|
validationRules="email-address-required|email-address-format"
|
|
semiAggressiveValidation
|
|
/>
|
|
</div>
|
|
</div>
|
|
<alert
|
|
class="my-4"
|
|
v-model="customAlertData"
|
|
v-if="noMatchAlert"
|
|
alertClass="alert-warning"
|
|
cmsWidgetName="NoMatchAlertWidget"
|
|
/>
|
|
<alert
|
|
class="my-4"
|
|
:manualHeadline="PerfectMatchNewVinAlertReadOnlyHeader"
|
|
:manualCopy="PerfectMatchNewVinAlertReadOnlyBody"
|
|
v-model="customAlertData"
|
|
v-if="isVinFieldReadOnly"
|
|
alertClass="alert-success"
|
|
/>
|
|
<alert
|
|
class="my-4"
|
|
:manualHeadline="MatchedDifferentVehicleAlertHeader"
|
|
:manualCopy="MatchedDifferentVehicleAlertBody"
|
|
v-model="customAlertData"
|
|
v-if="isCarIdDifferent && !vinNotFound && !perfectMatchNewVinAlert"
|
|
alertClass="alert-warning"
|
|
/>
|
|
<alert
|
|
class="my-4"
|
|
:manualHeadline="NoServiceZipHeader"
|
|
:manualCopy="NoServiceZipBody"
|
|
v-model="customAlertData"
|
|
v-if="noServiceZip"
|
|
alertClass="alert-danger"
|
|
/>
|
|
<alert
|
|
class="my-4"
|
|
v-model="customAlertData"
|
|
v-if="vinNotFound"
|
|
alertClass="alert-danger"
|
|
cmsWidgetName="VinNotFound"
|
|
/>
|
|
<alert
|
|
class="my-4"
|
|
:manualHeadline="PerfectMatchNewVinAlertHeader"
|
|
:manualCopy="PerfectMatchNewVinAlertBody"
|
|
v-model="customAlertData"
|
|
v-if="perfectMatchNewVinAlert && !noServiceZip && !vinNotFound && meta.valid"
|
|
alertClass="alert-success"
|
|
/>
|
|
<funnelFooter
|
|
cmsWidgetName="FunnelFooterWidget"
|
|
ref="funnelFooter"
|
|
:isForwardActionDisabled="!meta.valid"
|
|
@back-clicked="backButtonAction"
|
|
@ForwardClicked="forwardButtonAction"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</Form>
|
|
</template>
|
|
|
|
<script>
|
|
// Components
|
|
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 funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
|
import alert from "@/ux-components/alert/alert";
|
|
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
|
import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information";
|
|
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
|
|
|
|
// 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 { getDamageString, getIsWindshieldOnly, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
|
import { required, regex } from "@/helpers/validation-rules";
|
|
import { Form, defineRule } from "vee-validate";
|
|
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
|
|
|
// DEFINE VALIDATION RULES
|
|
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
|
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
|
|
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 {
|
|
name: "vin-lookup",
|
|
async beforeRouteEnter(to, from, next) {
|
|
// Call APIs
|
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
|
|
|
// 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);
|
|
});
|
|
},
|
|
data() {
|
|
return {
|
|
isCarIdDifferent: false,
|
|
noServiceZip: false,
|
|
vinNotFound: false,
|
|
vin: this.getVinFromStore(),
|
|
zip: this.getZipFromStore(),
|
|
email: this.getEmailFromStore(),
|
|
customAlertData: {},
|
|
previouslyEnteredCarId: '',
|
|
invalidZip: '',
|
|
vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
|
|
};
|
|
},
|
|
mounted() {
|
|
this.attachCustomEvents();
|
|
},
|
|
watch: {
|
|
vin() {
|
|
this.$refs.funnelFooter.updateButtonText(
|
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
|
);
|
|
}
|
|
},
|
|
computed: {
|
|
perfectMatchNewVinAlert() {
|
|
const isVinPerfectMatch = this.vinPopulatedOnPageLoad && this.vin === this.getVinFromStore();
|
|
this.updateIsCarIdDifferent(isVinPerfectMatch);
|
|
return isVinPerfectMatch;
|
|
},
|
|
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");
|
|
},
|
|
PerfectMatchNewVinAlertHeader() {
|
|
return this.getCmsContent("PerfectMatchNewVinAlert", "HeadlineText");
|
|
},
|
|
PerfectMatchNewVinAlertBody() {
|
|
return this.getCmsContent("PerfectMatchNewVinAlert", "BodyText").replaceAll("{custom:damage}",
|
|
getDamageString())
|
|
},
|
|
PerfectMatchNewVinAlertReadOnlyHeader () {
|
|
return this.getCmsContent("PerfectMatchNewVinAlertReadOnly", "HeadlineText");
|
|
},
|
|
PerfectMatchNewVinAlertReadOnlyBody () {
|
|
return this.getCmsContent("PerfectMatchNewVinAlertReadOnly", "BodyText").replaceAll("{custom:damage}",
|
|
getIsWindshieldOnly())
|
|
},
|
|
isVinFieldReadOnly(){
|
|
return this.$store.getters.payment.insuranceCoverage.isVerified;
|
|
},
|
|
},
|
|
methods: {
|
|
arePagePrerequisitesValid() {
|
|
return store.getters.vehicle.carId !== null;
|
|
},
|
|
resetDependentState() {
|
|
store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, null);
|
|
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);
|
|
},
|
|
getEmailFromStore(){
|
|
return store.getters.order.customer.emailAddress;
|
|
},
|
|
getVinFromStore(){
|
|
return store.getters.vehicle.vin;
|
|
},
|
|
getZipFromStore(){
|
|
return store.getters.order.serviceLocation.zipCode;
|
|
},
|
|
attachCustomEvents() {
|
|
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
|
this.pushEventToGA(
|
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
|
this.GaActions.SUBMITTED,
|
|
this.GaLabels.VIN_LOOKUP,
|
|
true
|
|
);
|
|
});
|
|
},
|
|
updateIsCarIdDifferent(isVinPerfectMatch){
|
|
if (isVinPerfectMatch) {
|
|
this.isCarIdDifferent = false;
|
|
}
|
|
},
|
|
backButtonAction() {
|
|
if (store.getters.vehicle.vin) {
|
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK_WITH_VIN, this.$route);
|
|
}
|
|
else {
|
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
|
}
|
|
},
|
|
async forwardButtonAction() {
|
|
const zipValidation = this.validateZip(this.zip);
|
|
const vehicleLookup = this.lookupVehicle(this.vin);
|
|
const zipValidationResponse = await zipValidation;
|
|
const vehicleLookupResponse = await vehicleLookup.catch(() => {
|
|
this.vinNotFound = true;
|
|
this.$refs.funnelFooter.removeLoader();
|
|
this.noServiceZip = false;
|
|
return;
|
|
});
|
|
if (!zipValidationResponse.data.isServiceable) {
|
|
this.customAlertData.zip = this.zip;
|
|
this.$refs.funnelFooter.removeLoader();
|
|
this.noServiceZip = true;
|
|
this.invalidZip = this.zip;
|
|
return;
|
|
}
|
|
this.isCarIdDifferent = vehicleLookupResponse.data.carId !== store.getters.vehicle.carId;
|
|
|
|
if (this.isCarIdDifferent && (vehicleLookupResponse.data.carId !== this.previouslyEnteredCarId)) {
|
|
this.previouslyEnteredCarId = vehicleLookupResponse.data.carId;
|
|
this.noServiceZip = false;
|
|
this.customAlertData.vehicleInfo = vehicleLookupResponse.data;
|
|
this.$refs.funnelFooter.updateButtonText(`Continue with ${vehicleLookupResponse.data.year} ${vehicleLookupResponse.data.make} ${vehicleLookupResponse.data.model}`);
|
|
this.isVinValid = true;
|
|
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vehicleLookupResponse.data.carId);
|
|
this.$refs.funnelFooter.removeLoader();
|
|
this.isCarIdDifferent = true;
|
|
return;
|
|
}
|
|
this.updateStore(vehicleLookupResponse.data);
|
|
this.navigateForward();
|
|
},
|
|
navigateForward(){
|
|
if(this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle){
|
|
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { displayVehicleChangeAlert: true }, {});
|
|
return;
|
|
} else {
|
|
this.$refs.loadingModal.showModal();
|
|
navigateAfterSaveToHeritageFunnel(this.$route);
|
|
return;
|
|
}
|
|
},
|
|
validateZip(zip) {
|
|
return baseMixin.methods.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
|
zip,
|
|
});
|
|
},
|
|
lookupVehicle(vin) {
|
|
return baseMixin.methods.dispatchStoreAction(
|
|
storeActions.LOOKUP_VEHICLE_BY_VIN,
|
|
{ vin }
|
|
);
|
|
},
|
|
updateStore(carInfo) {
|
|
if(this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle){
|
|
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.imageVifNumber);
|
|
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.zip);
|
|
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
|
|
},
|
|
},
|
|
components: {
|
|
Form,
|
|
funnelHeader,
|
|
vehicleBanner,
|
|
funnelSubHeader,
|
|
textboxQuestion,
|
|
alert,
|
|
funnelFooter,
|
|
vinInformation,
|
|
loadingModal,
|
|
},
|
|
};
|
|
</script>
|