DigitalConsumer.FixMyGlass/src/layouts/vehicle/vehicle.vue
CarlNation c41fe3fcfc CSR-2237
CSR-2237 found another cart price issue.  Salestax was showing $13 on an order that was pending coverage.  Changed salestax to return 0 for not verified insurance
2024-10-01 08:21:47 -04:00

560 lines
21 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" ref="funnelHeader" />
</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="isYearDisabled"
:options="yearOptions"
cmsWidgetName="VehicleYearQuestion"
validationRules="year-required"
placeHolderText="Select year"
customDropdownId="yearQuestionField" />
<vehicleQuestion
ref="vehicleMakeQuestion"
v-model="selectedMake"
:isDisabled="isMakeDisabled"
:options="makeOptions"
cmsWidgetName="VehicleMakeQuestion"
validationRules="make-required"
placeHolderText="Select make"
customDropdownId="makeQuestionField" />
<vehicleQuestion
ref="vehicleModelQuestion"
v-model="selectedModel"
cmsWidgetName="VehicleModelQuestion"
:isDisabled="isModelDisabled"
:options="modelOptions"
validationRules="model-required"
placeHolderText="Select model"
customDropdownId="modelQuestionField" />
<vehicleQuestion
ref="vehicleStyleQuestion"
v-model="selectedStyle"
cmsWidgetName="VehicleStyleQuestion"
:isDisabled="isStyleDisabled"
:options="styleOptions"
validationRules="style-required"
placeHolderText="Select style"
customDropdownId="styleQuestionField" />
<vehicleBanner
cmsWidgetName="VehicleBannerWidget"
:displayGenericVehicleImage="displayGeneric"
:displayVehicleImage="imageUrl"
:vehicleCategory="category"
:displayUnmatchedVehicleIcon="unmatchedVehicleIcon"
class="mt-5 vehicle-footer"
ref="banner" />
<alert
ref="AlertNoService"
v-if="displayNoServiceAlert"
class="mt-4 alert"
cmsWidgetName="AlertNoServiceWidget"
alertClass="alert-danger"
:isDismissible="false" />
<navbar
cmsWidgetName="FunnelFooterWidget"
@ForwardClicked="forwardButtonAction"
:isForwardActionDisabled="
!meta.valid || !allDataRetrieved || displayNoServiceAlert
"
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 alert from "@/ux-components/alert/alert";
import vehicleQuestion from "@/layouts/vehicle/vehicle-question/vehicle-question";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { experimentUniverses } from "@/constants/experiments";
import { getSessionKeyValue, getUserIdValue } 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";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { applicationConfig } from "../../constants/application-config";
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
//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: [],
displayNoServiceAlert: false,
};
},
async beforeRouteEnter(to, from, next) {
const log = getQuerystringParameter(queryStrings.LOG);
if (eval(log)) {
console.log("----------------- applicationConfig start -----------------");
console.log(new Date() + JSON.stringify(applicationConfig));
console.log("----------------- applicationConfig end -----------------");
}
// 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;
const year =
store.getters.externalParameterVehicle.year || store.getters.order.vehicle.year;
const make =
store.getters.externalParameterVehicle.make || store.getters.order.vehicle.make;
const model =
store.getters.externalParameterVehicle.model || store.getters.order.vehicle.model;
const style =
store.getters.externalParameterVehicle.style || store.getters.order.vehicle.style;
if (make && model && style) {
makeQuestionInitialDataPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_MAKES,
{
year: year,
},
"vehicle"
);
modelQuestionInitialDataPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_MODELS,
{
year: year,
make: make,
},
"vehicle"
);
styleQuestionInitialDataPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_STYLES,
{
year: year,
make: make,
model: 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: getUserIdValue(),
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);
//ExternalParameter widget have different case style value so need to parse with NextGen
if (store.getters.externalParameterState?.isExternalParameter) {
if (
makeQuestionInitialDataPromise &&
modelQuestionInitialDataPromise &&
styleQuestionInitialDataPromise
) {
const matchingMake = resultMap.makeQuestionInitialData?.filter(
(item) =>
item.toLowerCase() ===
store.getters.externalParameterVehicle.make.toLowerCase()
);
const matchingModel = resultMap.modelQuestionInitialData?.filter(
(item) =>
item.toLowerCase() ===
store.getters.externalParameterVehicle.model.toLowerCase()
);
const matchingStyle = resultMap.styleQuestionInitialData?.filter(
(item) =>
item.toLowerCase() ===
store.getters.externalParameterVehicle.style.toLowerCase()
);
baseMixin.methods.dispatchStoreAction(
storeActions.UPDATE_EXTERNAL_PARAMETER_MMS,
{
externalParameterMake: matchingMake[0],
externalParameterModel: matchingModel[0],
externalParameterStyle: matchingStyle[0],
},
false
);
}
}
// Call the "next" function to complete the transition to this page.
next(async (vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.initializeYearComponent(resultMap.yearQuestionInitialData);
if (
makeQuestionInitialDataPromise &&
modelQuestionInitialDataPromise &&
styleQuestionInitialDataPromise
)
vm.initializeMMSComponent(
resultMap.makeQuestionInitialData,
resultMap.modelQuestionInitialData,
resultMap.styleQuestionInitialData
);
if (store.getters.externalParameterState?.isExternalParameter) {
await vm.getVehicleDetails();
if (!vm.displayNoServiceAlert) {
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
if (isValid) {
vm.forwardButtonAction();
} else {
baseMixin.methods.ResetExternalParamsAndHideModal();
}
} else {
baseMixin.methods.ResetExternalParamsAndHideModal();
}
} else {
baseMixin.methods.ResetExternalParamsAndHideModal();
}
});
},
watch: {
async selectedYear(year) {
this.resetAlert();
this.makeOptions = [];
this.selectedMake = null;
this.selectedModel = null;
this.selectedStyle = null;
this.carId = null;
if (year) {
const result = await this.getMakeOptions(year);
if (this.selectedYear == year) {
this.makeOptions = result?.data;
if (this.selectedYearfromStore() !== year) {
this.selectedMake = null;
this.selectedModel = null;
this.selectedStyle = null;
this.carId = null;
}
}
}
},
async selectedMake(make) {
this.resetAlert();
this.modelOptions = [];
this.selectedModel = null;
this.selectedStyle = null;
this.carId = null;
if (make) {
const result = await this.getModelOptions(this.selectedYear, make);
if (this.selectedMake == make) {
this.modelOptions = result?.data;
if (this.modelOptions.length === 1) this.selectedModel = this.modelOptions[0];
else {
this.selectedModel = null;
this.selectedStyle = null;
this.carId = null;
}
}
}
},
async selectedModel(model) {
this.resetAlert();
this.styleOptions = [];
this.selectedStyle = null;
this.carId = null;
if (model) {
const result = await this.getStyleOptions(
this.selectedYear,
this.selectedMake,
model
);
if (this.selectedModel == 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;
this.carId = null;
}
}
}
},
async selectedStyle(style) {
this.resetAlert();
if (style) {
this.getVehicleDetails();
} else {
this.imageUrl = null;
this.carId = null;
}
},
},
computed: {
isYearDisabled() {
return this.isDisabled(this.yearOptions);
},
isMakeDisabled() {
return this.isDisabled(this.makeOptions);
},
isModelDisabled() {
return this.isDisabled(this.modelOptions);
},
isStyleDisabled() {
return this.isDisabled(this.styleOptions);
},
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;
},
allDataRetrieved() {
return (
!!this.selectedYear &&
!!this.selectedMake &&
!!this.selectedModel &&
!!this.selectedStyle &&
!!this.carId
);
},
},
methods: {
isDisabled(options) {
if (!options.length || store.getters.payment?.insuranceCoverage?.isVerified) {
return true;
} else {
return false;
}
},
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;
this.displayNoServiceAlert = !result?.data.canSafeliteService;
},
resetAlert() {
this.displayNoServiceAlert = false;
},
async forwardButtonAction() {
await this.dispatchStoreAction(storeActions.RESET_SUBMITTED_ORDER);
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.externalParameterVehicle.year ??
store.getters.vehicle.year?.toString()
);
},
selectedMakefromStore() {
return store.getters.externalParameterVehicle.make ?? store.getters.vehicle.make;
},
selectedModelfromStore() {
return store.getters.externalParameterVehicle.model ?? store.getters.vehicle.model;
},
selectedStylefromStore() {
return store.getters.externalParameterVehicle.style ?? 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,
alert,
vehicleQuestion,
},
};
</script>
<style lang="scss">
.vehicle-footer {
margin-bottom: 0;
}
.siteSubHeader {
margin-top: 1.5rem;
margin-bottom: 0;
}
</style>