204 lines
7.1 KiB
Vue
204 lines
7.1 KiB
Vue
<template>
|
|
<Form
|
|
ref="theForm"
|
|
v-slot="{ meta }"
|
|
@submit="onSubmit"
|
|
@invalid-submit="onInvalidSubmit">
|
|
<div class="page-container-grouped-styles">
|
|
<div class="fade-on-route-transition sub-container make-tall">
|
|
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
|
<siteSubHeader
|
|
cmsWidgetName="SiteSubHeaderWidget"
|
|
justification="left"
|
|
issContainingPage="service-packages" />
|
|
<div class="mx-5">
|
|
<servicePackageQuestion
|
|
ref="servicePackage"
|
|
cmsWidgetName="ServicePackage"
|
|
groupName="ServicePackageQuestion"
|
|
:availableLineItems="availableLineItems"
|
|
:validationRules="rules.optionRequired"
|
|
isRequired
|
|
@vapsItemsSelected="vapsItemsSelectedAction"
|
|
@link-event="openModalAction" />
|
|
<p
|
|
class="caption disclaimer"
|
|
v-html="PriceDisclaimerText"></p>
|
|
<siteFooter
|
|
cmsWidgetName="SiteFooterWidget"
|
|
:isForwardActionDisabled="!meta.valid"
|
|
@back-clicked="backButtonAction"
|
|
@ForwardClicked="forwardButtonAction" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<loadingModal
|
|
ref="loadingModal"
|
|
:textSlides="loadingText" />
|
|
<contentGroupModal
|
|
ref="RainDefenseModal"
|
|
cmsWidgetName="RainDefenseModal" />
|
|
<contentGroupModal
|
|
ref="FrontWiperModal"
|
|
cmsWidgetName="FrontWiperModal" />
|
|
<contentGroupModal
|
|
ref="RearWiperModal"
|
|
cmsWidgetName="RearWiperModal" />
|
|
<contentGroupModal
|
|
ref="RecalModal"
|
|
cmsWidgetName="RecalModal" />
|
|
</Form>
|
|
</template>
|
|
|
|
<script>
|
|
// Components
|
|
import baseFormMixin from '@/mixins/base-form-mixin';
|
|
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
|
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
|
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
|
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
|
import loadingModal from '@/iss-components/loading-modal/loading-modal.vue';
|
|
import settleAllPromises from '@/helpers/layout-helper';
|
|
import { useMainStore } from '@/store';
|
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
|
import { Form } from 'vee-validate';
|
|
import allGlassPartsAndItemsHavePrices from '@/layouts/service-packages/service-package-helper/service-package-helper';
|
|
import globalRules from '@/constants/global-rules';
|
|
import servicePackageQuestion from '@/layouts/service-packages/service-package-question/service-package-question.vue';
|
|
|
|
const store = useMainStore();
|
|
|
|
export default {
|
|
name: 'service-packages',
|
|
components: {
|
|
siteHeader,
|
|
siteFooter,
|
|
siteSubHeader,
|
|
// eslint-disable-next-line vue/no-reserved-component-names
|
|
Form,
|
|
servicePackageQuestion,
|
|
loadingModal,
|
|
contentGroupModal
|
|
},
|
|
mixins: [baseFormMixin],
|
|
async beforeRouteEnter(to, from, next) {
|
|
// Call APIs
|
|
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
|
|
|
const wipersPromise = await store.getWipers();
|
|
const rainDefensePromise = await store.getRainDefense();
|
|
const supportingItemsPromise = await store.getSupportingItems();
|
|
const promiseResultMap = [
|
|
{
|
|
resultKey: 'cmsContent',
|
|
promise: cmsContentPromise
|
|
},
|
|
{
|
|
resultKey: 'wipers',
|
|
promise: wipersPromise
|
|
},
|
|
{
|
|
resultKey: 'rainDefense',
|
|
promise: rainDefensePromise
|
|
},
|
|
{
|
|
resultKey: 'supportingItems',
|
|
promise: supportingItemsPromise
|
|
}
|
|
];
|
|
const resultMap = await settleAllPromises(promiseResultMap);
|
|
|
|
const clonedGlassParts = store.order.lineItems.glassParts
|
|
? JSON.parse(JSON.stringify(store.order.lineItems.glassParts))
|
|
: [];
|
|
const availableLineItems = [
|
|
resultMap.rainDefense,
|
|
...resultMap.supportingItems,
|
|
...resultMap.wipers,
|
|
...clonedGlassParts
|
|
];
|
|
|
|
const pricingResults = await store.getPriceOrderItems(availableLineItems);
|
|
|
|
// Call the "next" function to complete the transition to this page.
|
|
next((vm) => {
|
|
vm.setCmsContent(resultMap.cmsContent);
|
|
vm.pricedGlassParts = clonedGlassParts;
|
|
vm.supportingItems = resultMap.supportingItems;
|
|
vm.availableLineItems = pricingResults;
|
|
});
|
|
},
|
|
data() {
|
|
return {
|
|
selectedVaps: [],
|
|
availableLineItems: [],
|
|
supportingItems: [],
|
|
pricedGlassParts: [],
|
|
loadingText: [
|
|
'Finding shops near you',
|
|
'Looking for dates',
|
|
'Searching for times',
|
|
'Nearly there',
|
|
'Finishing up'
|
|
],
|
|
rules: {
|
|
optionRequired: globalRules.OPTION_REQUIRED
|
|
}
|
|
};
|
|
},
|
|
computed: {
|
|
PriceDisclaimerText() {
|
|
return this.getCmsContent('PriceDisclaimerWidget', 'Text');
|
|
}
|
|
},
|
|
methods: {
|
|
openModalAction(modalName) {
|
|
this.$refs[modalName.args].openModal();
|
|
},
|
|
arePagePrerequisitesValid() {
|
|
return (
|
|
store.order.serviceLocation.zipCode
|
|
&& store.order.serviceLocation.zipCodeCtu
|
|
&& (store.order.damage.isRepair
|
|
|| (store.order.lineItems?.glassParts != null
|
|
&& store.order.lineItems.glassParts.length > 0))
|
|
);
|
|
},
|
|
vapsItemsSelectedAction(vapsItemsSelected) {
|
|
this.selectedVaps = vapsItemsSelected;
|
|
},
|
|
backButtonAction() {
|
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
|
},
|
|
forwardButtonAction() {
|
|
const parts = { glassParts: this.pricedGlassParts, supportingItems: this.supportingItems, vaps: this.selectedVaps };
|
|
if (!allGlassPartsAndItemsHavePrices(parts)) {
|
|
window.console.error('One or more items have no price assigned!');
|
|
}
|
|
if (this.pricedGlassParts.length > 0) {
|
|
store.saveGlassParts(this.pricedGlassParts);
|
|
}
|
|
store.saveSupportingItems(this.supportingItems);
|
|
store.saveVaps(this.selectedVaps);
|
|
|
|
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.subheader-secondary {
|
|
margin-top: .5rem;
|
|
padding: 0px;
|
|
}
|
|
|
|
.disclaimer {
|
|
margin: 1.3rem 0 1.5rem 0;
|
|
|
|
a {
|
|
color: #4D5151;
|
|
font-weight: 400;
|
|
}
|
|
}
|
|
</style>
|