DigitalConsumer.FixMyGlass/src/layouts/service-location/service-location.vue
2023-03-27 09:47:30 -04:00

282 lines
11 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" />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
<div class="fade-on-route-transition sub-container make-tall">
<serviceZipModalQuestion
v-model="serviceZipCodeQuestion"
ref="serviceZipCodeQuestion"
:mobileFeePart="mobileFeePart"
@set-mobile-fee-part="setMobileFeePart"
linkWidgetName="ServiceZipLinkWidget"
modalWidgetName="ServiceZipModalWidget" />
<alert
class="my-4"
cmsWidgetName="AlertMilitaryBaseZipWidget"
v-if="zipContainsMilitaryBase"
alertClass="alert-warning" />
<serviceTypeQuestion
v-model="selectedServiceType"
:isGlassServiceableInshop="isGlassServiceableInshop"
:isRecalibrationServiceableInshop="isRecalibrationServiceableInshop"
:isGlassServiceableMobile="isGlassServiceableMobile"
:isRecalibrationServiceableMobile="isRecalibrationServiceableMobile"
ref="serviceTypeQuestion"
groupName="serviceTypeQuestion"
cmsWidgetName="ServiceTypeQuestionWidget"
validationRules="option-required" />
<mobileLocationModalQuestions
v-if="selectedServiceType === 'Mobile'"
v-model="mobileLocationQuestions"
:mobileFeePart="mobileFeePart"
@set-mobile-fee-part="setMobileFeePart"
ref="mobileLocationModalQuestions"
linkWidgetName="MobileLocationLinkWidget"
modalWidgetName="MobileLocationModalWidget" />
<funnel-footer
cmsWidgetName="FunnelFooterWidget"
ref="funnelFooter"
:isForwardActionDisabled="!meta.valid || shouldDisableForwardAction"
@back-clicked="backButtonAction"
@ForwardClicked="forwardButtonAction" />
</div>
</div>
</Form>
</template>
<script>
// Components
import alert from "@/ux-components/alert/alert";
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question";
import mobileLocationModalQuestions from "@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions";
import serviceTypeQuestion from "@/layouts/service-location/service-type-question/service-type-question";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
import { Form } from "vee-validate";
// Supporting files
import baseMixin from "@/mixins/base-mixin.js";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import {
getPricedMobileFeePart,
getServiceabilityDetails,
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
import store from "@/store";
export default {
name: "service-location",
data() {
return {
streetAddress: this.getServiceAddressFromStore(),
apartmentNumberOrBusinessName: "",
city: this.getServiceCityFromStore(),
state: this.getServiceStateFromStore(),
zipCode: this.getServiceZipCodeFromStore(),
isVehicleProtected: null,
isGlassServiceableInshop: null,
isRecalibrationServiceableInshop: null,
isGlassServiceableMobile: null,
isRecalibrationServiceableMobile: null,
mobileFeePart: null,
zipContainsMilitaryBase: false,
selectedServiceType: null,
};
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
const getZipCodeData = baseMixin.methods.getZipCodeData(serviceZipCode);
const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
const serviceType = store.getters.damage.isRepair ? "Repair" : "Replace";
const parentAccountNumber = store.getters.payment.parentAccountNumber;
const billToAccountNumber = 87291;
const mobileFeePartPromise = getPricedMobileFeePart(
serviceZipCode,
serviceType,
parentAccountNumber,
billToAccountNumber
);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "mobileFeePart",
promise: mobileFeePartPromise,
},
{
resultKey: "serviceabilityDetails",
promise: serviceabilityDetailsPromise,
},
{
resultKey: "zipCodeData",
promise: getZipCodeData,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.setData(
resultMap.zipCodeData,
resultMap.serviceabilityDetails,
resultMap.mobileFeePart
);
});
},
computed: {
serviceZipCodeQuestion: {
get: function () {
return {
state: this.state,
zipCode: this.zipCode,
};
},
set: function (newValue) {
if (newValue.zipCode !== this.zipCode) {
this.resetMobileLocation();
}
this.state = newValue.state;
this.zipCode = newValue.zipCode;
},
},
mobileLocationQuestions: {
get: function () {
return {
addressQuestions: {
streetAddress: this.streetAddress,
apartmentNumberOrBusinessName: this.apartmentNumberOrBusinessName,
city: this.city,
state: this.state,
zipCode: this.zipCode,
},
isVehicleProtected: this.isVehicleProtected,
};
},
set: function (newValue) {
this.streetAddress = newValue.addressQuestions.streetAddress;
this.apartmentNumberOrBusinessName =
newValue.addressQuestions.apartmentNumberOrBusinessName;
this.city = newValue.addressQuestions.city;
this.state = newValue.addressQuestions.state;
this.zipCode = newValue.addressQuestions.zipCode;
this.isVehicleProtected = newValue.isVehicleProtected;
},
},
shouldDisableForwardAction() {
return this.zipContainsMilitaryBase;
},
},
methods: {
arePagePrerequisitesValid() {
return (
store.getters.lineItems.supportingItems !== null &&
store.getters.order.serviceLocation.zipCode !== null &&
store.getters.payment.isInsurance !== null
);
},
setData(zipCodeData, serviceabilityDetails, mobileFeePart) {
if (zipCodeData) {
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
}
if (serviceabilityDetails) {
this.setServiceabilityDetails(serviceabilityDetails);
}
if (mobileFeePart) {
this.mobileFeePart = mobileFeePart;
}
},
getServiceAddressFromStore() {
return store.getters.order.serviceLocation.address;
},
getServiceCityFromStore() {
return store.getters.order.serviceLocation.city;
},
getServiceStateFromStore() {
return store.getters.order.serviceLocation.state;
},
getServiceZipCodeFromStore() {
return store.getters.order.serviceLocation.zipCode;
},
setMobileFeePart(mobileFeePart) {
this.mobileFeePart = mobileFeePart;
},
resetMobileLocation() {
this.streetAddress = "";
this.apartmentNumberOrBusinessName = "";
this.city = "";
this.isVehicleProtected = null;
},
setServiceabilityDetails(serviceabilityDetails) {
this.isGlassServiceableInshop = serviceabilityDetails.isGlassServiceableInshop;
this.isRecalibrationServiceableInshop =
serviceabilityDetails.isRecalibrationServiceableInshop;
this.isGlassServiceableMobile = serviceabilityDetails.isGlassServiceableMobile;
this.isRecalibrationServiceableMobile =
serviceabilityDetails.isRecalibrationServiceableMobile;
},
backButtonAction() {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
forwardButtonAction() {
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal });
},
},
watch: {
zipCode: {
async handler(newValue, oldValue) {
if (newValue !== oldValue) {
baseMixin.methods.getZipCodeData(newValue).then((r) => {
this.zipContainsMilitaryBase = r.containsMilitaryBase;
});
}
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
const serviceabilityDetails = await getServiceabilityDetails(serviceZipCode);
this.setServiceabilityDetails(serviceabilityDetails.data);
},
},
},
components: {
alert,
serviceZipModalQuestion,
serviceTypeQuestion,
mobileLocationModalQuestions,
funnelHeader,
funnelFooter,
funnelSubHeader,
Form,
loadingModal,
},
};
</script>
<style lang="scss">
.question-text {
& > span {
text-align: center;
}
}
</style>