start of address-vehicles page
This commit is contained in:
parent
2e924cbaf1
commit
a3c3b0b300
3 changed files with 318 additions and 44 deletions
|
|
@ -0,0 +1,82 @@
|
||||||
|
<template>
|
||||||
|
<buttonQuestion
|
||||||
|
class="address-vehicles-question"
|
||||||
|
buttonTypeString="listButton"
|
||||||
|
groupName="ChooseAddressVehicle"
|
||||||
|
:questionText="questionText"
|
||||||
|
:answers="vehicles"
|
||||||
|
v-model="selectedVehicleVin"
|
||||||
|
isRequired
|
||||||
|
:validation-rules="validationRules"
|
||||||
|
:valueToLogType="ValueToLogTypes.LAST_5" />
|
||||||
|
<alert
|
||||||
|
ref="differentVehicleAlert"
|
||||||
|
v-if="isCarIdDifferent"
|
||||||
|
class="my-3"
|
||||||
|
cmsWidgetName="FoundWindshield"
|
||||||
|
:manualHeadline="differentVehicleAlertHeader"
|
||||||
|
:manualCopy="differentVehicleAlertBody"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
// Supporting files
|
||||||
|
import { getDamageString } from "@/helpers/damage-helper";
|
||||||
|
export default {
|
||||||
|
name: "address-vehicles-question",
|
||||||
|
props: {
|
||||||
|
vehicles: Array,
|
||||||
|
modelValue: String,
|
||||||
|
cmsWidgetName: String,
|
||||||
|
validationRules: String,
|
||||||
|
isCarIdDifferent: Boolean,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
differentVehicleAlertHeader() {
|
||||||
|
return this.getCmsContent("FoundWindshield", "HeadlineText").replaceAll(
|
||||||
|
"{custom:damage}",
|
||||||
|
getDamageString()
|
||||||
|
);
|
||||||
|
},
|
||||||
|
differentVehicleAlertBody() {
|
||||||
|
return this.getCmsContent("FoundWindshield", "BodyText")
|
||||||
|
.replaceAll("{custom:damage}", getDamageString())
|
||||||
|
.replaceAll("{custom:vinlookupYear}", this.selectedVehicle?.vehicle.year)
|
||||||
|
.replaceAll("{custom:vinlookupMake}", this.selectedVehicle?.vehicle.make)
|
||||||
|
.replaceAll("{custom:vinlookupModel}", this.selectedVehicle?.vehicle.model);
|
||||||
|
},
|
||||||
|
questionText() {
|
||||||
|
return this.getCmsContent("VehicleConfirmationQuestion", "QuestionText");
|
||||||
|
},
|
||||||
|
selectedVehicleVin: {
|
||||||
|
get: function () {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set: function (newValue) {
|
||||||
|
this.$emit("update:modelValue", newValue);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selectedVehicle() {
|
||||||
|
// this computed is only needed for the computed differentVehicleAlertBody text above
|
||||||
|
return this.vehicles.find(({ vin }) => vin === this.selectedVehicleVin);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
buttonQuestion,
|
||||||
|
alert,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.address-vehicles-question {
|
||||||
|
.question-text {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
& > span {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -2,22 +2,59 @@
|
||||||
<Form
|
<Form
|
||||||
@submit="onSubmit"
|
@submit="onSubmit"
|
||||||
@invalidSubmit="onInvalidSubmit"
|
@invalidSubmit="onInvalidSubmit"
|
||||||
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
v-slot="{ meta }"
|
||||||
>
|
>
|
||||||
<div class="page-container-grouped-styles overflow-auto">
|
<div class="page-container-grouped-styles overflow-auto">
|
||||||
<siteHeader
|
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||||
cmsWidgetName="SiteHeaderWidget"
|
|
||||||
/>
|
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false"
|
:displayGenericVehicleImage="false"
|
||||||
/>
|
/>
|
||||||
<siteSubHeader
|
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||||
cmsWidgetName="SiteSubHeaderWidget"
|
<alert
|
||||||
|
cmsWidgetName="FoundMultipleVehicles"
|
||||||
|
ref="alertFoundMultipleVehicles"
|
||||||
|
class="my-5"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
:manualHeadline="AlertFoundMultipleVehiclesHeader"
|
||||||
|
manualCopy=""
|
||||||
|
v-bind:isDismissible="false"
|
||||||
/>
|
/>
|
||||||
<div class="fade-on-route-transition sub-container make-tall mt-5">
|
<alert
|
||||||
<p>Placeholder for address-vehicles page</p>
|
cmsWidgetName="FoundWindshield"
|
||||||
|
ref="alertFoundWindshield"
|
||||||
|
class="my-5"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
:manualHeadline="AlertFoundWindshieldHeader"
|
||||||
|
:manualCopy="AlertFoundWindshieldBody"
|
||||||
|
v-bind:isDismissible="false"
|
||||||
|
/>
|
||||||
|
<addressVehiclesQuestion
|
||||||
|
ref="addressVehiclesQuestion"
|
||||||
|
cmsWidgetName="VehicleConfirmationQuestion"
|
||||||
|
:vehicles="VehiclesForQuestions"
|
||||||
|
validationRules="vehicle-required"
|
||||||
|
v-model="selectedVehicleVin"
|
||||||
|
:isCarIdDifferent="isCarIdDifferent"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="alert-provide-vin my-3"
|
||||||
|
v-if="splitAlertProvideVinBodyForLink.length"
|
||||||
|
>
|
||||||
|
<span v-for="copy in splitAlertProvideVinBodyForLink" :key="copy">
|
||||||
|
<span v-if="doesCopyContainRouterLink(copy)" class="text-body">
|
||||||
|
<router-link
|
||||||
|
:to="{
|
||||||
|
query: { fmgPage: `${getRouterLinkRouteFromCopy(copy)}` },
|
||||||
|
name: 'root',
|
||||||
|
}"
|
||||||
|
>{{ getRouterLinkDisplayTextFromCopy(copy) }}</router-link
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span v-else class="m-0 text-body" v-html="copy"></span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<siteFooter
|
<siteFooter
|
||||||
cmsWidgetName="SiteFooterWidget"
|
cmsWidgetName="SiteFooterWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
|
@ -26,42 +63,50 @@
|
||||||
ref="siteFooter"
|
ref="siteFooter"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Import Supporting Files
|
// Import Supporting Files
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from '@/helpers/layout-helper';
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import { useMainStore } from "@/store";
|
||||||
|
import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||||
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
|
import { required } from "@/helpers/validation-rules";
|
||||||
|
import { Form, defineRule } from "vee-validate";
|
||||||
|
import { isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||||
|
import {
|
||||||
|
doesCopyContainRouterLink,
|
||||||
|
splitCopyOnCMSPlaceHolder,
|
||||||
|
getRouterLinkRouteFromCopy,
|
||||||
|
getRouterLinkDisplayTextFromCopy,
|
||||||
|
} from "@/helpers/cms-content-helper";
|
||||||
|
import { routerParams } from "@/router/router-constants/router-params";
|
||||||
|
import vinPagesMixin from "@/mixins/vin-pages-mixin";
|
||||||
|
|
||||||
// Import Component
|
// Import Component
|
||||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
import baseFormMixin from "@/mixins/base-form-mixin";
|
||||||
import { Form } from 'vee-validate';
|
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
|
||||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner.vue";
|
||||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
import addressVehiclesQuestion from "@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question";
|
||||||
|
|
||||||
|
// DEFINE VALIDATION RULES
|
||||||
|
defineRule("vehicle-required", required(errorMessages.VEHICLE_REQUIRED));
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'capability-questions',
|
name: "address-vehicles",
|
||||||
mixins: [baseFormMixin],
|
mixins: [baseFormMixin, vinPagesMixin],
|
||||||
components: {
|
|
||||||
siteFooter,
|
|
||||||
siteHeader,
|
|
||||||
siteSubHeader,
|
|
||||||
Form,
|
|
||||||
vehicleBanner,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||||
|
|
||||||
// Settle promises and get results
|
// Settle promises and get results
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
resultKey: 'cmsContent',
|
resultKey: "cmsContent",
|
||||||
promise: cmsContentPromise,
|
promise: cmsContentPromise,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
@ -72,18 +117,156 @@ export default {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
validationRules: String,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedVehicleVin: "",
|
||||||
|
isCarIdDifferent: false,
|
||||||
|
isSelectedGlassAvailableForVehicle: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
vehicleCount() {
|
||||||
|
return this.VehiclesForQuestions.length;
|
||||||
|
},
|
||||||
|
AlertFoundMultipleVehiclesHeader() {
|
||||||
|
return this.getCmsContent("FoundMultipleVehicles", "HeadlineText")
|
||||||
|
.replaceAll("{custom:vehicleCount}", this.vehicleCount);
|
||||||
|
},
|
||||||
|
AlertFoundWindshieldHeader() {
|
||||||
|
return this.getCmsContent("FoundWindshield", "HeadlineText")
|
||||||
|
.replaceAll("{custom:vehicleCount}", this.vehicleCount);
|
||||||
|
},
|
||||||
|
AlertFoundWindshieldBody() {
|
||||||
|
return this.getCmsContent("FoundWindshield", "BodyText")
|
||||||
|
.replaceAll("{custom:vinlookupYear}", this.vehicleCount)
|
||||||
|
.replaceAll("{custom:vinlookupMake}", this.vehicleCount)
|
||||||
|
.replaceAll("{custom:vinlookupModel}", this.vehicleCount);
|
||||||
|
},
|
||||||
|
AlertProvideVinBody() {
|
||||||
|
return this.getCmsContent("ProvideVinAlert", "BodyText");
|
||||||
|
},
|
||||||
|
splitAlertProvideVinBodyForLink() {
|
||||||
|
// Splits content when brackets are found in text so that text can be looped through and router-link can be injected when needed
|
||||||
|
return this.splitCopyOnCMSPlaceHolder(this.AlertProvideVinBody);
|
||||||
|
},
|
||||||
|
VehiclesForQuestions() {
|
||||||
|
// Map API result data, to address-vehicles data structure
|
||||||
|
const mappedData = this.VehiclesFromApi.map((v) => {
|
||||||
|
const maskSymbol = "X";
|
||||||
|
const vinStart = maskSymbol.repeat(v.vin.length - 6);
|
||||||
|
const vinEnd = v.vin.substring(v.vin.length - 6);
|
||||||
|
return {
|
||||||
|
vin: v.vin,
|
||||||
|
vehicle: v.vehicle,
|
||||||
|
Text: v.vehicle.year + " " + v.vehicle.make + " " + v.vehicle.model,
|
||||||
|
Name: v.vin,
|
||||||
|
SubText: "VIN " + vinStart + vinEnd,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return mappedData;
|
||||||
|
},
|
||||||
|
VehiclesFromApi() {
|
||||||
|
return useMainStore().pageData(issPageValues.ADDRESS_VEHICLES);
|
||||||
|
},
|
||||||
|
selectedVehicle() {
|
||||||
|
return this.VehiclesForQuestions.find(
|
||||||
|
({ vin }) => vin === this.selectedVehicleVin
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisiteValid() {
|
doesCopyContainRouterLink,
|
||||||
|
splitCopyOnCMSPlaceHolder,
|
||||||
|
getRouterLinkRouteFromCopy,
|
||||||
|
getRouterLinkDisplayTextFromCopy,
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
if (
|
||||||
|
useMainStore().order.vehicle.carId &&
|
||||||
|
useMainStore().order.serviceLocation.zipCode &&
|
||||||
|
useMainStore().order.customer.emailAddress &&
|
||||||
|
useMainStore().getters.pageData(issPageValues.ADDRESS_VEHICLES)
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
/**
|
this.$router.navigate(
|
||||||
* this.navigationScenarios comes from base-mixin
|
this.navigationScenarios.CLICKED_BACK,
|
||||||
*/
|
this.$route
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
);
|
||||||
},
|
},
|
||||||
async forwardButtonAction() {},
|
async forwardButtonAction() {
|
||||||
resetDependentState() {},
|
const vinLookup = await this.dispatchStoreAction(
|
||||||
|
storeActions.LOOKUP_VEHICLE_BY_VIN,
|
||||||
|
{
|
||||||
|
vin: this.selectedVehicle.vin,
|
||||||
|
}
|
||||||
|
).catch(() => {
|
||||||
|
this.$refs.siteFooter.removeLoader();
|
||||||
|
});
|
||||||
|
if (!vinLookup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
|
||||||
|
vinLookup.data.carId
|
||||||
|
);
|
||||||
|
await this.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_VIN,
|
||||||
|
{
|
||||||
|
vehicleInfo: Object.assign(this.selectedVehicle.vehicle, {
|
||||||
|
vin: this.selectedVehicle.vin,
|
||||||
|
}),
|
||||||
|
isSelectedGlassAvailableForVehicle:
|
||||||
|
this.isSelectedGlassAvailableForVehicle,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
return await this.navigateForward();
|
||||||
|
},
|
||||||
|
async navigateForward() {
|
||||||
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
|
this.$router.navigateWithSaving(
|
||||||
|
this.navigationScenarios.CLICKED_FORWARD,
|
||||||
|
this.$route,
|
||||||
|
{},
|
||||||
|
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await this.navigateForwardWithSingleCarMatch();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectedVehicleVin: {
|
||||||
|
handler() {
|
||||||
|
// does this vehicle match the previously selected carId?
|
||||||
|
this.isCarIdDifferent =
|
||||||
|
this.selectedVehicle?.vehicle.carId !== useMainStore().vehicle.carId;
|
||||||
|
if (this.isCarIdDifferent) {
|
||||||
|
this.$refs.siteFooter.updateButtonText(
|
||||||
|
`Continue with ${this.selectedVehicle.vehicle.year} ${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.$refs.siteFooter.updateButtonText(
|
||||||
|
this.getCmsContent("SiteFooterWidget", "ForwardButtonText")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
siteFooter,
|
||||||
|
siteHeader,
|
||||||
|
siteSubHeader,
|
||||||
|
Form,
|
||||||
|
vehicleBanner,
|
||||||
|
alert,
|
||||||
|
addressVehiclesQuestion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,15 @@ const routingTable = function(store) {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
issPageValue: issPageValues.ADDRESS_VEHICLES,
|
||||||
|
maps: [
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
|
destinationIssPageValue: issPageValues.ADDRESS_LOOKUP,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
issPageValue: issPageValues.WELCOME_PAGE,
|
issPageValue: issPageValues.WELCOME_PAGE,
|
||||||
maps: [
|
maps: [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue