DigitalConsumer.FixMyGlass/src/layouts/vin-lookup/vin-lookup.vue
Scott Kiener 2544954f8f CSR-652 | Add CSS class to each alert
That matches CMS
2022-06-14 16:49:24 -04:00

373 lines
14 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
v-if="noMatchAlert"
class="my-4"
cmsWidgetName="NoMatchAlertWidget"
alertClass="alert-warning"
/>
<alert
v-if="isVinFieldReadOnly"
class="my-4"
cmsWidgetName="PerfectMatchNewVinAlertReadOnly"
:manualHeadline="PerfectMatchNewVinAlertReadOnlyHeader"
:manualCopy="PerfectMatchNewVinAlertReadOnlyBody"
alertClass="alert-success"
/>
<alert
v-if="isCarIdDifferent && !vinNotFound && !perfectMatchNewVinAlert"
class="my-4"
cmsWidgetName="MatchedDifferentVehicle"
:manualHeadline="MatchedDifferentVehicleAlertHeader"
:manualCopy="MatchedDifferentVehicleAlertBody"
alertClass="alert-warning"
/>
<alert
v-if="noServiceZip"
class="my-4"
cmsWidgetName="NoServiceZipWidget"
:manualHeadline="NoServiceZipHeader"
:manualCopy="NoServiceZipBody"
alertClass="alert-danger"
/>
<alert
v-if="vinNotFound"
class="my-4"
cmsWidgetName="VinNotFound"
alertClass="alert-danger"
/>
<alert
v-if="perfectMatchNewVinAlert && !noServiceZip && !vinNotFound && meta.valid && !isVinFieldReadOnly"
class="my-4"
cmsWidgetName="PerfectMatchNewVinAlert"
:manualHeadline="PerfectMatchNewVinAlertHeader"
:manualCopy="PerfectMatchNewVinAlertBody"
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";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-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-hA-Hj-nJ-NpPr-zR-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.vinNotFound = false;
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 || getFunnelCookie().HasDelayedClaimRegistration;
},
},
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 false;
});
if (!vehicleLookupResponse) {
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, zipValidationResponse.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, zipInfo) {
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_SERVICE_LOCATION_STATE, zipInfo.state);
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
},
},
components: {
Form,
funnelHeader,
vehicleBanner,
funnelSubHeader,
textboxQuestion,
alert,
funnelFooter,
vinInformation,
loadingModal,
},
};
</script>