DigitalConsumer.FixMyGlass/src/layouts/vehicle/vehicle.vue

435 lines
16 KiB
Vue

<template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-md-6">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-6 col-xl-4">
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
<vehicleQuestion
ref="vehicleYearQuestion"
v-model="selectedYear"
:isDisabled="!yearOptions.length"
:options="yearOptions"
cmsWidgetName="VehicleYearQuestion"
validationRules="year-required"
placeHolderText="Select year"
inputId="yearQuestionField" />
<vehicleQuestion
ref="vehicleMakeQuestion"
v-model="selectedMake"
:isDisabled="!makeOptions.length"
:options="makeOptions"
cmsWidgetName="VehicleMakeQuestion"
validationRules="make-required"
placeHolderText="Select make"
inputId="makeQuestionField" />
<vehicleQuestion
ref="vehicleModelQuestion"
v-model="selectedModel"
cmsWidgetName="VehicleModelQuestion"
:isDisabled="!modelOptions.length"
:options="modelOptions"
validationRules="model-required"
placeHolderText="Select model"
inputId="modelQuestionField" />
<vehicleQuestion
ref="vehicleStyleQuestion"
v-model="selectedStyle"
cmsWidgetName="VehicleStyleQuestion"
:isDisabled="!styleOptions.length"
:options="styleOptions"
validationRules="style-required"
placeHolderText="Select style"
inputId="styleQuestionField" />
<vehicleBanner
cmsWidgetName="VehicleBannerWidget"
:displayGenericVehicleImage="displayGeneric"
:displayVehicleImage="imageUrl"
:vehicleCategory="category"
:displayUnmatchedVehicleIcon="unmatchedVehicleIcon"
class="mt-5 vehicle-footer"
ref="banner" />
<navbar
cmsWidgetName="FunnelFooterWidget"
@ForwardClicked="forwardButtonAction"
:isForwardActionDisabled="!meta.valid"
ref="navbar" />
</div>
</div>
</div>
</Form>
</template>
<script>
// Components
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import navbar from "@/fmg-components/nav-bar/nav-bar";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
import vehicleQuestion from "@/layouts/vehicle/vehicle-question/vehicle-question";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { experimentUniverses } from "@/constants/experiments";
import { getDeviceIdValue, getSessionKeyValue } from "@/helpers/heritage-integration/cookie-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { Form, defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
//define validation rules
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
defineRule("make-required", required(errorMessages.MAKE_REQUIRED));
defineRule("model-required", required(errorMessages.MODEL_REQUIRED));
defineRule("style-required", required(errorMessages.STYLE_REQUIRED));
export default {
name: "vehicle",
data() {
return {
selectedYear: this.selectedYearfromStore(),
selectedMake: this.selectedMakefromStore(),
selectedModel: this.selectedModelfromStore(),
selectedStyle: this.selectedStylefromStore(),
carId: this.getCarIdfromStore(),
category: this.getCategoryfromStore(),
imageUrl: this.getImagefromStore(),
imageVifNumber: this.getImageVifNumberfromStore(),
imageVifColor: this.getImageVifColorfromStore(),
yearOptions: [],
makeOptions: [],
modelOptions: [],
styleOptions: [],
};
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const experimentForLogging = store.getters.applicationUser.experiments.find(
(e) => e.universeName === experimentUniverses.CONCEPT_FUNNEL
);
const yearQuestionInitialDataPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_YEARS,
{},
"vehicle"
);
var makeQuestionInitialDataPromise = null;
var modelQuestionInitialDataPromise = null;
var styleQuestionInitialDataPromise = null;
if (
store.getters.order.vehicle.make &&
store.getters.order.vehicle.model &&
store.getters.order.vehicle.style
) {
makeQuestionInitialDataPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_MAKES,
{
year: store.getters.order.vehicle.year,
},
"vehicle"
);
modelQuestionInitialDataPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_MODELS,
{
year: store.getters.order.vehicle.year,
make: store.getters.order.vehicle.make,
},
"vehicle"
);
styleQuestionInitialDataPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_STYLES,
{
year: store.getters.order.vehicle.year,
make: store.getters.order.vehicle.make,
model: store.getters.order.vehicle.model,
},
"vehicle"
);
}
// If the concept funnel experiment is found, as it should be when coming from safelite.com, then log the experiment exposure.
if (experimentForLogging !== undefined) {
// Log experiment exposure
baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.LOG_EXPERIMENT_EXPOSURE,
{
userId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.query.fmgPage,
experiment: experimentForLogging,
},
"vehicle",
false
);
}
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "yearQuestionInitialData",
promise: yearQuestionInitialDataPromise,
},
{
resultKey: "makeQuestionInitialData",
promise: makeQuestionInitialDataPromise,
},
{
resultKey: "modelQuestionInitialData",
promise: modelQuestionInitialDataPromise,
},
{
resultKey: "styleQuestionInitialData",
promise: styleQuestionInitialDataPromise,
},
];
let resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.initializeYearComponent(resultMap.yearQuestionInitialData);
if (
makeQuestionInitialDataPromise &&
modelQuestionInitialDataPromise &&
styleQuestionInitialDataPromise
)
vm.initializeMMSComponent(
resultMap.makeQuestionInitialData,
resultMap.modelQuestionInitialData,
resultMap.styleQuestionInitialData
);
});
},
watch: {
async selectedYear(year) {
if (year) {
const result = await this.getMakeOptions(year);
this.makeOptions = result?.data;
if (this.selectedYearfromStore() !== year) {
this.selectedMake = null;
this.selectedModel = null;
this.selectedStyle = null;
}
} else {
this.makeOptions = [];
this.selectedMake = null;
this.selectedModel = null;
this.selectedStyle = null;
}
},
async selectedMake(make) {
if (make) {
const result = await this.getModelOptions(this.selectedYear, make);
this.modelOptions = result?.data;
if (this.modelOptions.length === 1) this.selectedModel = this.modelOptions[0];
else {
this.selectedModel = null;
this.selectedStyle = null;
}
} else {
this.modelOptions = [];
this.selectedModel = null;
this.selectedStyle = null;
}
},
async selectedModel(model) {
if (model) {
const result = await this.getStyleOptions(
this.selectedYear,
this.selectedMake,
model
);
this.styleOptions = result?.data;
if (this.styleOptions.length === 1) {
const sameStyle = this.selectedStyle === this.styleOptions[0];
this.selectedStyle = this.styleOptions[0];
if (sameStyle) {
this.getVehicleDetails();
}
} else this.selectedStyle = null;
} else {
this.styleOptions = [];
this.selectedStyle = null;
}
},
async selectedStyle(style) {
if (style) {
this.getVehicleDetails();
} else {
this.imageUrl = null;
}
},
},
computed: {
unmatchedVehicleIcon() {
if (this.imageUrl == null && this.carId !== null) return true;
else return false;
},
displayGeneric() {
if (!this.selectedStyle) return true;
else if (this.carId == null) return true;
else if (this.imageUrl == null && this.carId !== null) return false;
else return true;
},
},
methods: {
getVehicle(year, make, model, style) {
return this.dispatchStoreActionWithLogging(
this.storeActions.GET_VEHICLE,
{
year: year,
make: make,
model: model,
style: style,
},
"vehicle"
);
},
arePagePrerequisitesValid() {
return true;
},
async getVehicleDetails() {
this.carId = null;
const result = await this.getVehicle(
this.selectedYear,
this.selectedMake,
this.selectedModel,
this.selectedStyle
);
this.carId = result?.data.carId;
this.category = result?.data.category;
this.imageUrl = result?.data.imageUrl;
this.imageVifNumber = result?.data.imageVifNumber;
this.imageVifColor = result?.data.imageVifColor;
},
async forwardButtonAction() {
this.dispatchStoreAction(
storeActions.SAVE_VEHICLE,
{
year: this.selectedYear,
make: this.selectedMake,
model: this.selectedModel,
style: this.selectedStyle,
carId: this.carId,
category: this.category,
imageUrl: this.imageUrl,
imageVifNumber: this.imageVifNumber,
imageVifColor: this.imageVifColor,
},
false
);
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
initializeYearComponent(initialData) {
this.yearOptions = initialData;
},
initializeMMSComponent(makeOptions, modelOptions, styleOptions) {
this.makeOptions = makeOptions;
this.modelOptions = modelOptions;
this.styleOptions = styleOptions;
},
selectedYearfromStore() {
return store.getters.vehicle.year?.toString();
},
selectedMakefromStore() {
return store.getters.vehicle.make;
},
selectedModelfromStore() {
return store.getters.vehicle.model;
},
selectedStylefromStore() {
return store.getters.vehicle.style;
},
async getMakeOptions(year) {
return await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_MAKES,
{
year: year,
},
"vehicle"
);
},
async getModelOptions(year, make) {
return await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_MODELS,
{
year: year,
make: make,
},
"vehicle"
);
},
async getStyleOptions(year, make, model) {
return await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_STYLES,
{
year: year,
make: make,
model: model,
},
"vehicle"
);
},
getImagefromStore() {
return store.getters.vehicle.imageUrl;
},
getCarIdfromStore() {
return store.getters.vehicle.carId;
},
getCategoryfromStore() {
return store.getters.vehicle.category;
},
getImageVifNumberfromStore() {
return store.getters.vehicle.imageVifNumber;
},
getImageVifColorfromStore() {
return store.getters.vehicle.imageVifColor;
},
},
components: {
funnelHeader,
navbar,
funnelSubHeader,
vehicleBanner,
Form,
vehicleQuestion,
},
};
</script>
<style lang="scss">
.vehicle-footer {
margin-bottom: 0;
}
.siteSubHeader {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
}
</style>