DigitalConsumer.ISS/src/layouts/policy-vehicles/policy-vehicles.vue
2026-01-26 14:57:56 -05:00

321 lines
12 KiB
Vue

<template>
<Form
ref="theForm"
v-slot="{ meta }"
@submit="onSubmit"
@invalidSubmit="onInvalidSubmit">
<div class="fade-on-route-transition policy-vehicles">
<div class="justify-content-center">
<siteHeader
class="header"
cmsWidgetName="SiteHeaderWidget" />
</div>
<div class="iss-heritage-container-width">
<div class="policy-vehicles-container iss-heritage-content-container-width">
<div class="select-car-form rounded text-center">
<siteSubHeader
cmsWidgetName="SiteSubHeaderWidget"
class="mt-4" />
<policyVehiclesQuestion
v-model="selectedVehicleVin"
cmsWidgetName="PolicyVehiclesQuestion"
:vehicles="VehiclesForQuestions"
:validationRules="rules.optionRequired"
class="mb-2" />
<buttonMain
:variant="buttonVariants.primary"
buttonText="Add another vehicle"
class="w-100"
@clickEvent="addAnotherVehicle" />
<alert
v-if="displayNoServiceAlert"
ref="AlertNoService"
class="mt-3"
cmsWidgetName="AlertVehicleSelection"
alertClass="alert-danger"
:isDismissable="false" />
<siteFooter
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!meta.valid || displayNoServiceAlert"
@ForwardClicked="forwardButtonAction"
@backClicked="backButtonAction" />
</div>
</div>
</div>
</div>
</Form>
</template>
<script>
// Components
import siteHeader from '@/iss-components/site-header/site-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import policyVehiclesQuestion from '@/layouts/policy-vehicles/policy-vehicles-question/policy-vehicles-question.vue';
// Supporting files
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper.js';
import { Form } from 'vee-validate';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
import vehicleSelectionOptions from '@/constants/vehicle-selection-options.js';
import endorsementOptions from '@/constants/endorsement-options.js';
import globalRules from '@/constants/global-rules.js';
import { useMainStore } from '@/store/index.js';
import bailoutMessage from '@/constants/bailoutMessage';
import {
deductibleForSelectedVehicle,
endorsementsForSelectedVehicle,
noCoverageForSelectedVehicle,
repairWaivedForSelectedVehicle
} from '@/helpers/policy-vehicle-helper';
import coverageType from '@/constants/coverage-type';
import alert from '@/ux-components/alert/alert.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import buttonMain from '@/ux-components/button-main/button-main.vue';
import { buttonVariants } from '@/constants/component-variants';
export default {
name: 'policy-vehicles',
components: {
buttonMain,
siteSubHeader,
siteHeader,
siteFooter,
policyVehiclesQuestion,
// eslint-disable-next-line vue/no-reserved-component-names
Form,
alert
},
mixins: [BaseFormMixin],
async beforeRouteEnter(to, from, next) {
const cmsContentPromise = await fetchCmsContentForPage(to.query.issPage);
next((vm) => {
vm.setCmsContent(cmsContentPromise);
});
},
setup() {
const mainStore = useMainStore();
return { mainStore };
},
data() {
const policyVehicles = useMainStore().order.policy.vehicles;
return {
policyVehicles,
selectedVehicleVin: '',
policyVinFound: true,
rules: {
optionRequired: globalRules.OPTION_REQUIRED
},
displayNoServiceAlert: false,
buttonVariants
};
},
computed: {
VehiclesForQuestions() {
// Map API result data, to address-vehicles data structure
const vehicles = this.policyVehicles;
const mappedData =
vehicles?.map((v) => {
const maskSymbol = '*';
const vinStart = maskSymbol.repeat(v.vin.length - 6);
const vinEnd = v.vin.substring(v.vin.length - 6);
return {
vin: v.vin,
vehicle: v,
Text: `${v.vehicleYear} ${v.vehicleMake} ${v.vehicleModel}`,
Name: v.vin,
SubText: `VIN: ${vinStart}${vinEnd}`
};
}) ?? [];
return mappedData;
},
selectedPolicyVehicle() {
if (this.selectedVehicleVin !== vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
return this.policyVehicles.find((p) => p.vin === this.selectedVehicleVin);
}
return null;
},
noCoverageForSelectedVehicle() {
return noCoverageForSelectedVehicle(this.selectedPolicyVehicle);
},
deductibleForSelectedVehicle() {
return deductibleForSelectedVehicle(this.selectedPolicyVehicle);
},
endorsementsForSelectedVehicle() {
return endorsementsForSelectedVehicle(this.selectedPolicyVehicle);
},
repairWaivedForSelectedVehicle() {
return repairWaivedForSelectedVehicle(this.selectedPolicyVehicle);
},
selectedVehicle() {
const vehicle = this.mainStore.lookupVehicleByVin(this.selectedVehicleVin);
return vehicle;
}
},
watch: {
async selectedVehicleVin(value) {
this.displayNoServiceAlert = false;
if (value === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
// clear previously selected vehicle and image
this.mainStore.resetVehicleState();
} else {
// get vehicle details from selected VIN
const vehicle = await this.lookupVehicleByVin(value);
// handle error in case vehicle info doesn't come back for selected VIN
if (vehicle?.error === true) {
this.mainStore.resetVehicleState();
return;
}
if (!vehicle?.data.canSafeliteService) {
this.displayNoServiceAlert = true;
return;
}
if (vehicle) {
// save selected vehicle to the store
useMainStore().updateVehicle({
...vehicle.data,
policyVehicleId: this.selectedPolicyVehicle?.id,
vin: value
});
}
}
}
},
beforeMount() {
if (this.mainStore.order.vehicle.vin) {
this.selectedVehicleVin = this.mainStore.order.vehicle.vin;
} else if (this.policyVehicles?.length === 1) {
this.selectedVehicleVin = this.policyVehicles[0]?.vin;
}
},
methods: {
backButtonAction() {
useMainStore().issConfig.disabledFields.policyNumber = true;
this.$router.navigate(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
async forwardButtonAction() {
if (this.selectedVehicleVin !== vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
const vehicleLookupResponse = await this.lookupVehicleByVin(this.selectedVehicleVin);
const vehicle = this.policyVehicles.find((pv) => pv.vin === this.selectedVehicleVin);
if (vehicleLookupResponse.error) {
if (vehicleLookupResponse.status === 404) {
this.mainStore.resetVehicleState();
useMainStore().updateVehicle({
policyVehicleId: vehicle.id,
carId: '0',
category: '',
year: vehicle.vehicleYear || '',
make: vehicle.vehicleMake || '',
model: vehicle.vehicleModel || '',
style: vehicle.vehicleStyle || '',
vin: vehicle.vin
});
this.policyVinFound = false;
return this.navigateForward();
}
this.mainStore.setBailout(bailoutMessage.vehicleVinLookupError(
vehicle.vin,
vehicleLookupResponse.data
));
return this.navigateForward();
}
useMainStore().updateVehicle({
...vehicleLookupResponse.data,
policyVehicleId: vehicle.id,
vin: this.selectedVehicleVin
});
useMainStore().updateVehicleCoverage({
noCoverage: this.noCoverageForSelectedVehicle,
deductible: this.deductibleForSelectedVehicle,
repairWaived: this.repairWaivedForSelectedVehicle,
endorsements: this.endorsementsForSelectedVehicle
});
} else {
useMainStore().updateCoverageType(coverageType.NONE);
}
return this.navigateForward();
},
navigateForward() {
if (this.mainStore.isBailout) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route,
{},
{}
);
} else if (this.selectedVehicleVin === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_NON_LISTED_VEHICLE,
this.$route,
{},
{}
);
} else if (this.endorsementsForSelectedVehicle?.length > 0
&& (this.endorsementsForSelectedVehicle?.includes(endorsementOptions.PARKING_GUARD)
|| this.endorsementsForSelectedVehicle?.includes(endorsementOptions.EDUCATOR))
) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS,
this.$route
);
} else if (!this.policyVinFound) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_CAR_ID_NOT_FOUND,
this.$route,
{},
{}
);
} else {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_LISTED_VEHICLE,
this.$route,
{},
{}
);
}
},
async lookupVehicleByVin(vin) {
try {
return await useMainStore().lookupVehicleByVin(vin);
} catch (responseError) {
return {
error: true,
status: responseError.status,
data: responseError.data
};
}
},
async addAnotherVehicle() {
this.selectedVehicleVin = vehicleSelectionOptions.VEHICLE_NOT_LISTED;
await this.forwardButtonAction();
}
}
};
</script>
<style lang="scss" scoped>
.iss-heritage-container-width {
.policy-vehicles-container {
position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
:deep(.subheader-secondary p) {
text-align: left;
}
:deep(span.small) {
font-size: 1rem;
}
:deep(.form-test-error) {
text-align: left;
}
}
}
</style>