WIP update files with updated ESLint settings.
This commit is contained in:
parent
fa3c7711f6
commit
7e5c8fd1b6
17 changed files with 3204 additions and 3369 deletions
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -37,7 +37,7 @@
|
|||
"@vue/vue3-jest": "^27.0.0-alpha.1",
|
||||
"axios-mock-adapter": "^1.21.5",
|
||||
"babel-jest": "^27.0.6",
|
||||
"eslint": "8.45.0",
|
||||
"eslint": "^8.45.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-import-resolver-alias": "1.1.2",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
"@vue/vue3-jest": "^27.0.0-alpha.1",
|
||||
"axios-mock-adapter": "^1.21.5",
|
||||
"babel-jest": "^27.0.6",
|
||||
"eslint": "8.45.0",
|
||||
"eslint": "^8.45.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-import-resolver-alias": "1.1.2",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
|
|
@ -61,4 +61,4 @@
|
|||
"vitest": "^0.33.0",
|
||||
"volar-service-vetur": "latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@
|
|||
<img :src="footerImageURL" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "footer-image",
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
<script>
|
||||
export default {
|
||||
name: 'footer-image',
|
||||
props: {
|
||||
cmsWidgetName: String
|
||||
},
|
||||
computed: {
|
||||
computed: {
|
||||
footerImageURL() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'FooterImageURL');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.footerImage {
|
||||
|
|
|
|||
|
|
@ -1,47 +1,50 @@
|
|||
<template>
|
||||
<div>
|
||||
<footer
|
||||
id="infoBox"
|
||||
class="footer container-fluid g-5 my-5 px-0">
|
||||
<div
|
||||
class="row d-flex vw-100 mx-0"
|
||||
:class="[
|
||||
isStackedVertically
|
||||
? 'flex-column align-items-stretch'
|
||||
: 'flex-row-reverse align-items-center'
|
||||
]">
|
||||
<div
|
||||
id="stacked"
|
||||
class="col button-col d-flex px-0">
|
||||
<buttonMain
|
||||
v-if="!isForwardButtonHidden"
|
||||
ref="buttonMain"
|
||||
isPrimary
|
||||
:buttonText="buttonText"
|
||||
loaderColor="white"
|
||||
:class="(disableForwardAction || isForwardActionDisabled) && 'form-test-invalid'"
|
||||
:aria-disabled="isForwardActionDisabled"
|
||||
:isDisabled="isForwardActionDisabled"
|
||||
data-bs-target="#footerModal"
|
||||
data-bs-dismiss="modal"
|
||||
data-test-id="site-footer-main-button"
|
||||
@clickEvent="buttonClick" />
|
||||
</div>
|
||||
<div
|
||||
v-if="!isBackButtonHidden"
|
||||
class="col-auto link-col py-1 px-0 text-break">
|
||||
<textLink
|
||||
linkType="navigation"
|
||||
:text="backLink"
|
||||
href="javascript:void(0)"
|
||||
data-bs-target="#footerModal"
|
||||
data-bs-dismiss="modal"
|
||||
data-test-id="site-footer-back-button"
|
||||
@clickEvent="linkClick" />
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div>
|
||||
<footer
|
||||
id="infoBox"
|
||||
class="footer container-fluid g-5 my-5 px-0">
|
||||
<div
|
||||
class="row d-flex vw-100 mx-0"
|
||||
:class="[
|
||||
isStackedVertically
|
||||
? 'flex-column align-items-stretch'
|
||||
: 'flex-row-reverse align-items-center',
|
||||
]">
|
||||
<div
|
||||
id="stacked"
|
||||
class="col button-col d-flex px-0">
|
||||
<buttonMain
|
||||
v-if="!isForwardButtonHidden"
|
||||
ref="buttonMain"
|
||||
isPrimary
|
||||
:buttonText="buttonText"
|
||||
loaderColor="white"
|
||||
:class="
|
||||
(disableForwardAction || isForwardActionDisabled) &&
|
||||
'form-test-invalid'
|
||||
"
|
||||
:aria-disabled="isForwardActionDisabled"
|
||||
:isDisabled="isForwardActionDisabled"
|
||||
data-bs-target="#footerModal"
|
||||
data-bs-dismiss="modal"
|
||||
data-test-id="site-footer-main-button"
|
||||
@clickEvent="buttonClick" />
|
||||
</div>
|
||||
<div
|
||||
v-if="!isBackButtonHidden"
|
||||
class="col-auto link-col py-1 px-0 text-break">
|
||||
<textLink
|
||||
linkType="navigation"
|
||||
:text="backLink"
|
||||
href="javascript:void(0)"
|
||||
data-bs-target="#footerModal"
|
||||
data-bs-dismiss="modal"
|
||||
data-test-id="site-footer-back-button"
|
||||
@clickEvent="linkClick" />
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -53,7 +56,7 @@ export default {
|
|||
name: 'site-footer',
|
||||
components: {
|
||||
textLink,
|
||||
buttonMain,
|
||||
buttonMain
|
||||
},
|
||||
props: {
|
||||
isForwardActionDisabled: Boolean,
|
||||
|
|
@ -80,18 +83,20 @@ export default {
|
|||
: this.getCmsContent(this.cmsWidgetName, 'ForwardButtonText');
|
||||
},
|
||||
footerImageURL() {
|
||||
//return this.getCmsContent(this.cmsWidgetName, 'FooterImageURL');
|
||||
// return this.getCmsContent(this.cmsWidgetName, 'FooterImageURL');
|
||||
const output = this.getCmsContent(this.cmsWidgetName, 'FooterImageURL');
|
||||
console.log("original image", output);
|
||||
console.log('original image', output);
|
||||
return output;
|
||||
},
|
||||
includeFooterImage() {
|
||||
const currentPageName = this.getPageNameByQueryString();
|
||||
return (currentPageName.toLowerCase() === issPageValues.WELCOME_PAGE);
|
||||
return currentPageName.toLowerCase() === issPageValues.WELCOME_PAGE;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.paddingHeight = this.includeFooterImage ? this.getFooterInfoBoxHeight() + 16 : this.getFooterInfoBoxHeight() + 24;
|
||||
this.paddingHeight = this.includeFooterImage
|
||||
? this.getFooterInfoBoxHeight() + 16
|
||||
: this.getFooterInfoBoxHeight() + 24;
|
||||
this.$nextTick(() => {
|
||||
window.addEventListener('resize', this.onResize);
|
||||
});
|
||||
|
|
@ -133,63 +138,60 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.footer {
|
||||
display: flex;
|
||||
overflow: visible;
|
||||
a {
|
||||
display: flex;
|
||||
overflow: visible;
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
justify-content: center;
|
||||
}
|
||||
.col,
|
||||
.col-auto,
|
||||
.col button {
|
||||
width: 100%;
|
||||
}
|
||||
@media only screen and (min-width: 340px) {
|
||||
.col,
|
||||
.col-auto,
|
||||
.col button {
|
||||
width: 100%;
|
||||
width: auto;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
@media only screen and (min-width: 340px) {
|
||||
.col,
|
||||
.col-auto,
|
||||
.col button {
|
||||
width: auto;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.btn-primary {
|
||||
width: auto;
|
||||
}
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.btn-primary {
|
||||
width: auto;
|
||||
}
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
& > .container-fluid {
|
||||
overflow-x: visible; // needed to fix hidden footer on some iphones
|
||||
& > .container-fluid {
|
||||
overflow-x: visible; // needed to fix hidden footer on some iphones
|
||||
}
|
||||
div.flex-column {
|
||||
.btn-primary {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
div.flex-column {
|
||||
.btn-primary {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
div.link-col {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
div.link-col {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footerImage
|
||||
{
|
||||
text-align: center;
|
||||
position: sticky;
|
||||
.footerImage {
|
||||
text-align: center;
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 340px) {
|
||||
.footerImage
|
||||
{
|
||||
bottom: 78px;
|
||||
}
|
||||
.footerImage {
|
||||
bottom: 78px;
|
||||
}
|
||||
}
|
||||
|
||||
#siteFooterImage
|
||||
{
|
||||
width: 100%;
|
||||
#siteFooterImage {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@
|
|||
ref="contact-details-form"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader ref="siteHeader" :cmsWidgetName="widget.siteHeader" />
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
:cmsWidgetName="widget.siteHeader" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -17,8 +18,7 @@
|
|||
id="sub-header"
|
||||
ref="siteSubHeader"
|
||||
class="mt-5"
|
||||
:cmsWidgetName="widget.siteSubHeader"
|
||||
/>
|
||||
:cmsWidgetName="widget.siteSubHeader" />
|
||||
<textboxQuestion
|
||||
ref="firstNameQuestion"
|
||||
v-model="firstName"
|
||||
|
|
@ -26,8 +26,7 @@
|
|||
inputId="firstName"
|
||||
:cmsWidgetName="widget.firstNameQuestion"
|
||||
isRequired
|
||||
:validationRules="rules.firstName"
|
||||
/>
|
||||
:validationRules="rules.firstName" />
|
||||
<textboxQuestion
|
||||
ref="lastNameQuestion"
|
||||
v-model="lastName"
|
||||
|
|
@ -35,8 +34,7 @@
|
|||
inputId="lastName"
|
||||
:cmsWidgetName="widget.lastNameQuestion"
|
||||
isRequired
|
||||
:validationRules="rules.lastName"
|
||||
/>
|
||||
:validationRules="rules.lastName" />
|
||||
<textboxQuestion
|
||||
ref="emailQuestion"
|
||||
v-model="emailAddress"
|
||||
|
|
@ -44,8 +42,7 @@
|
|||
inputId="emailAddress"
|
||||
:cmsWidgetName="widget.emailQuestion"
|
||||
isRequired
|
||||
:validationRules="rules.emailAddress"
|
||||
/>
|
||||
:validationRules="rules.emailAddress" />
|
||||
<textboxQuestion
|
||||
ref="phoneNumberQuestion"
|
||||
v-model="phoneNumber"
|
||||
|
|
@ -54,8 +51,7 @@
|
|||
:cmsWidgetName="widget.phoneNumberQuestion"
|
||||
isRequired
|
||||
:mask="phoneMask"
|
||||
:validationRules="rules.phoneNumber"
|
||||
/>
|
||||
:validationRules="rules.phoneNumber" />
|
||||
<checkbox
|
||||
ref="requestTextUpdatesCheckbox"
|
||||
v-model="requestTextUpdates"
|
||||
|
|
@ -63,8 +59,7 @@
|
|||
class="mt-3"
|
||||
checkboxName="requestTextUpdates"
|
||||
buttonID="requestTextUpdates"
|
||||
:checkboxLabel="requestTextUpdatesCheckboxText"
|
||||
/>
|
||||
:checkboxLabel="requestTextUpdatesCheckboxText" />
|
||||
<textareaQuestion
|
||||
ref="notesQuestion"
|
||||
v-model="notesForTechnician"
|
||||
|
|
@ -74,25 +69,24 @@
|
|||
:isRequired="false"
|
||||
:cmsWidgetName="widget.notesQuestion"
|
||||
maxLength="250"
|
||||
:inputRows="4"
|
||||
/>
|
||||
<p ref="disclaimerText" class="caption dark-gray mt-6">
|
||||
:inputRows="4" />
|
||||
<p
|
||||
ref="disclaimerText"
|
||||
class="caption dark-gray mt-6">
|
||||
{{ textUpdateDisclaimerText }} I also agree to Safelite's
|
||||
<textLink
|
||||
ref="privacyPolicyLink"
|
||||
class="normal-line-height"
|
||||
linkType="text"
|
||||
text="Privacy Policy"
|
||||
href="//www.safelite.com/privacy-center"
|
||||
/>
|
||||
href="//www.safelite.com/privacy-center" />
|
||||
and
|
||||
<textLink
|
||||
ref="termsOfUseLink"
|
||||
class="normal-line-height"
|
||||
linkType="text"
|
||||
text="Terms of Use"
|
||||
href="//www.safelite.com/terms-of-use"
|
||||
/>.
|
||||
href="//www.safelite.com/terms-of-use" />.
|
||||
</p>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
|
|
@ -100,8 +94,7 @@
|
|||
:cmsWidgetName="widget.siteFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack"
|
||||
/>
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -109,117 +102,117 @@
|
|||
</template>
|
||||
<script>
|
||||
// Components
|
||||
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 textboxQuestion from "@/digital-components/textbox-question/textbox-question.vue";
|
||||
import checkbox from "@/ux-components/checkbox/checkbox.vue";
|
||||
import textareaQuestion from "@/digital-components/textarea-question/textarea-question.vue";
|
||||
import textLink from "@/ux-components/text-link/text-link.vue";
|
||||
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 textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
import checkbox from '@/ux-components/checkbox/checkbox.vue';
|
||||
import textareaQuestion from '@/digital-components/textarea-question/textarea-question.vue';
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper.js";
|
||||
import { Form } from "vee-validate";
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import { useMainStore } from "@/store/index.js";
|
||||
import globalRules from "@/constants/global-rules.js";
|
||||
import MaskaFormattedMasks from "@/constants/maska-masks";
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper.js';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
import globalRules from '@/constants/global-rules.js';
|
||||
import MaskaFormattedMasks from '@/constants/maska-masks';
|
||||
|
||||
export default {
|
||||
name: "contact-details",
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
textboxQuestion,
|
||||
checkbox,
|
||||
textareaQuestion,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
textLink,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContent = await fetchCmsContentForPage(to.query.issPage);
|
||||
name: 'contact-details',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
textboxQuestion,
|
||||
checkbox,
|
||||
textareaQuestion,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
textLink
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContent = await fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(cmsContent);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
const {
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
phoneNumber,
|
||||
requestTextUpdates,
|
||||
notesForTechnician,
|
||||
} = useMainStore().contactInfo;
|
||||
return {
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
phoneNumber,
|
||||
requestTextUpdates,
|
||||
notesForTechnician,
|
||||
widget: {
|
||||
siteHeader: "SiteHeaderWidget",
|
||||
siteSubHeader: "SiteSubHeaderWidget",
|
||||
firstNameQuestion: "FirstNameQuestionWidget",
|
||||
lastNameQuestion: "LastNameQuestionWidget",
|
||||
emailQuestion: "EmailQuestionWidget",
|
||||
phoneNumberQuestion: "PhoneNumberQuestionWidget",
|
||||
requestTextUpdates: "TextContentWidget",
|
||||
notesQuestion: "NotesQuestionWidget",
|
||||
disclaimer: "TextUpdateDisclaimerWidget",
|
||||
siteFooter: "SiteFooterWidget",
|
||||
},
|
||||
rules: {
|
||||
firstName: globalRules.FIRST_NAME_REQUIRED,
|
||||
lastName: globalRules.LAST_NAME_REQUIRED,
|
||||
emailAddress: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
next((vm) => {
|
||||
vm.setCmsContent(cmsContent);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
const {
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
phoneNumber,
|
||||
requestTextUpdates,
|
||||
notesForTechnician
|
||||
} = useMainStore().contactInfo;
|
||||
return {
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
phoneNumber,
|
||||
requestTextUpdates,
|
||||
notesForTechnician,
|
||||
widget: {
|
||||
siteHeader: 'SiteHeaderWidget',
|
||||
siteSubHeader: 'SiteSubHeaderWidget',
|
||||
firstNameQuestion: 'FirstNameQuestionWidget',
|
||||
lastNameQuestion: 'LastNameQuestionWidget',
|
||||
emailQuestion: 'EmailQuestionWidget',
|
||||
phoneNumberQuestion: 'PhoneNumberQuestionWidget',
|
||||
requestTextUpdates: 'TextContentWidget',
|
||||
notesQuestion: 'NotesQuestionWidget',
|
||||
disclaimer: 'TextUpdateDisclaimerWidget',
|
||||
siteFooter: 'SiteFooterWidget'
|
||||
},
|
||||
rules: {
|
||||
firstName: globalRules.FIRST_NAME_REQUIRED,
|
||||
lastName: globalRules.LAST_NAME_REQUIRED,
|
||||
emailAddress: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* @returns {string} Returns the CMS text associated with the "get text updates" checkbox.
|
||||
*/
|
||||
requestTextUpdatesCheckboxText() {
|
||||
return `${this.getCmsContent(this.widget.requestTextUpdates, "Text")}*`;
|
||||
requestTextUpdatesCheckboxText() {
|
||||
return `${this.getCmsContent(this.widget.requestTextUpdates, 'Text')}*`;
|
||||
},
|
||||
/**
|
||||
* @returns {string} Returns the CMS text associated with the "get text updates" checkbox.
|
||||
*/
|
||||
textUpdateDisclaimerText() {
|
||||
return `*${this.getCmsContent(this.widget.disclaimer, 'Text')}`;
|
||||
},
|
||||
phoneMask() {
|
||||
return MaskaFormattedMasks.PHONE_NUMBER;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @returns {string} Returns the CMS text associated with the "get text updates" checkbox.
|
||||
*/
|
||||
textUpdateDisclaimerText() {
|
||||
return `*${this.getCmsContent(this.widget.disclaimer, "Text")}`;
|
||||
},
|
||||
phoneMask() {
|
||||
return MaskaFormattedMasks.PHONE_NUMBER;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
methods: {
|
||||
/**
|
||||
* @summary Steps to perform when forward button clicked.
|
||||
*/
|
||||
forwardButtonAction() {
|
||||
const contactInfo = {
|
||||
firstName: this.firstName,
|
||||
lastName: this.lastName,
|
||||
emailAddress: this.emailAddress,
|
||||
phoneNumber: this.phoneNumber,
|
||||
requestTextUpdates: this.requestTextUpdates,
|
||||
notesForTechnician: this.notesForTechnician,
|
||||
};
|
||||
useMainStore().updateContactInfo(contactInfo);
|
||||
const scenario =
|
||||
forwardButtonAction() {
|
||||
const contactInfo = {
|
||||
firstName: this.firstName,
|
||||
lastName: this.lastName,
|
||||
emailAddress: this.emailAddress,
|
||||
phoneNumber: this.phoneNumber,
|
||||
requestTextUpdates: this.requestTextUpdates,
|
||||
notesForTechnician: this.notesForTechnician
|
||||
};
|
||||
useMainStore().updateContactInfo(contactInfo);
|
||||
const scenario =
|
||||
useMainStore().order.serviceLocation.IsSafeliteProvider === false
|
||||
? this.navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP
|
||||
: this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP;
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
},
|
||||
},
|
||||
? this.navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP
|
||||
: this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP;
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,16 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<loadingModal ref="loadingModal" :textSlides="loadingText" />
|
||||
<siteHeader ref="siteHeader" cmsWidgetName="SiteHeaderWidget" />
|
||||
<loadingModal
|
||||
ref="loadingModal"
|
||||
:textSlides="loadingText" />
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center pt-5">
|
||||
|
|
@ -17,34 +20,28 @@
|
|||
<h5
|
||||
ref="siteSubHeader"
|
||||
class="text-center text-black"
|
||||
v-html="coverageStatementSubHeader"
|
||||
></h5>
|
||||
v-html="coverageStatementSubHeader"></h5>
|
||||
<div
|
||||
ref="explanatoryText"
|
||||
class="body-text text-center mt-2"
|
||||
v-html="explanatoryText"
|
||||
></div>
|
||||
v-html="explanatoryText"></div>
|
||||
<div
|
||||
ref="secondaryText"
|
||||
class="text-center mt-4 mb-1 fw-bold text-black"
|
||||
v-html="secondaryText"
|
||||
></div>
|
||||
v-html="secondaryText"></div>
|
||||
<div
|
||||
v-if="verifiedDeductible"
|
||||
class="d-flex justify-content-center cost"
|
||||
>
|
||||
class="d-flex justify-content-center cost">
|
||||
{{ deductibleForDisplay }}
|
||||
</div>
|
||||
<div
|
||||
v-if="isQuoteDisplayed"
|
||||
class="d-flex justify-content-center cost mb-0"
|
||||
>
|
||||
class="d-flex justify-content-center cost mb-0">
|
||||
{{ servicePriceForDisplay }}
|
||||
</div>
|
||||
<div
|
||||
v-if="verifiedITAC"
|
||||
class="d-flex justify-content-center mb-4 deductible-text"
|
||||
>
|
||||
class="d-flex justify-content-center mb-4 deductible-text">
|
||||
{{ deductibleText }}
|
||||
<span class="text-success fw-bold">{{ deductibleForDisplay }}</span>
|
||||
</div>
|
||||
|
|
@ -56,14 +53,14 @@
|
|||
:manualHeadline="verifiedItacAlertHeader"
|
||||
:manualCopy="verifiedItacAlertBody"
|
||||
alertClass="alert-success"
|
||||
:isDismissible="false"
|
||||
>
|
||||
:isDismissible="false">
|
||||
</alert>
|
||||
<div
|
||||
class="fw-bold text-black mt-5 mb-2"
|
||||
v-html="nextStepsHeader"
|
||||
></div>
|
||||
<div class="body-text" v-html="nextStepsBody"></div>
|
||||
v-html="nextStepsHeader"></div>
|
||||
<div
|
||||
class="body-text"
|
||||
v-html="nextStepsBody"></div>
|
||||
<buttonQuestion
|
||||
v-if="isQuoteDisplayed"
|
||||
v-model="selectedProvider"
|
||||
|
|
@ -73,407 +70,393 @@
|
|||
groupName="ServiceProviderQuestionOption"
|
||||
buttonTypeString="listButton"
|
||||
isRequired
|
||||
:validationRules="rules.selectionRequired"
|
||||
>
|
||||
:validationRules="rules.selectionRequired">
|
||||
</buttonQuestion>
|
||||
<text-block
|
||||
v-if="isQuoteDisplayed"
|
||||
cmsWidgetName="DisclaimerWidget"
|
||||
typeStyle="caption"
|
||||
/>
|
||||
typeStyle="caption" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBackByVehicleQuestions"
|
||||
@forwardClicked="navigateForward"
|
||||
/>
|
||||
@forwardClicked="navigateForward" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<recalModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
<recalModal
|
||||
ref="RecalModal"
|
||||
cmsWidgetName="RecalModal" />
|
||||
<contentGroupModal
|
||||
ref="DeductibleModal"
|
||||
cmsWidgetName="DeductibleModal"
|
||||
class="deductible-modal"
|
||||
/>
|
||||
class="deductible-modal" />
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
// Import Component
|
||||
import { Form } from "vee-validate";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import recalModal from "@/layouts/coverage-statement/recal-modal/recal-modal.vue";
|
||||
import alert from "@/ux-components/alert/alert.vue";
|
||||
import contentGroupModal from "@/iss-components/content-group-modal/content-group-modal.vue";
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question.vue";
|
||||
import loadingModal from "@/iss-components/loading-modal/loading-modal.vue";
|
||||
import textBlock from "@/digital-components/text-block/text-block.vue";
|
||||
import { Form } from 'vee-validate';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import recalModal from '@/layouts/coverage-statement/recal-modal/recal-modal.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import loadingModal from '@/iss-components/loading-modal/loading-modal.vue';
|
||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||
|
||||
// Import Supporting Files
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
setupModalLinks,
|
||||
processIfStatements,
|
||||
} from "@/helpers/cms-content-helper.js";
|
||||
import settleAllPromises from "@/helpers/layout-helper.js";
|
||||
import { getDamageString } from "@/helpers/damage-helper.js";
|
||||
import { useMainStore } from "@/store/index.js";
|
||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin.js";
|
||||
import globalRules from "@/constants/global-rules.js";
|
||||
import baseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import navigationScenarios from "@/router/router-constants/navigation-scenarios.js";
|
||||
import issPageValues from "@/router/router-constants/issPage-values";
|
||||
import bailoutMessage from "@/constants/bailoutMessage";
|
||||
import coverageStatuses from "@/constants/coverage-statuses";
|
||||
import widgetFields from "@/constants/cms-widget-fields.js";
|
||||
import getPriceOfLineItems from "@/helpers/price-calculator.js";
|
||||
import { formatAmountInDollars } from "@/helpers/text-helper.js";
|
||||
fetchCmsContentForPage,
|
||||
setupModalLinks,
|
||||
processIfStatements
|
||||
} from '@/helpers/cms-content-helper.js';
|
||||
import settleAllPromises from '@/helpers/layout-helper.js';
|
||||
import { getDamageString } from '@/helpers/damage-helper.js';
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin.js';
|
||||
import globalRules from '@/constants/global-rules.js';
|
||||
import baseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import navigationScenarios from '@/router/router-constants/navigation-scenarios.js';
|
||||
import issPageValues from '@/router/router-constants/issPage-values';
|
||||
import bailoutMessage from '@/constants/bailoutMessage';
|
||||
import coverageStatuses from '@/constants/coverage-statuses';
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
import getPriceOfLineItems from '@/helpers/price-calculator.js';
|
||||
import { formatAmountInDollars } from '@/helpers/text-helper.js';
|
||||
|
||||
const SAFELITE_PROVIDER = "Safelite";
|
||||
const SAFELITE_PROVIDER = 'Safelite';
|
||||
|
||||
export default {
|
||||
name: "coverage-statement",
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
recalModal,
|
||||
alert,
|
||||
contentGroupModal,
|
||||
buttonQuestion,
|
||||
loadingModal,
|
||||
textBlock,
|
||||
},
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
name: 'coverage-statement',
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
recalModal,
|
||||
alert,
|
||||
contentGroupModal,
|
||||
buttonQuestion,
|
||||
loadingModal,
|
||||
textBlock
|
||||
},
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to?.query?.issPage);
|
||||
const supportingItemsPromise = await useMainStore().getSupportingItems();
|
||||
const cmsContentPromise = fetchCmsContentForPage(to?.query?.issPage);
|
||||
const supportingItemsPromise = await useMainStore().getSupportingItems();
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "supportingItems",
|
||||
promise: supportingItemsPromise,
|
||||
},
|
||||
];
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'supportingItems',
|
||||
promise: supportingItemsPromise
|
||||
}
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
const clonedGlassParts = useMainStore().lineItems.glassParts
|
||||
? JSON.parse(JSON.stringify(useMainStore().lineItems.glassParts))
|
||||
: [];
|
||||
const availableLineItems = [
|
||||
...(resultMap.supportingItems ?? []),
|
||||
...(clonedGlassParts ?? []),
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
const clonedGlassParts = useMainStore().lineItems.glassParts
|
||||
? JSON.parse(JSON.stringify(useMainStore().lineItems.glassParts))
|
||||
: [];
|
||||
const availableLineItems = [
|
||||
...(resultMap.supportingItems ?? []),
|
||||
...(clonedGlassParts ?? [])
|
||||
];
|
||||
|
||||
let hasBailedOut = false;
|
||||
let pricingResults = [];
|
||||
if (
|
||||
useMainStore().policy.policyLookupSuccessful &&
|
||||
useMainStore().vehicle.policyVehicleId >= 0
|
||||
) {
|
||||
await useMainStore().getFinalDeductible();
|
||||
pricingResults = await useMainStore()
|
||||
.getPriceOrderItems(availableLineItems)
|
||||
.catch((err) => {
|
||||
useMainStore().setBailout(
|
||||
bailoutMessage.pricingResponseError(
|
||||
availableLineItems.map((li) => li.partNumber),
|
||||
{ code: err.code, message: err.message, data: err.data }
|
||||
)
|
||||
);
|
||||
hasBailedOut = true;
|
||||
next(`/?issPage=${issPageValues.BAILOUT_PAGE}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasBailedOut) {
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.setSupportingItems(resultMap.supportingItems);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
vm.setBaseServiceLineItems(pricingResults);
|
||||
vm.$refs.loadingModal.showModal();
|
||||
vm.initializeComponent();
|
||||
if (!vm.unverified) {
|
||||
useMainStore().disableKeyFields();
|
||||
let hasBailedOut = false;
|
||||
let pricingResults = [];
|
||||
if (
|
||||
useMainStore().policy.policyLookupSuccessful
|
||||
&& useMainStore().vehicle.policyVehicleId >= 0
|
||||
) {
|
||||
await useMainStore().getFinalDeductible();
|
||||
pricingResults = await useMainStore()
|
||||
.getPriceOrderItems(availableLineItems)
|
||||
.catch((err) => {
|
||||
useMainStore().setBailout(bailoutMessage.pricingResponseError(
|
||||
availableLineItems.map((li) => li.partNumber),
|
||||
{ code: err.code, message: err.message, data: err.data }
|
||||
));
|
||||
hasBailedOut = true;
|
||||
next(`/?issPage=${issPageValues.BAILOUT_PAGE}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasBailedOut) {
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.setSupportingItems(resultMap.supportingItems);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
vm.setBaseServiceLineItems(pricingResults);
|
||||
vm.$refs.loadingModal.showModal();
|
||||
vm.initializeComponent();
|
||||
if (!vm.unverified) {
|
||||
useMainStore().disableKeyFields();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const { isRepair } = useMainStore().damage;
|
||||
const { policyLookupSuccessful, noCoverage } = useMainStore().policy;
|
||||
return {
|
||||
isRepair,
|
||||
policyLookupSuccessful,
|
||||
isNoComp: noCoverage ?? false,
|
||||
baseServiceLineItems: [],
|
||||
selectedProvider: "",
|
||||
deductibleText: "Your deductible is",
|
||||
// TODO update when design team gives appropriate text
|
||||
loadingText: [
|
||||
"Connecting to your insurance company",
|
||||
"Nearly there",
|
||||
"Finishing up",
|
||||
],
|
||||
rules: {
|
||||
selectionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
supportingItems: null,
|
||||
widget: {
|
||||
subheader: "SiteSubHeaderWidget",
|
||||
verifiedItacAlert: "VerifiedITACAlert",
|
||||
explanatoryText: "ExplanatoryTextWidget",
|
||||
nextStep: "NextStepsWidget",
|
||||
serviceProviderQuestion: "ServiceProviderQuestion",
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
coverageStatementSubHeader() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.subheader,
|
||||
widgetFields.SUB_HEADER_WIDGET.SUB_HEADER_TEXT
|
||||
);
|
||||
},
|
||||
verifiedItacAlertHeader() {
|
||||
return this.getCmsContent(
|
||||
this.widget.verifiedItacAlert,
|
||||
widgetFields.ALERT_WIDGET.HEADLINE_TEXT
|
||||
);
|
||||
data() {
|
||||
const { isRepair } = useMainStore().damage;
|
||||
const { policyLookupSuccessful, noCoverage } = useMainStore().policy;
|
||||
return {
|
||||
isRepair,
|
||||
policyLookupSuccessful,
|
||||
isNoComp: noCoverage ?? false,
|
||||
baseServiceLineItems: [],
|
||||
selectedProvider: '',
|
||||
deductibleText: 'Your deductible is',
|
||||
// TODO update when design team gives appropriate text
|
||||
loadingText: [
|
||||
'Connecting to your insurance company',
|
||||
'Nearly there',
|
||||
'Finishing up'
|
||||
],
|
||||
rules: {
|
||||
selectionRequired: globalRules.OPTION_REQUIRED
|
||||
},
|
||||
supportingItems: null,
|
||||
widget: {
|
||||
subheader: 'SiteSubHeaderWidget',
|
||||
verifiedItacAlert: 'VerifiedITACAlert',
|
||||
explanatoryText: 'ExplanatoryTextWidget',
|
||||
nextStep: 'NextStepsWidget',
|
||||
serviceProviderQuestion: 'ServiceProviderQuestion'
|
||||
}
|
||||
};
|
||||
},
|
||||
verifiedItacAlertBody() {
|
||||
return this.getCmsContent(
|
||||
this.widget.verifiedItacAlert,
|
||||
widgetFields.ALERT_WIDGET.BODY_TEXT
|
||||
)?.replaceAll("{custom:costSavings}", this.itacCostSavingsForDisplay);
|
||||
computed: {
|
||||
coverageStatementSubHeader() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.subheader,
|
||||
widgetFields.SUB_HEADER_WIDGET.SUB_HEADER_TEXT
|
||||
);
|
||||
},
|
||||
verifiedItacAlertHeader() {
|
||||
return this.getCmsContent(
|
||||
this.widget.verifiedItacAlert,
|
||||
widgetFields.ALERT_WIDGET.HEADLINE_TEXT
|
||||
);
|
||||
},
|
||||
verifiedItacAlertBody() {
|
||||
return this.getCmsContent(
|
||||
this.widget.verifiedItacAlert,
|
||||
widgetFields.ALERT_WIDGET.BODY_TEXT
|
||||
)?.replaceAll('{custom:costSavings}', this.itacCostSavingsForDisplay);
|
||||
},
|
||||
secondaryText() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.subheader,
|
||||
widgetFields.SUB_HEADER_WIDGET.SECONDARY_TEXT
|
||||
);
|
||||
},
|
||||
explanatoryText() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.explanatoryText,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||
);
|
||||
},
|
||||
nextStepsHeader() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.nextStep,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT
|
||||
);
|
||||
},
|
||||
nextStepsBody() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.nextStep,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||
)?.replaceAll('{custom:damage}', this.damageText);
|
||||
},
|
||||
damageText() {
|
||||
const damageString = getDamageString();
|
||||
return damageString === 'match' ? '' : damageString;
|
||||
},
|
||||
deductibleValue() {
|
||||
return useMainStore().order.currentDeductible;
|
||||
},
|
||||
deductibleForDisplay() {
|
||||
return formatAmountInDollars(this.deductibleValue);
|
||||
},
|
||||
registerClaimSuccessful() {
|
||||
return useMainStore().payment.insuranceCoverage.isVerified;
|
||||
},
|
||||
verifiedNoComp() {
|
||||
return this.policyLookupSuccessful && this.isNoComp;
|
||||
},
|
||||
verifiedITAC() {
|
||||
return (
|
||||
this.policyLookupSuccessful
|
||||
&& !this.isNoComp
|
||||
&& this.deductibleValue > this.totalServicePrice
|
||||
);
|
||||
},
|
||||
coveredAndServicePriceAboveOrEqualDeductible() {
|
||||
return (
|
||||
!this.verifiedNoComp && this.totalServicePrice >= this.deductibleValue
|
||||
);
|
||||
},
|
||||
verifiedDeductible() {
|
||||
return useMainStore().isClaimRegistrationRequired
|
||||
? this.registerClaimSuccessful
|
||||
&& this.coveredAndServicePriceAboveOrEqualDeductible
|
||||
&& this.deductibleValue !== null
|
||||
: this.policyLookupSuccessful
|
||||
&& this.coveredAndServicePriceAboveOrEqualDeductible;
|
||||
},
|
||||
unverified() {
|
||||
return (
|
||||
!this.verifiedDeductible && !this.verifiedITAC && !this.verifiedNoComp
|
||||
);
|
||||
},
|
||||
isADAS() {
|
||||
const parts = useMainStore().order.lineItems.glassParts;
|
||||
return (
|
||||
parts !== null && !!parts.find((part) => part.requiresRecalibration)
|
||||
);
|
||||
},
|
||||
totalServicePrice() {
|
||||
return getPriceOfLineItems(this.baseServiceLineItems);
|
||||
},
|
||||
servicePriceForDisplay() {
|
||||
return formatAmountInDollars(this.totalServicePrice);
|
||||
},
|
||||
itacCostSavings() {
|
||||
return this.deductibleValue - this.totalServicePrice;
|
||||
},
|
||||
itacCostSavingsForDisplay() {
|
||||
return formatAmountInDollars(this.itacCostSavings);
|
||||
},
|
||||
serviceProviderQuestionText() {
|
||||
return this.getCmsContent(
|
||||
this.widget.serviceProviderQuestion,
|
||||
widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT
|
||||
);
|
||||
},
|
||||
serviceProviderQuestionAnswers() {
|
||||
return this.getCmsContent(
|
||||
this.widget.serviceProviderQuestion,
|
||||
widgetFields.INPUT_QUESTION_WIDGET.ANSWERS
|
||||
);
|
||||
},
|
||||
isQuoteDisplayed() {
|
||||
return this.verifiedITAC || this.verifiedNoComp;
|
||||
},
|
||||
shouldRegisterClaim() {
|
||||
return (
|
||||
this.policyLookupSuccessful
|
||||
&& useMainStore().vehicle.policyVehicleId != null
|
||||
&& useMainStore().vehicle.policyVehicleId >= 0
|
||||
&& useMainStore().isClaimRegistrationRequired
|
||||
&& !useMainStore().isClaimAlreadyRegistered
|
||||
&& (this.coveredAndServicePriceAboveOrEqualDeductible || this.verifiedITAC)
|
||||
);
|
||||
}
|
||||
},
|
||||
secondaryText() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.subheader,
|
||||
widgetFields.SUB_HEADER_WIDGET.SECONDARY_TEXT
|
||||
);
|
||||
},
|
||||
explanatoryText() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.explanatoryText,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||
);
|
||||
},
|
||||
nextStepsHeader() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.nextStep,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT
|
||||
);
|
||||
},
|
||||
nextStepsBody() {
|
||||
return this.getTextFromCmsWithCustomIfStatements(
|
||||
this.widget.nextStep,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||
)?.replaceAll("{custom:damage}", this.damageText);
|
||||
},
|
||||
damageText() {
|
||||
const damageString = getDamageString();
|
||||
return damageString === "match" ? "" : damageString;
|
||||
},
|
||||
deductibleValue() {
|
||||
return useMainStore().order.currentDeductible;
|
||||
},
|
||||
deductibleForDisplay() {
|
||||
return formatAmountInDollars(this.deductibleValue);
|
||||
},
|
||||
registerClaimSuccessful() {
|
||||
return useMainStore().payment.insuranceCoverage.isVerified;
|
||||
},
|
||||
verifiedNoComp() {
|
||||
return this.policyLookupSuccessful && this.isNoComp;
|
||||
},
|
||||
verifiedITAC() {
|
||||
return (
|
||||
this.policyLookupSuccessful &&
|
||||
!this.isNoComp &&
|
||||
this.deductibleValue > this.totalServicePrice
|
||||
);
|
||||
},
|
||||
coveredAndServicePriceAboveOrEqualDeductible() {
|
||||
return (
|
||||
!this.verifiedNoComp && this.totalServicePrice >= this.deductibleValue
|
||||
);
|
||||
},
|
||||
verifiedDeductible() {
|
||||
return useMainStore().isClaimRegistrationRequired
|
||||
? this.registerClaimSuccessful &&
|
||||
this.coveredAndServicePriceAboveOrEqualDeductible &&
|
||||
this.deductibleValue !== null
|
||||
: this.policyLookupSuccessful &&
|
||||
this.coveredAndServicePriceAboveOrEqualDeductible;
|
||||
},
|
||||
unverified() {
|
||||
return (
|
||||
!this.verifiedDeductible && !this.verifiedITAC && !this.verifiedNoComp
|
||||
);
|
||||
},
|
||||
isADAS() {
|
||||
const parts = useMainStore().order.lineItems.glassParts;
|
||||
return (
|
||||
parts !== null && !!parts.find((part) => part.requiresRecalibration)
|
||||
);
|
||||
},
|
||||
totalServicePrice() {
|
||||
return getPriceOfLineItems(this.baseServiceLineItems);
|
||||
},
|
||||
servicePriceForDisplay() {
|
||||
return formatAmountInDollars(this.totalServicePrice);
|
||||
},
|
||||
itacCostSavings() {
|
||||
return this.deductibleValue - this.totalServicePrice;
|
||||
},
|
||||
itacCostSavingsForDisplay() {
|
||||
return formatAmountInDollars(this.itacCostSavings);
|
||||
},
|
||||
serviceProviderQuestionText() {
|
||||
return this.getCmsContent(
|
||||
this.widget.serviceProviderQuestion,
|
||||
widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT
|
||||
);
|
||||
},
|
||||
serviceProviderQuestionAnswers() {
|
||||
return this.getCmsContent(
|
||||
this.widget.serviceProviderQuestion,
|
||||
widgetFields.INPUT_QUESTION_WIDGET.ANSWERS
|
||||
);
|
||||
},
|
||||
isQuoteDisplayed() {
|
||||
return this.verifiedITAC || this.verifiedNoComp;
|
||||
},
|
||||
shouldRegisterClaim() {
|
||||
return (
|
||||
this.policyLookupSuccessful &&
|
||||
useMainStore().vehicle.policyVehicleId != null &&
|
||||
useMainStore().vehicle.policyVehicleId >= 0 &&
|
||||
useMainStore().isClaimRegistrationRequired &&
|
||||
!useMainStore().isClaimAlreadyRegistered &&
|
||||
(this.coveredAndServicePriceAboveOrEqualDeductible || this.verifiedITAC)
|
||||
);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedProvider() {
|
||||
const buttonText =
|
||||
watch: {
|
||||
selectedProvider() {
|
||||
const buttonText =
|
||||
this.selectedProvider === SAFELITE_PROVIDER
|
||||
? "Continue with Safelite"
|
||||
: "Safelite";
|
||||
this.$refs.siteFooter.updateButtonText(buttonText);
|
||||
},
|
||||
nextStepsBody(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
setupModalLinks(this, "RecalModal");
|
||||
setupModalLinks(this, "DeductibleModal");
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
setupModalLinks(this);
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return !!useMainStore().vehicle.carId;
|
||||
},
|
||||
async initializeComponent() {
|
||||
useMainStore().updatePolicyITACFlag(this.verifiedITAC);
|
||||
const coverageStatus =
|
||||
this.verifiedITAC || this.verifiedNoComp
|
||||
? coverageStatuses.VERIFIED
|
||||
: coverageStatuses.PENDING;
|
||||
useMainStore().updateCoverageStatus(coverageStatus);
|
||||
if (this.shouldRegisterClaim) {
|
||||
await useMainStore()
|
||||
.registerClaim()
|
||||
?.catch(() => {});
|
||||
}
|
||||
this.$refs.loadingModal.hideModal();
|
||||
},
|
||||
async navigateForward() {
|
||||
if (this.unverified || this.verifiedDeductible) {
|
||||
useMainStore().updateSupportingItems(this.supportingItems);
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD);
|
||||
} else if (this.verifiedITAC || this.verifiedNoComp) {
|
||||
useMainStore().updateIsSafeliteProvider(
|
||||
this.selectedProvider === SAFELITE_PROVIDER
|
||||
);
|
||||
if (this.selectedProvider === SAFELITE_PROVIDER) {
|
||||
useMainStore().updateSupportingItems(this.supportingItems);
|
||||
this.navigateWithScenario(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE
|
||||
);
|
||||
} else {
|
||||
useMainStore().setBailout(bailoutMessage.RequestCallback());
|
||||
this.navigateWithScenario(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP
|
||||
);
|
||||
? 'Continue with Safelite'
|
||||
: 'Safelite';
|
||||
this.$refs.siteFooter.updateButtonText(buttonText);
|
||||
},
|
||||
nextStepsBody(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
setupModalLinks(this, 'RecalModal');
|
||||
setupModalLinks(this, 'DeductibleModal');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
useMainStore().setBailout(
|
||||
bailoutMessage.coverageStatementInvalidState()
|
||||
);
|
||||
this.navigateWithScenario(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE
|
||||
);
|
||||
}
|
||||
},
|
||||
navigateWithScenario(scenario) {
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
mounted() {
|
||||
setupModalLinks(this);
|
||||
},
|
||||
getTextFromCmsWithCustomIfStatements(widgetName, widgetField) {
|
||||
const rawText = this.getCmsContent(widgetName, widgetField);
|
||||
return processIfStatements(
|
||||
rawText,
|
||||
"custom",
|
||||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case "coverageUnverified":
|
||||
return this.unverified;
|
||||
case "verifiedDeductible":
|
||||
return this.verifiedDeductible;
|
||||
case "verifiedITAC":
|
||||
return this.verifiedITAC;
|
||||
case "verifiedNoComp":
|
||||
return this.verifiedNoComp;
|
||||
case "ADASReplace":
|
||||
return !this.isRepair && this.isADAS;
|
||||
case "nonADASReplace":
|
||||
return !this.isRepair && !this.isADAS;
|
||||
case "nonADASRepair":
|
||||
return this.isRepair;
|
||||
case "deductibleOverZero":
|
||||
return this.verifiedDeductible && this.deductibleValue !== 0; // TODO what if deductible is negative?
|
||||
case "isDeductibleZero":
|
||||
return this.verifiedDeductible && this.deductibleValue === 0;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
setSupportingItems(newSupportingItems) {
|
||||
this.supportingItems = newSupportingItems;
|
||||
},
|
||||
setBaseServiceLineItems(lineItems) {
|
||||
this.baseServiceLineItems = lineItems;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return !!useMainStore().vehicle.carId;
|
||||
},
|
||||
async initializeComponent() {
|
||||
useMainStore().updatePolicyITACFlag(this.verifiedITAC);
|
||||
const coverageStatus =
|
||||
this.verifiedITAC || this.verifiedNoComp
|
||||
? coverageStatuses.VERIFIED
|
||||
: coverageStatuses.PENDING;
|
||||
useMainStore().updateCoverageStatus(coverageStatus);
|
||||
if (this.shouldRegisterClaim) {
|
||||
await useMainStore()
|
||||
.registerClaim()
|
||||
?.catch(() => {});
|
||||
}
|
||||
this.$refs.loadingModal.hideModal();
|
||||
},
|
||||
async navigateForward() {
|
||||
if (this.unverified || this.verifiedDeductible) {
|
||||
useMainStore().updateSupportingItems(this.supportingItems);
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD);
|
||||
} else if (this.verifiedITAC || this.verifiedNoComp) {
|
||||
useMainStore().updateIsSafeliteProvider(this.selectedProvider === SAFELITE_PROVIDER);
|
||||
if (this.selectedProvider === SAFELITE_PROVIDER) {
|
||||
useMainStore().updateSupportingItems(this.supportingItems);
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE);
|
||||
} else {
|
||||
useMainStore().setBailout(bailoutMessage.RequestCallback());
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP);
|
||||
}
|
||||
} else {
|
||||
useMainStore().setBailout(bailoutMessage.coverageStatementInvalidState());
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE);
|
||||
}
|
||||
},
|
||||
navigateWithScenario(scenario) {
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
},
|
||||
getTextFromCmsWithCustomIfStatements(widgetName, widgetField) {
|
||||
const rawText = this.getCmsContent(widgetName, widgetField);
|
||||
return processIfStatements(
|
||||
rawText,
|
||||
'custom',
|
||||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case 'coverageUnverified':
|
||||
return this.unverified;
|
||||
case 'verifiedDeductible':
|
||||
return this.verifiedDeductible;
|
||||
case 'verifiedITAC':
|
||||
return this.verifiedITAC;
|
||||
case 'verifiedNoComp':
|
||||
return this.verifiedNoComp;
|
||||
case 'ADASReplace':
|
||||
return !this.isRepair && this.isADAS;
|
||||
case 'nonADASReplace':
|
||||
return !this.isRepair && !this.isADAS;
|
||||
case 'nonADASRepair':
|
||||
return this.isRepair;
|
||||
case 'deductibleOverZero':
|
||||
return this.verifiedDeductible && this.deductibleValue !== 0; // TODO what if deductible is negative?
|
||||
case 'isDeductibleZero':
|
||||
return this.verifiedDeductible && this.deductibleValue === 0;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
setSupportingItems(newSupportingItems) {
|
||||
this.supportingItems = newSupportingItems;
|
||||
},
|
||||
setBaseServiceLineItems(lineItems) {
|
||||
this.baseServiceLineItems = lineItems;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@
|
|||
ref="duplicate-check-form"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader ref="siteHeader" :cmsWidgetName="widget.siteHeader" />
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
:cmsWidgetName="widget.siteHeader" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -17,8 +18,7 @@
|
|||
id="sub-header"
|
||||
ref="siteSubHeader"
|
||||
class="mt-5 duplicate-check-subheader"
|
||||
:cmsWidgetName="widget.siteSubHeader"
|
||||
/>
|
||||
:cmsWidgetName="widget.siteSubHeader" />
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="selectedAnswer"
|
||||
|
|
@ -29,16 +29,14 @@
|
|||
groupName="existingOrNewQuestionOption"
|
||||
buttonTypeString="listButton"
|
||||
isRequired
|
||||
:validationRules="rules.selectionRequired"
|
||||
/>
|
||||
:validationRules="rules.selectionRequired" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="my-5"
|
||||
:cmsWidgetName="widget.siteFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack"
|
||||
/>
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -47,166 +45,166 @@
|
|||
|
||||
<script>
|
||||
// Components
|
||||
import { Form } from "vee-validate";
|
||||
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 buttonQuestion from "@/digital-components/button-question/button-question.vue";
|
||||
import { Form } from 'vee-validate';
|
||||
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 buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper.js";
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import { useMainStore } from "@/store/index.js";
|
||||
import globalRules from "@/constants/global-rules.js";
|
||||
import { toTitleCase } from "@/helpers/text-helper.js";
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper.js';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
import globalRules from '@/constants/global-rules.js';
|
||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||
|
||||
export default {
|
||||
name: "duplicate-check",
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
buttonQuestion,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContent = await fetchCmsContentForPage(to.query.issPage);
|
||||
name: 'duplicate-check',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
buttonQuestion,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContent = await fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(cmsContent);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedAnswer: null,
|
||||
widget: {
|
||||
siteHeader: "SiteHeaderWidget",
|
||||
siteSubHeader: "SiteSubHeaderWidget",
|
||||
existingOrNewQuestion: "ExistingOrNewQuestion",
|
||||
siteFooter: "SiteFooterWidget",
|
||||
},
|
||||
rules: {
|
||||
selectionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(
|
||||
this.widget.existingOrNewQuestion,
|
||||
"QuestionText"
|
||||
);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(cmsContent);
|
||||
});
|
||||
},
|
||||
answersFromCms() {
|
||||
return (
|
||||
this.getCmsContent(this.widget.existingOrNewQuestion, "Answers") ?? []
|
||||
);
|
||||
data() {
|
||||
return {
|
||||
selectedAnswer: null,
|
||||
widget: {
|
||||
siteHeader: 'SiteHeaderWidget',
|
||||
siteSubHeader: 'SiteSubHeaderWidget',
|
||||
existingOrNewQuestion: 'ExistingOrNewQuestion',
|
||||
siteFooter: 'SiteFooterWidget'
|
||||
},
|
||||
rules: {
|
||||
selectionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
};
|
||||
},
|
||||
getNewOrderSelectionName() {
|
||||
return this.answersFromCms?.[0]?.Name ?? "";
|
||||
},
|
||||
duplicateOrders() {
|
||||
const duplicateOrderText = "Finish Existing Claim";
|
||||
const orders = useMainStore().applicationUser.duplicateOrders;
|
||||
return (
|
||||
orders?.map((o) => {
|
||||
const vehicle =
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(
|
||||
this.widget.existingOrNewQuestion,
|
||||
'QuestionText'
|
||||
);
|
||||
},
|
||||
answersFromCms() {
|
||||
return (
|
||||
this.getCmsContent(this.widget.existingOrNewQuestion, 'Answers') ?? []
|
||||
);
|
||||
},
|
||||
getNewOrderSelectionName() {
|
||||
return this.answersFromCms?.[0]?.Name ?? '';
|
||||
},
|
||||
duplicateOrders() {
|
||||
const duplicateOrderText = 'Finish Existing Claim';
|
||||
const orders = useMainStore().applicationUser.duplicateOrders;
|
||||
return (
|
||||
orders?.map((o) => {
|
||||
const vehicle =
|
||||
!!o.vehicleYear && !!o.vehicleMake && !!o.vehicleModel
|
||||
? `${o.vehicleYear} ${o.vehicleMake} ${o.vehicleModel}`
|
||||
: null;
|
||||
? `${o.vehicleYear} ${o.vehicleMake} ${o.vehicleModel}`
|
||||
: null;
|
||||
|
||||
const dateOfLoss =
|
||||
const dateOfLoss =
|
||||
o.responseDate == null
|
||||
? ""
|
||||
: new Date(o.responseDate).toLocaleDateString();
|
||||
const subtext =
|
||||
? ''
|
||||
: new Date(o.responseDate).toLocaleDateString();
|
||||
const subtext =
|
||||
vehicle && o.responseDate
|
||||
? `${vehicle}, ${dateOfLoss}`
|
||||
: (vehicle ?? "").concat(dateOfLoss);
|
||||
? `${vehicle}, ${dateOfLoss}`
|
||||
: (vehicle ?? '').concat(dateOfLoss);
|
||||
|
||||
return {
|
||||
Text: duplicateOrderText,
|
||||
Name: o.referralNumber,
|
||||
SubText: toTitleCase(subtext),
|
||||
value: o,
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
return {
|
||||
Text: duplicateOrderText,
|
||||
Name: o.referralNumber,
|
||||
SubText: toTitleCase(subtext),
|
||||
value: o
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
},
|
||||
answers() {
|
||||
return [...this.duplicateOrders, ...this.answersFromCms];
|
||||
}
|
||||
},
|
||||
answers() {
|
||||
return [...this.duplicateOrders, ...this.answersFromCms];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
methods: {
|
||||
/**
|
||||
* @summary Steps to perform when forward button clicked.
|
||||
*/
|
||||
async forwardButtonAction() {
|
||||
if (
|
||||
this.selectedAnswer !== null &&
|
||||
typeof this.selectedAnswer === "object"
|
||||
) {
|
||||
await useMainStore()
|
||||
.loadSession(this.selectedAnswer)
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
async forwardButtonAction() {
|
||||
if (
|
||||
this.selectedAnswer !== null
|
||||
&& typeof this.selectedAnswer === 'object'
|
||||
) {
|
||||
await useMainStore()
|
||||
.loadSession(this.selectedAnswer)
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
this.navigateForward();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.navigateForward();
|
||||
});
|
||||
return;
|
||||
}
|
||||
},
|
||||
navigateForward() {
|
||||
if (!this.mainStore.order.policy.policyLookupSuccessful) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
this.$route
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
if (!this.mainStore.order.policy.policyLookupSuccessful) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
this.$route
|
||||
);
|
||||
return;
|
||||
}
|
||||
const policyVehicles = useMainStore().order.policy.vehicles ?? [];
|
||||
if (!this.mainStore.order.loadedFromDupeCheck) {
|
||||
if (policyVehicles.length !== 0) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const policyVehicles = useMainStore().order.policy.vehicles ?? [];
|
||||
if (!this.mainStore.order.loadedFromDupeCheck) {
|
||||
if (policyVehicles.length !== 0) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
if (this.mainStore.order.vehicle.vin) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_POLICY_VEHICLE,
|
||||
this.$route
|
||||
);
|
||||
} else if (policyVehicles.length !== 0) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_NON_POLICY_VEHICLE,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_NO_POLICY_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.mainStore.order.vehicle.vin) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_POLICY_VEHICLE,
|
||||
this.$route
|
||||
);
|
||||
} else if (policyVehicles.length !== 0) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_NON_POLICY_VEHICLE,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_NO_POLICY_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,35 +3,33 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader class="mb-2 header" cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteHeader
|
||||
class="mb-2 header"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<vehicleBanner
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
class="mt-2 mb-4"
|
||||
/>
|
||||
<policyVehiclesQuestion
|
||||
v-model="selectedVehicleVin"
|
||||
cmsWidgetName="PolicyVehiclesQuestion"
|
||||
:vehicles="VehiclesForQuestions"
|
||||
:validationRules="rules.optionRequired"
|
||||
/>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="backButtonAction"
|
||||
/>
|
||||
<div class="select-car-form rounded text-center">
|
||||
<vehicleBanner
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
class="mt-2 mb-4" />
|
||||
<policyVehiclesQuestion
|
||||
v-model="selectedVehicleVin"
|
||||
cmsWidgetName="PolicyVehiclesQuestion"
|
||||
:vehicles="VehiclesForQuestions"
|
||||
:validationRules="rules.optionRequired" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -40,250 +38,236 @@
|
|||
</template>
|
||||
<script>
|
||||
// Components
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner.vue";
|
||||
import policyVehiclesQuestion from "@/layouts/policy-vehicles/policy-vehicles-question/policy-vehicles-question.vue";
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import policyVehiclesQuestion from '@/layouts/policy-vehicles/policy-vehicles-question/policy-vehicles-question.vue';
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper.js";
|
||||
import { Form } from "vee-validate";
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import vehicleSelectionOptions from "@/constants/vehicle-selection-options.js";
|
||||
import endorsementOptions from "@/constants/endorsement-options.js";
|
||||
import globalRules from "@/constants/global-rules.js";
|
||||
import { useMainStore } from "@/store/index.js";
|
||||
import bailoutMessage from "@/constants/bailoutMessage";
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper.js';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import vehicleSelectionOptions from '@/constants/vehicle-selection-options.js';
|
||||
import endorsementOptions from '@/constants/endorsement-options.js';
|
||||
import globalRules from '@/constants/global-rules.js';
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
import bailoutMessage from '@/constants/bailoutMessage';
|
||||
import {
|
||||
deductibleForSelectedVehicle,
|
||||
endorsementsForSelectedVehicle,
|
||||
noCoverageForSelectedVehicle,
|
||||
repairWaivedForSelectedVehicle,
|
||||
} from "@/helpers/policy-vehicle-helper";
|
||||
deductibleForSelectedVehicle,
|
||||
endorsementsForSelectedVehicle,
|
||||
noCoverageForSelectedVehicle,
|
||||
repairWaivedForSelectedVehicle
|
||||
} from '@/helpers/policy-vehicle-helper';
|
||||
|
||||
export default {
|
||||
name: "policy-vehicles",
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
policyVehiclesQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = await fetchCmsContentForPage(to.query.issPage);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(cmsContentPromise);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
const policyVehicles = useMainStore().order.policy.vehicles;
|
||||
return {
|
||||
policyVehicles,
|
||||
selectedVehicleVin: "",
|
||||
selectedPolicyVehicle: null,
|
||||
displayGeneric: true,
|
||||
policyVinFound: true,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
VehiclesForQuestions() {
|
||||
// Map API result data, to address-vehicles data structure
|
||||
const vehicles = this.policyVehicles;
|
||||
const mappedData =
|
||||
vehicles?.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,
|
||||
Text: `${v.vehicleYear} ${v.vehicleMake} ${v.vehicleModel}`,
|
||||
Name: v.vin,
|
||||
SubText: `VIN ${vinStart}${vinEnd}`,
|
||||
};
|
||||
}) ?? [];
|
||||
return mappedData;
|
||||
name: 'policy-vehicles',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
policyVehiclesQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
noCoverageForSelectedVehicle() {
|
||||
return noCoverageForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
deductibleForSelectedVehicle() {
|
||||
return deductibleForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
endorsementsForSelectedVehicle() {
|
||||
return endorsementsForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
repairWaivedForSelectedVehicle() {
|
||||
return repairWaivedForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
selectedVehicle() {
|
||||
const vehicle = this.mainStore.lookupVehicleByVin(
|
||||
this.selectedVehicleVin
|
||||
);
|
||||
return vehicle;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
async selectedVehicleVin(value) {
|
||||
if (value === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
|
||||
// clear previously selected vehicle and image
|
||||
this.mainStore.resetVehicleState();
|
||||
this.displayGeneric = true;
|
||||
this.selectedPolicyVehicle = null;
|
||||
} else {
|
||||
// get vehicle details from selected VIN
|
||||
const vehicle = await this.lookupVehicleByVin(value);
|
||||
|
||||
// handle error in case vehicle info doesn't come back for selected VIN
|
||||
if (vehicle?.error === true) {
|
||||
this.mainStore.resetVehicleState();
|
||||
this.displayGeneric = true;
|
||||
this.selectedPolicyVehicle = null;
|
||||
return;
|
||||
}
|
||||
if (vehicle) {
|
||||
// save selected vehicle to the store
|
||||
this.mainStore.updateVehicle(vehicle.data);
|
||||
this.displayGeneric = false;
|
||||
this.selectedPolicyVehicle = this.policyVehicles.find(
|
||||
(p) => p.vin === value
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
if (this.mainStore.order.vehicle.vin) {
|
||||
this.selectedVehicleVin = this.mainStore.order.vehicle.vin;
|
||||
} else if (this.policyVehicles?.length === 1) {
|
||||
this.selectedVehicleVin = this.policyVehicles[0]?.vin;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
backButtonAction() {
|
||||
useMainStore().issConfig.disabledFields.policyNumber = true;
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
if (
|
||||
this.selectedVehicleVin !== vehicleSelectionOptions.VEHICLE_NOT_LISTED
|
||||
) {
|
||||
const vehicleLookupResponse = await this.lookupVehicleByVin(
|
||||
this.selectedVehicleVin
|
||||
);
|
||||
const vehicle = this.policyVehicles.find(
|
||||
(pv) => pv.vin === this.selectedVehicleVin
|
||||
);
|
||||
|
||||
if (vehicleLookupResponse.error) {
|
||||
if (vehicleLookupResponse.status === 404) {
|
||||
this.mainStore.resetVehicleState();
|
||||
useMainStore().updateVehicle({
|
||||
policyVehicleId: vehicle.id,
|
||||
carId: "0",
|
||||
category: "",
|
||||
year: vehicle.vehicleYear || "",
|
||||
make: vehicle.vehicleMake || "",
|
||||
model: vehicle.vehicleModel || "",
|
||||
style: vehicle.vehicleStyle || "",
|
||||
vin: vehicle.vin,
|
||||
noCoverage: this.noCoverageForSelectedVehicle,
|
||||
deductible: this.deductibleForSelectedVehicle,
|
||||
repairWaived: this.repairWaivedForSelectedVehicle,
|
||||
});
|
||||
this.policyVinFound = false;
|
||||
return this.navigateForward();
|
||||
}
|
||||
|
||||
this.mainStore.setBailout(
|
||||
bailoutMessage.vehicleLookupError(
|
||||
vehicle.vin,
|
||||
vehicleLookupResponse.data
|
||||
)
|
||||
);
|
||||
return this.navigateForward();
|
||||
}
|
||||
|
||||
this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, {
|
||||
policyVehicleId: vehicle.id,
|
||||
vin: this.selectedVehicleVin,
|
||||
noCoverage: this.noCoverageForSelectedVehicle,
|
||||
deductible: this.deductibleForSelectedVehicle,
|
||||
repairWaived: this.repairWaivedForSelectedVehicle,
|
||||
endorsements: this.endorsementsForSelectedVehicle,
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = await fetchCmsContentForPage(to.query.issPage);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(cmsContentPromise);
|
||||
});
|
||||
|
||||
useMainStore().updateVehicle(this.vehicleFromLookup);
|
||||
}
|
||||
return this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
if (this.mainStore.isBailout) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
} else if (
|
||||
this.selectedVehicleVin === vehicleSelectionOptions.VEHICLE_NOT_LISTED
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_NON_LISTED_VEHICLE,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
} else if (
|
||||
this.endorsementsForSelectedVehicle?.length > 0 &&
|
||||
(this.endorsementsForSelectedVehicle?.includes(
|
||||
endorsementOptions.PARKING_GUARD
|
||||
) ||
|
||||
this.endorsementsForSelectedVehicle?.includes(
|
||||
endorsementOptions.EDUCATOR
|
||||
))
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS,
|
||||
this.$route
|
||||
);
|
||||
} else if (!this.policyVinFound) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_CAR_ID_NOT_FOUND,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_LISTED_VEHICLE,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
}
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
async lookupVehicleByVin(vin) {
|
||||
try {
|
||||
return await useMainStore().lookupVehicleByVin(vin);
|
||||
} catch (responseError) {
|
||||
data() {
|
||||
const policyVehicles = useMainStore().order.policy.vehicles;
|
||||
return {
|
||||
error: true,
|
||||
status: responseError.status,
|
||||
data: responseError.data,
|
||||
policyVehicles,
|
||||
selectedVehicleVin: '',
|
||||
selectedPolicyVehicle: null,
|
||||
displayGeneric: true,
|
||||
policyVinFound: true,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
VehiclesForQuestions() {
|
||||
// Map API result data, to address-vehicles data structure
|
||||
const vehicles = this.policyVehicles;
|
||||
const mappedData =
|
||||
vehicles?.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,
|
||||
Text: `${v.vehicleYear} ${v.vehicleMake} ${v.vehicleModel}`,
|
||||
Name: v.vin,
|
||||
SubText: `VIN ${vinStart}${vinEnd}`
|
||||
};
|
||||
}) ?? [];
|
||||
return mappedData;
|
||||
},
|
||||
noCoverageForSelectedVehicle() {
|
||||
return noCoverageForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
deductibleForSelectedVehicle() {
|
||||
return deductibleForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
endorsementsForSelectedVehicle() {
|
||||
return endorsementsForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
repairWaivedForSelectedVehicle() {
|
||||
return repairWaivedForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
selectedVehicle() {
|
||||
const vehicle = this.mainStore.lookupVehicleByVin(this.selectedVehicleVin);
|
||||
return vehicle;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async selectedVehicleVin(value) {
|
||||
if (value === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
|
||||
// clear previously selected vehicle and image
|
||||
this.mainStore.resetVehicleState();
|
||||
this.displayGeneric = true;
|
||||
this.selectedPolicyVehicle = null;
|
||||
} else {
|
||||
// get vehicle details from selected VIN
|
||||
const vehicle = await this.lookupVehicleByVin(value);
|
||||
|
||||
// handle error in case vehicle info doesn't come back for selected VIN
|
||||
if (vehicle?.error === true) {
|
||||
this.mainStore.resetVehicleState();
|
||||
this.displayGeneric = true;
|
||||
this.selectedPolicyVehicle = null;
|
||||
return;
|
||||
}
|
||||
if (vehicle) {
|
||||
// save selected vehicle to the store
|
||||
this.mainStore.updateVehicle(vehicle.data);
|
||||
this.displayGeneric = false;
|
||||
this.selectedPolicyVehicle = this.policyVehicles.find((p) => p.vin === value);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
if (this.mainStore.order.vehicle.vin) {
|
||||
this.selectedVehicleVin = this.mainStore.order.vehicle.vin;
|
||||
} else if (this.policyVehicles?.length === 1) {
|
||||
this.selectedVehicleVin = this.policyVehicles[0]?.vin;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
backButtonAction() {
|
||||
useMainStore().issConfig.disabledFields.policyNumber = true;
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
if (
|
||||
this.selectedVehicleVin !== vehicleSelectionOptions.VEHICLE_NOT_LISTED
|
||||
) {
|
||||
const vehicleLookupResponse = await this.lookupVehicleByVin(this.selectedVehicleVin);
|
||||
const vehicle = this.policyVehicles.find((pv) => pv.vin === this.selectedVehicleVin);
|
||||
|
||||
if (vehicleLookupResponse.error) {
|
||||
if (vehicleLookupResponse.status === 404) {
|
||||
this.mainStore.resetVehicleState();
|
||||
useMainStore().updateVehicle({
|
||||
policyVehicleId: vehicle.id,
|
||||
carId: '0',
|
||||
category: '',
|
||||
year: vehicle.vehicleYear || '',
|
||||
make: vehicle.vehicleMake || '',
|
||||
model: vehicle.vehicleModel || '',
|
||||
style: vehicle.vehicleStyle || '',
|
||||
vin: vehicle.vin,
|
||||
noCoverage: this.noCoverageForSelectedVehicle,
|
||||
deductible: this.deductibleForSelectedVehicle,
|
||||
repairWaived: this.repairWaivedForSelectedVehicle
|
||||
});
|
||||
this.policyVinFound = false;
|
||||
return this.navigateForward();
|
||||
}
|
||||
|
||||
this.mainStore.setBailout(bailoutMessage.vehicleLookupError(
|
||||
vehicle.vin,
|
||||
vehicleLookupResponse.data
|
||||
));
|
||||
return this.navigateForward();
|
||||
}
|
||||
|
||||
this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, {
|
||||
policyVehicleId: vehicle.id,
|
||||
vin: this.selectedVehicleVin,
|
||||
noCoverage: this.noCoverageForSelectedVehicle,
|
||||
deductible: this.deductibleForSelectedVehicle,
|
||||
repairWaived: this.repairWaivedForSelectedVehicle,
|
||||
endorsements: this.endorsementsForSelectedVehicle
|
||||
});
|
||||
|
||||
useMainStore().updateVehicle(this.vehicleFromLookup);
|
||||
}
|
||||
return this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
if (this.mainStore.isBailout) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
} else if (
|
||||
this.selectedVehicleVin === vehicleSelectionOptions.VEHICLE_NOT_LISTED
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_NON_LISTED_VEHICLE,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
} else if (
|
||||
this.endorsementsForSelectedVehicle?.length > 0
|
||||
&& (this.endorsementsForSelectedVehicle?.includes(endorsementOptions.PARKING_GUARD)
|
||||
|| this.endorsementsForSelectedVehicle?.includes(endorsementOptions.EDUCATOR))
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS,
|
||||
this.$route
|
||||
);
|
||||
} else if (!this.policyVinFound) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_CAR_ID_NOT_FOUND,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_LISTED_VEHICLE,
|
||||
this.$route,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
}
|
||||
},
|
||||
async lookupVehicleByVin(vin) {
|
||||
try {
|
||||
return await useMainStore().lookupVehicleByVin(vin);
|
||||
} catch (responseError) {
|
||||
return {
|
||||
error: true,
|
||||
status: responseError.status,
|
||||
data: responseError.data
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<template>
|
||||
<Form ref="theForm" @submit="onSubmit" @invalidSubmit="onInvalidSubmit">
|
||||
<Form
|
||||
ref="theForm"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader class="mb-2 header" cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteHeader
|
||||
class="mb-2 header"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -11,8 +16,7 @@
|
|||
<siteSubHeader
|
||||
id="sub-header"
|
||||
cmsWidgetName="SiteSubHeader"
|
||||
class="mb-5 mt-4"
|
||||
/>
|
||||
class="mb-5 mt-4" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -25,219 +29,214 @@
|
|||
groupName="prefQuestions"
|
||||
buttonTypeString="providerPrefRadio"
|
||||
:validationRules="rules.optionRequired"
|
||||
isRequired
|
||||
/>
|
||||
isRequired />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
/>
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
<recalModal ref="recalModal" cmsWidgetName="RecalModal" />
|
||||
<recalModal
|
||||
ref="recalModal"
|
||||
cmsWidgetName="RecalModal" />
|
||||
<steeringModal
|
||||
ref="StateSteeringModal"
|
||||
cmsWidgetName="StateSteeringModal"
|
||||
/>
|
||||
cmsWidgetName="StateSteeringModal" />
|
||||
<shopPreferenceModal
|
||||
ref="ShopPreferenceDrawer"
|
||||
cmsWidgetName="ShopPreferenceDrawer"
|
||||
:showSteeringLink="showSteeringLink"
|
||||
@openSteering="openStateSteeringModal"
|
||||
/>
|
||||
@openSteering="openStateSteeringModal" />
|
||||
<tpaRecalModal
|
||||
ref="TPARecalModal"
|
||||
cmsWidgetName="TPARecalModal"
|
||||
:ackError="ackError"
|
||||
@buttonClick="navigateWithTPAAck"
|
||||
/>
|
||||
@buttonClick="navigateWithTPAAck" />
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
setupModalLinks,
|
||||
} from "@/helpers/cms-content-helper";
|
||||
import settleAllPromises from "@/helpers/layout-helper";
|
||||
import errorMessages from "@/constants/error-messages";
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question.vue";
|
||||
import issPageValues from "@/router/router-constants/issPage-values";
|
||||
fetchCmsContentForPage,
|
||||
setupModalLinks
|
||||
} from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import issPageValues from '@/router/router-constants/issPage-values';
|
||||
|
||||
// Import Component
|
||||
import baseFormMixin from "@/mixins/base-form-mixin";
|
||||
import { Form } from "vee-validate";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
|
||||
import recalModal from "@/layouts/coverage-statement/recal-modal/recal-modal.vue";
|
||||
import steeringModal from "@/layouts/provider-preference/steering-modal/steering-modal.vue";
|
||||
import shopPreferenceModal from "@/layouts/provider-preference/shop-preference-modal/shop-preference-modal.vue";
|
||||
import tpaRecalModal from "@/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue";
|
||||
import globalRules from "@/constants/global-rules";
|
||||
import bailoutCode from "@/constants/bailoutCode";
|
||||
import bailoutMessage from "@/constants/bailoutMessage";
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import { Form } from 'vee-validate';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import recalModal from '@/layouts/coverage-statement/recal-modal/recal-modal.vue';
|
||||
import steeringModal from '@/layouts/provider-preference/steering-modal/steering-modal.vue';
|
||||
import shopPreferenceModal from '@/layouts/provider-preference/shop-preference-modal/shop-preference-modal.vue';
|
||||
import tpaRecalModal from '@/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
import bailoutCode from '@/constants/bailoutCode';
|
||||
import bailoutMessage from '@/constants/bailoutMessage';
|
||||
|
||||
const options = { SAFELITE: "SafeliteOption", TPA: "TPAOption" };
|
||||
const options = { SAFELITE: 'SafeliteOption', TPA: 'TPAOption' };
|
||||
|
||||
export default {
|
||||
name: "provider-preference",
|
||||
name: 'provider-preference',
|
||||
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
buttonQuestion,
|
||||
recalModal,
|
||||
steeringModal,
|
||||
shopPreferenceModal,
|
||||
tpaRecalModal,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
|
||||
vm.showSteeringLink = !!vm.$refs.StateSteeringModal.ModalBodyText;
|
||||
if (vm.showSteeringLink) {
|
||||
vm.$refs.StateSteeringModal.openModal();
|
||||
}
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedProvider: null,
|
||||
showSteeringLink: false,
|
||||
tpaAcknowledgement: false,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedProvider === null;
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
buttonQuestion,
|
||||
recalModal,
|
||||
steeringModal,
|
||||
shopPreferenceModal,
|
||||
tpaRecalModal
|
||||
},
|
||||
prefAnswers() {
|
||||
const cmsAnswersContent = [
|
||||
{
|
||||
cmsWidgetName: options.SAFELITE,
|
||||
},
|
||||
{
|
||||
cmsWidgetName: options.TPA,
|
||||
},
|
||||
];
|
||||
// if cms content has not yet loaded, skip
|
||||
if (
|
||||
!this.getCmsContent(cmsAnswersContent[0].cmsWidgetName, "HeaderText") ||
|
||||
this.getCmsContent(cmsAnswersContent[0].cmsWidgetName, "HeaderText") ===
|
||||
""
|
||||
) {
|
||||
return {};
|
||||
}
|
||||
const modifiedAnswers = cmsAnswersContent.map((answer) => ({
|
||||
value: answer.cmsWidgetName,
|
||||
buttonLabel: this.getHeaderTextFromCms(answer.cmsWidgetName),
|
||||
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.cmsWidgetName),
|
||||
buttonBodyCopy: this.getBodyTextFromCms(answer.cmsWidgetName),
|
||||
}));
|
||||
return modifiedAnswers;
|
||||
},
|
||||
ackError() {
|
||||
return errorMessages.ACKNOWLEDGEMENT_REQUIRED;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
setupModalLinks(this);
|
||||
const pageData = this.mainStore.pageData(issPageValues.PROVIDER_PREFERENCE);
|
||||
this.selectedProvider = pageData?.selectedProvider
|
||||
? pageData.selectedProvider
|
||||
: null;
|
||||
this.tpaAcknowledgement = pageData?.tpaAcknowledgement
|
||||
? pageData.tpaAcknowledgement
|
||||
: false;
|
||||
},
|
||||
methods: {
|
||||
getHeaderTextFromCms(cmsWidgetName) {
|
||||
const headerText = this.getCmsContent(cmsWidgetName, "HeaderText");
|
||||
return headerText?.replace(
|
||||
"{custom:SafeliteLogo}",
|
||||
"<span class='safeliteLogo'></span>"
|
||||
);
|
||||
},
|
||||
getSubheaderTextFromCms(cmsWidgetName) {
|
||||
return this.getCmsContent(cmsWidgetName, "SubheaderText");
|
||||
},
|
||||
getBodyTextFromCms(cmsWidgetName) {
|
||||
return this.getCmsContent(cmsWidgetName, "BodyText");
|
||||
},
|
||||
arePagePrerequisiteValid() {
|
||||
return true;
|
||||
},
|
||||
navigateForward(scenario) {
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
},
|
||||
navigateWithTPAAck() {
|
||||
this.mainStore.saveProviderPreferenceData({
|
||||
selectedProvider: this.selectedProvider,
|
||||
tpaAcknowledgement: this.tpaAcknowledgement,
|
||||
});
|
||||
this.navigateForward(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED
|
||||
);
|
||||
},
|
||||
forwardButtonAction() {
|
||||
if (this.selectedProvider) {
|
||||
let scenario = null;
|
||||
switch (this.selectedProvider) {
|
||||
case options.SAFELITE:
|
||||
this.mainStore.updateIsSafeliteProvider(true);
|
||||
scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE;
|
||||
break;
|
||||
case options.TPA:
|
||||
this.mainStore.updateIsSafeliteProvider(false);
|
||||
if (this.mainStore.issConfig.enableTPAFlow) {
|
||||
if (this.mainStore.hasRecalibrationPart) {
|
||||
this.$refs.TPARecalModal.openModal();
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return;
|
||||
}
|
||||
scenario =
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED;
|
||||
} else {
|
||||
this.mainStore.setBailout(bailoutMessage.TPANotEnabled());
|
||||
scenario =
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED;
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
|
||||
vm.showSteeringLink = !!vm.$refs.StateSteeringModal.ModalBodyText;
|
||||
if (vm.showSteeringLink) {
|
||||
vm.$refs.StateSteeringModal.openModal();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
this.navigateForward(scenario);
|
||||
this.mainStore.saveProviderPreferenceData({
|
||||
selectedProvider: this.selectedProvider,
|
||||
tpaAcknowledgement: this.tpaAcknowledgement,
|
||||
});
|
||||
}
|
||||
},
|
||||
openStateSteeringModal() {
|
||||
this.$refs.StateSteeringModal.openModal();
|
||||
data() {
|
||||
return {
|
||||
selectedProvider: null,
|
||||
showSteeringLink: false,
|
||||
tpaAcknowledgement: false,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedProvider === null;
|
||||
},
|
||||
prefAnswers() {
|
||||
const cmsAnswersContent = [
|
||||
{
|
||||
cmsWidgetName: options.SAFELITE
|
||||
},
|
||||
{
|
||||
cmsWidgetName: options.TPA
|
||||
}
|
||||
];
|
||||
// if cms content has not yet loaded, skip
|
||||
if (
|
||||
!this.getCmsContent(cmsAnswersContent[0].cmsWidgetName, 'HeaderText')
|
||||
|| this.getCmsContent(cmsAnswersContent[0].cmsWidgetName, 'HeaderText')
|
||||
=== ''
|
||||
) {
|
||||
return {};
|
||||
}
|
||||
const modifiedAnswers = cmsAnswersContent.map((answer) => ({
|
||||
value: answer.cmsWidgetName,
|
||||
buttonLabel: this.getHeaderTextFromCms(answer.cmsWidgetName),
|
||||
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.cmsWidgetName),
|
||||
buttonBodyCopy: this.getBodyTextFromCms(answer.cmsWidgetName)
|
||||
}));
|
||||
return modifiedAnswers;
|
||||
},
|
||||
ackError() {
|
||||
return errorMessages.ACKNOWLEDGEMENT_REQUIRED;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
setupModalLinks(this);
|
||||
const pageData = this.mainStore.pageData(issPageValues.PROVIDER_PREFERENCE);
|
||||
this.selectedProvider = pageData?.selectedProvider
|
||||
? pageData.selectedProvider
|
||||
: null;
|
||||
this.tpaAcknowledgement = pageData?.tpaAcknowledgement
|
||||
? pageData.tpaAcknowledgement
|
||||
: false;
|
||||
},
|
||||
methods: {
|
||||
getHeaderTextFromCms(cmsWidgetName) {
|
||||
const headerText = this.getCmsContent(cmsWidgetName, 'HeaderText');
|
||||
return headerText?.replace(
|
||||
'{custom:SafeliteLogo}',
|
||||
"<span class='safeliteLogo'></span>"
|
||||
);
|
||||
},
|
||||
getSubheaderTextFromCms(cmsWidgetName) {
|
||||
return this.getCmsContent(cmsWidgetName, 'SubheaderText');
|
||||
},
|
||||
getBodyTextFromCms(cmsWidgetName) {
|
||||
return this.getCmsContent(cmsWidgetName, 'BodyText');
|
||||
},
|
||||
arePagePrerequisiteValid() {
|
||||
return true;
|
||||
},
|
||||
navigateForward(scenario) {
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
},
|
||||
navigateWithTPAAck() {
|
||||
this.mainStore.saveProviderPreferenceData({
|
||||
selectedProvider: this.selectedProvider,
|
||||
tpaAcknowledgement: this.tpaAcknowledgement
|
||||
});
|
||||
this.navigateForward(this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED);
|
||||
},
|
||||
forwardButtonAction() {
|
||||
if (this.selectedProvider) {
|
||||
let scenario = null;
|
||||
switch (this.selectedProvider) {
|
||||
case options.SAFELITE:
|
||||
this.mainStore.updateIsSafeliteProvider(true);
|
||||
scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE;
|
||||
break;
|
||||
case options.TPA:
|
||||
this.mainStore.updateIsSafeliteProvider(false);
|
||||
if (this.mainStore.issConfig.enableTPAFlow) {
|
||||
if (this.mainStore.hasRecalibrationPart) {
|
||||
this.$refs.TPARecalModal.openModal();
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return;
|
||||
}
|
||||
scenario =
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED;
|
||||
} else {
|
||||
this.mainStore.setBailout(bailoutMessage.TPANotEnabled());
|
||||
scenario =
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
this.navigateForward(scenario);
|
||||
this.mainStore.saveProviderPreferenceData({
|
||||
selectedProvider: this.selectedProvider,
|
||||
tpaAcknowledgement: this.tpaAcknowledgement
|
||||
});
|
||||
}
|
||||
},
|
||||
openStateSteeringModal() {
|
||||
this.$refs.StateSteeringModal.openModal();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader class="mb-2 header" cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteHeader
|
||||
class="mb-2 header"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -16,21 +17,18 @@
|
|||
<siteSubHeader
|
||||
cmsWidgetName="ScheduleSubHeaderWidget"
|
||||
subTextClasses="text-center small sub-text"
|
||||
class="mt-4"
|
||||
/>
|
||||
class="mt-4" />
|
||||
<template v-if="ChangeShopLink.length">
|
||||
<textBlock
|
||||
cmsWidgetName="ChangeShopLink"
|
||||
justifyText="center"
|
||||
class="mb-3 text-link-small"
|
||||
:marginTopSizeOverride="1"
|
||||
/>
|
||||
:marginTopSizeOverride="1" />
|
||||
</template>
|
||||
<div class="main-content-container">
|
||||
<locationAlerts
|
||||
ref="locationAlerts"
|
||||
cmsWidgetPrefix="LocationAlert-"
|
||||
/>
|
||||
cmsWidgetPrefix="LocationAlert-" />
|
||||
<datePicker
|
||||
ref="datePicker"
|
||||
v-model="selectedDate"
|
||||
|
|
@ -39,8 +37,7 @@
|
|||
class="text-link-small"
|
||||
:customSelectableDatesCallback="getAvailableDatesMethod"
|
||||
validationRules="date-required"
|
||||
@dateClicked="openInshopTimeSlotsModal"
|
||||
/>
|
||||
@dateClicked="openInshopTimeSlotsModal" />
|
||||
<timeSlotModalQuestion
|
||||
ref="timeSlotModalQuestion"
|
||||
v-model="selectedTimeSlotInfo"
|
||||
|
|
@ -62,16 +59,14 @@
|
|||
selectableDatesData.estimatedServiceMinutesMaximum
|
||||
"
|
||||
validationRules="time-slot-selection-required"
|
||||
@timeSlotModalClosed="timeSlotModalClosed"
|
||||
/>
|
||||
@timeSlotModalClosed="timeSlotModalClosed" />
|
||||
<siteFooter
|
||||
ref="navbar"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
/>
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -80,419 +75,407 @@
|
|||
</template>
|
||||
<script>
|
||||
// Components
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
|
||||
import locationAlerts from "@/layouts/schedule-page/location-alerts/location-alerts.vue";
|
||||
import datePicker from "@/digital-components/date-picker/date-picker.vue";
|
||||
import timeSlotModalQuestion from "@/layouts/schedule-page/time-slot-modal-question/time-slot-modal-question.vue";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import textBlock from "@/digital-components/text-block/text-block.vue";
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import locationAlerts from '@/layouts/schedule-page/location-alerts/location-alerts.vue';
|
||||
import datePicker from '@/digital-components/date-picker/date-picker.vue';
|
||||
import timeSlotModalQuestion from '@/layouts/schedule-page/time-slot-modal-question/time-slot-modal-question.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||
|
||||
// Supporting files
|
||||
import {
|
||||
AppointmentTypeStrings,
|
||||
GET_MOBILE_TIME_SLOTS,
|
||||
GET_SHOP_TIME_SLOTS,
|
||||
PREMIUM_FEE_PART_TYPE,
|
||||
} from "@/constants/schedule-constants.js";
|
||||
AppointmentTypeStrings,
|
||||
GET_MOBILE_TIME_SLOTS,
|
||||
GET_SHOP_TIME_SLOTS,
|
||||
PREMIUM_FEE_PART_TYPE
|
||||
} from '@/constants/schedule-constants.js';
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
} from "@/helpers/cms-content-helper";
|
||||
fetchCmsContentForPage,
|
||||
splitCopyOnCMSPlaceHolder
|
||||
} from '@/helpers/cms-content-helper';
|
||||
import {
|
||||
calcDaysBetweenDates,
|
||||
convertDateStringToDate,
|
||||
sumDateString,
|
||||
} from "@/helpers/date-helper";
|
||||
import settleAllPromises from "@/helpers/layout-helper";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import errorMessages from "@/constants/error-messages";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import { useMainStore } from "@/store";
|
||||
calcDaysBetweenDates,
|
||||
convertDateStringToDate,
|
||||
sumDateString
|
||||
} from '@/helpers/date-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import { Form, defineRule } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule("date-required", required(errorMessages.DATE_REQUIRED));
|
||||
defineRule("time-slot-selection-required", (value) => {
|
||||
if (value?.timeSlot?.routeCode == null) {
|
||||
return errorMessages.DATE_REQUIRED;
|
||||
}
|
||||
return true;
|
||||
defineRule('date-required', required(errorMessages.DATE_REQUIRED));
|
||||
defineRule('time-slot-selection-required', (value) => {
|
||||
if (value?.timeSlot?.routeCode == null) {
|
||||
return errorMessages.DATE_REQUIRED;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Define constants
|
||||
const TIME_SLOTS_CALL_DAYS_LIMIT = 34; // needs to be 34 for API limits (35 does not consistently work)
|
||||
|
||||
const getAvailableDates = async (
|
||||
startDateString,
|
||||
endDateString,
|
||||
appointmentType,
|
||||
providerNumber
|
||||
) => {
|
||||
const apiEndDateLimit = sumDateString(
|
||||
startDateString,
|
||||
TIME_SLOTS_CALL_DAYS_LIMIT
|
||||
);
|
||||
const difference = calcDaysBetweenDates(startDateString, endDateString);
|
||||
const apiCallsCount = Math.ceil(difference / TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||
const storeActionConfigs = [];
|
||||
const timeSlotsData = {};
|
||||
timeSlotsData.days = [];
|
||||
let apiStartDate = startDateString;
|
||||
let apiEndDate = endDateString;
|
||||
endDateString,
|
||||
appointmentType,
|
||||
providerNumber
|
||||
) => {
|
||||
const apiEndDateLimit = sumDateString(
|
||||
startDateString,
|
||||
TIME_SLOTS_CALL_DAYS_LIMIT
|
||||
);
|
||||
const difference = calcDaysBetweenDates(startDateString, endDateString);
|
||||
const apiCallsCount = Math.ceil(difference / TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||
const storeActionConfigs = [];
|
||||
const timeSlotsData = {};
|
||||
timeSlotsData.days = [];
|
||||
let apiStartDate = startDateString;
|
||||
let apiEndDate = endDateString;
|
||||
|
||||
for (let i = 1; i <= apiCallsCount; i++) {
|
||||
let storeActionConfig;
|
||||
for (let i = 1; i <= apiCallsCount; i++) {
|
||||
let storeActionConfig;
|
||||
|
||||
if (i > 1) {
|
||||
apiStartDate = sumDateString(apiEndDate, 1);
|
||||
apiEndDate = sumDateString(apiStartDate, TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||
if (i > 1) {
|
||||
apiStartDate = sumDateString(apiEndDate, 1);
|
||||
apiEndDate = sumDateString(apiStartDate, TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||
|
||||
if (i === apiCallsCount) {
|
||||
apiEndDate = endDateString;
|
||||
}
|
||||
} else if (apiEndDate > apiEndDateLimit) {
|
||||
apiEndDate = apiEndDateLimit;
|
||||
}
|
||||
|
||||
if (
|
||||
appointmentType === AppointmentTypeStrings.MOBILE ||
|
||||
appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
) {
|
||||
storeActionConfig = {
|
||||
storeAction: GET_MOBILE_TIME_SLOTS,
|
||||
payload: {
|
||||
startDate: apiStartDate,
|
||||
endDate: apiEndDate,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
storeActionConfig = {
|
||||
storeAction: GET_SHOP_TIME_SLOTS,
|
||||
payload: {
|
||||
startDate: apiStartDate,
|
||||
endDate: apiEndDate,
|
||||
shopAppointmentType: appointmentType,
|
||||
providerNumber,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (apiStartDate < apiEndDate) storeActionConfigs.push(storeActionConfig);
|
||||
}
|
||||
|
||||
const timeSlotsResponsesData = {
|
||||
days: [],
|
||||
};
|
||||
|
||||
function compareDayStrings(a, b) {
|
||||
if (a.date < b.date) return -1;
|
||||
if (a.date > b.date) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const makeParallelCalls = async () => {
|
||||
await Promise.all(
|
||||
storeActionConfigs.map(async (storeAction) => {
|
||||
let timeSlotsResponse = null;
|
||||
if (storeAction.storeAction === GET_SHOP_TIME_SLOTS) {
|
||||
timeSlotsResponse = await useMainStore().getShopTimeSlots(
|
||||
storeAction.payload.startDate,
|
||||
storeAction.payload.endDate,
|
||||
storeAction.payload.shopAppointmentType,
|
||||
storeAction.payload.providerNumber
|
||||
);
|
||||
} else {
|
||||
timeSlotsResponse = await useMainStore().getMobileTimeSlots(
|
||||
storeAction.payload.startDate,
|
||||
storeAction.payload.endDate
|
||||
);
|
||||
if (i === apiCallsCount) {
|
||||
apiEndDate = endDateString;
|
||||
}
|
||||
} else if (apiEndDate > apiEndDateLimit) {
|
||||
apiEndDate = apiEndDateLimit;
|
||||
}
|
||||
|
||||
timeSlotsResponsesData.estimatedServiceMinutesMinimum =
|
||||
timeSlotsResponse.data.estimatedServiceMinutesMinimum;
|
||||
timeSlotsResponsesData.estimatedServiceMinutesMaximum =
|
||||
timeSlotsResponse.data.estimatedServiceMinutesMaximum;
|
||||
timeSlotsResponsesData.days = [
|
||||
...timeSlotsResponsesData.days,
|
||||
...timeSlotsResponse.data.days,
|
||||
];
|
||||
})
|
||||
);
|
||||
};
|
||||
if (
|
||||
appointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
) {
|
||||
storeActionConfig = {
|
||||
storeAction: GET_MOBILE_TIME_SLOTS,
|
||||
payload: {
|
||||
startDate: apiStartDate,
|
||||
endDate: apiEndDate
|
||||
}
|
||||
};
|
||||
} else {
|
||||
storeActionConfig = {
|
||||
storeAction: GET_SHOP_TIME_SLOTS,
|
||||
payload: {
|
||||
startDate: apiStartDate,
|
||||
endDate: apiEndDate,
|
||||
shopAppointmentType: appointmentType,
|
||||
providerNumber
|
||||
}
|
||||
};
|
||||
}
|
||||
if (apiStartDate < apiEndDate) storeActionConfigs.push(storeActionConfig);
|
||||
}
|
||||
|
||||
return makeParallelCalls().then(() => {
|
||||
const timeSlotsResponsesData = {
|
||||
days: []
|
||||
};
|
||||
|
||||
function compareDayStrings(a, b) {
|
||||
if (a.date < b.date) return -1;
|
||||
if (a.date > b.date) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const makeParallelCalls = async () => {
|
||||
await Promise.all(storeActionConfigs.map(async (storeAction) => {
|
||||
let timeSlotsResponse = null;
|
||||
if (storeAction.storeAction === GET_SHOP_TIME_SLOTS) {
|
||||
timeSlotsResponse = await useMainStore().getShopTimeSlots(
|
||||
storeAction.payload.startDate,
|
||||
storeAction.payload.endDate,
|
||||
storeAction.payload.shopAppointmentType,
|
||||
storeAction.payload.providerNumber
|
||||
);
|
||||
} else {
|
||||
timeSlotsResponse = await useMainStore().getMobileTimeSlots(
|
||||
storeAction.payload.startDate,
|
||||
storeAction.payload.endDate
|
||||
);
|
||||
}
|
||||
|
||||
timeSlotsResponsesData.estimatedServiceMinutesMinimum =
|
||||
timeSlotsResponse.data.estimatedServiceMinutesMinimum;
|
||||
timeSlotsResponsesData.estimatedServiceMinutesMaximum =
|
||||
timeSlotsResponse.data.estimatedServiceMinutesMaximum;
|
||||
timeSlotsResponsesData.days = [
|
||||
...timeSlotsResponsesData.days,
|
||||
...timeSlotsResponse.data.days
|
||||
];
|
||||
}));
|
||||
};
|
||||
|
||||
return makeParallelCalls().then(() => {
|
||||
// sort days chronologically
|
||||
timeSlotsResponsesData.days.sort(compareDayStrings);
|
||||
return timeSlotsResponsesData;
|
||||
});
|
||||
timeSlotsResponsesData.days.sort(compareDayStrings);
|
||||
return timeSlotsResponsesData;
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "schedule-page",
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
locationAlerts,
|
||||
datePicker,
|
||||
timeSlotModalQuestion,
|
||||
siteFooter,
|
||||
textBlock,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
name: 'schedule-page',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
locationAlerts,
|
||||
datePicker,
|
||||
timeSlotModalQuestion,
|
||||
siteFooter,
|
||||
textBlock,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
let preSelectedDate = await useMainStore().order.schedule.date;
|
||||
if (!preSelectedDate || preSelectedDate.startTime === null) {
|
||||
preSelectedDate = null;
|
||||
}
|
||||
let preSelectedDate = await useMainStore().order.schedule.date;
|
||||
if (!preSelectedDate || preSelectedDate.startTime === null) {
|
||||
preSelectedDate = null;
|
||||
}
|
||||
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
const datePickerInitialDataPromise =
|
||||
const datePickerInitialDataPromise =
|
||||
await datePicker.methods.loadInitialData({
|
||||
selectableDatesSetting: "custom",
|
||||
initialViewRowsToShow: 5,
|
||||
customSelectableDatesCallback: getAvailableDates,
|
||||
preSelectedDate,
|
||||
selectableDatesSetting: 'custom',
|
||||
initialViewRowsToShow: 5,
|
||||
customSelectableDatesCallback: getAvailableDates,
|
||||
preSelectedDate
|
||||
});
|
||||
|
||||
const premiumFeePromise = useMainStore().getMobilePremiumFee();
|
||||
const premiumFeePromise = useMainStore().getMobilePremiumFee();
|
||||
|
||||
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
||||
if (result.data) {
|
||||
return useMainStore().priceOrderItemsAndSaveServerData(result.data);
|
||||
}
|
||||
return result.data;
|
||||
});
|
||||
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
||||
if (result.data) {
|
||||
return useMainStore().priceOrderItemsAndSaveServerData(result.data);
|
||||
}
|
||||
return result.data;
|
||||
});
|
||||
|
||||
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
||||
useMainStore().order.serviceLocation.zipCodeCtu,
|
||||
useMainStore().order.serviceLocation.provider?.address?.zipCodeCtu
|
||||
);
|
||||
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
||||
useMainStore().order.serviceLocation.zipCodeCtu,
|
||||
useMainStore().order.serviceLocation.provider?.address?.zipCodeCtu
|
||||
);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "alertReasons",
|
||||
promise: alertReasonsPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "datePickerInitialData",
|
||||
promise: datePickerInitialDataPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "premiumFeeWithPrice",
|
||||
promise: premiumFeeWithPricePromise,
|
||||
},
|
||||
];
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'alertReasons',
|
||||
promise: alertReasonsPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'datePickerInitialData',
|
||||
promise: datePickerInitialDataPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'premiumFeeWithPrice',
|
||||
promise: premiumFeeWithPricePromise
|
||||
}
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData);
|
||||
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
||||
vm.setData(
|
||||
resultMap.datePickerInitialData.initialShopTimeSlotsResponse,
|
||||
resultMap.premiumFeeWithPrice
|
||||
);
|
||||
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedDate: this.getSelectedDate(),
|
||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||
selectableDatesData: [],
|
||||
mobilePremiumAppointmentFee: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
ChangeShopLinkText() {
|
||||
return this.getCmsContent("ChangeShopLink", "Text");
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData);
|
||||
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
||||
vm.setData(
|
||||
resultMap.datePickerInitialData.initialShopTimeSlotsResponse,
|
||||
resultMap.premiumFeeWithPrice
|
||||
);
|
||||
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
||||
});
|
||||
},
|
||||
ChangeShopLink() {
|
||||
return this.splitCopyOnCMSPlaceHolder(this.ChangeShopLinkText);
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
appointmentType() {
|
||||
return useMainStore().order.serviceLocation.appointmentType;
|
||||
},
|
||||
timeSlotsForSelectedDate() {
|
||||
if (!this.selectedDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.selectableDatesData.days?.find(
|
||||
(selectableDate) => selectableDate.date === this.selectedDate
|
||||
);
|
||||
},
|
||||
supportingItems() {
|
||||
return useMainStore().lineItems.supportingItems;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedDate(newValue, oldValue) {
|
||||
// Clear time slot selection if date selected changes
|
||||
if (newValue !== oldValue) {
|
||||
this.selectedTimeSlotInfo = {
|
||||
timeSlot: {
|
||||
date: null,
|
||||
routeCode: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
},
|
||||
isPremiumAppointment: null,
|
||||
data() {
|
||||
return {
|
||||
selectedDate: this.getSelectedDate(),
|
||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||
selectableDatesData: [],
|
||||
mobilePremiumAppointmentFee: null
|
||||
};
|
||||
}
|
||||
},
|
||||
selectedTimeSlotInfo(newValue) {
|
||||
this.updateFooterButtonText(newValue);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
arePagePrerequisitesValid() {
|
||||
const { serviceLocation } = useMainStore().order;
|
||||
const serviceLocationPreReqs =
|
||||
serviceLocation.zipCode &&
|
||||
serviceLocation.zipCodeCtu &&
|
||||
serviceLocation.appointmentType &&
|
||||
(serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE ||
|
||||
serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP ||
|
||||
serviceLocation.provider.providerNumber);
|
||||
const supportingItems = this.supportingItems !== null;
|
||||
const damageInfo =
|
||||
useMainStore().order.damage.isRepair ||
|
||||
(useMainStore().order.lineItems?.glassParts != null &&
|
||||
useMainStore().order.lineItems.glassParts.length > 0);
|
||||
computed: {
|
||||
ChangeShopLinkText() {
|
||||
return this.getCmsContent('ChangeShopLink', 'Text');
|
||||
},
|
||||
ChangeShopLink() {
|
||||
return this.splitCopyOnCMSPlaceHolder(this.ChangeShopLinkText);
|
||||
},
|
||||
appointmentType() {
|
||||
return useMainStore().order.serviceLocation.appointmentType;
|
||||
},
|
||||
timeSlotsForSelectedDate() {
|
||||
if (!this.selectedDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return serviceLocationPreReqs && supportingItems && damageInfo;
|
||||
return this.selectableDatesData.days?.find((selectableDate) => selectableDate.date === this.selectedDate);
|
||||
},
|
||||
supportingItems() {
|
||||
return useMainStore().lineItems.supportingItems;
|
||||
}
|
||||
},
|
||||
setData(initialShopTimeSlotsResponse, premiumFeeWithPriceResponse) {
|
||||
this.selectableDatesData = initialShopTimeSlotsResponse;
|
||||
this.mobilePremiumAppointmentFee = premiumFeeWithPriceResponse
|
||||
? premiumFeeWithPriceResponse[0]
|
||||
: null;
|
||||
watch: {
|
||||
selectedDate(newValue, oldValue) {
|
||||
// Clear time slot selection if date selected changes
|
||||
if (newValue !== oldValue) {
|
||||
this.selectedTimeSlotInfo = {
|
||||
timeSlot: {
|
||||
date: null,
|
||||
routeCode: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null
|
||||
},
|
||||
isPremiumAppointment: null
|
||||
};
|
||||
}
|
||||
},
|
||||
selectedTimeSlotInfo(newValue) {
|
||||
this.updateFooterButtonText(newValue);
|
||||
}
|
||||
},
|
||||
async getAvailableDatesMethod(startDate, endDate) {
|
||||
const newShopTimeSlots = await getAvailableDates(
|
||||
startDate,
|
||||
endDate,
|
||||
this.appointmentType,
|
||||
this.mainStore.order.serviceLocation.provider.providerNumber
|
||||
);
|
||||
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
||||
this.selectableDatesData.days = this.selectableDatesData.days.concat(
|
||||
newShopTimeSlots.days
|
||||
);
|
||||
return newShopTimeSlots;
|
||||
},
|
||||
getAvailableDates,
|
||||
getServiceZipCtuCodeFromStore() {
|
||||
return this.mainStore.order.serviceLocation.zipCodeCtu;
|
||||
},
|
||||
openInshopTimeSlotsModal() {
|
||||
this.$refs.timeSlotModalQuestion.openModal();
|
||||
},
|
||||
getSelectedDate() {
|
||||
return this.mainStore.order.schedule.date;
|
||||
},
|
||||
getSelectedTimeSlotInfo() {
|
||||
const isPremiumAppointment =
|
||||
methods: {
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
arePagePrerequisitesValid() {
|
||||
const { serviceLocation } = useMainStore().order;
|
||||
const serviceLocationPreReqs =
|
||||
serviceLocation.zipCode
|
||||
&& serviceLocation.zipCodeCtu
|
||||
&& serviceLocation.appointmentType
|
||||
&& (serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| serviceLocation.appointmentType
|
||||
=== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
|| serviceLocation.provider.providerNumber);
|
||||
const supportingItems = this.supportingItems !== null;
|
||||
const damageInfo =
|
||||
useMainStore().order.damage.isRepair
|
||||
|| (useMainStore().order.lineItems?.glassParts != null
|
||||
&& useMainStore().order.lineItems.glassParts.length > 0);
|
||||
|
||||
return serviceLocationPreReqs && supportingItems && damageInfo;
|
||||
},
|
||||
setData(initialShopTimeSlotsResponse, premiumFeeWithPriceResponse) {
|
||||
this.selectableDatesData = initialShopTimeSlotsResponse;
|
||||
this.mobilePremiumAppointmentFee = premiumFeeWithPriceResponse
|
||||
? premiumFeeWithPriceResponse[0]
|
||||
: null;
|
||||
},
|
||||
async getAvailableDatesMethod(startDate, endDate) {
|
||||
const newShopTimeSlots = await getAvailableDates(
|
||||
startDate,
|
||||
endDate,
|
||||
this.appointmentType,
|
||||
this.mainStore.order.serviceLocation.provider.providerNumber
|
||||
);
|
||||
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
||||
this.selectableDatesData.days = this.selectableDatesData.days.concat(newShopTimeSlots.days);
|
||||
return newShopTimeSlots;
|
||||
},
|
||||
getAvailableDates,
|
||||
getServiceZipCtuCodeFromStore() {
|
||||
return this.mainStore.order.serviceLocation.zipCodeCtu;
|
||||
},
|
||||
openInshopTimeSlotsModal() {
|
||||
this.$refs.timeSlotModalQuestion.openModal();
|
||||
},
|
||||
getSelectedDate() {
|
||||
return this.mainStore.order.schedule.date;
|
||||
},
|
||||
getSelectedTimeSlotInfo() {
|
||||
const isPremiumAppointment =
|
||||
!!(
|
||||
this.supportingItems?.filter(
|
||||
(lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE
|
||||
) ?? []
|
||||
this.supportingItems?.filter((lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE) ?? []
|
||||
).length > 0;
|
||||
|
||||
const selectedTimeSlotInfo = {
|
||||
timeSlot: this.mainStore.order.schedule,
|
||||
isPremiumAppointment,
|
||||
};
|
||||
const selectedTimeSlotInfo = {
|
||||
timeSlot: this.mainStore.order.schedule,
|
||||
isPremiumAppointment
|
||||
};
|
||||
|
||||
return selectedTimeSlotInfo;
|
||||
},
|
||||
timeSlotModalClosed() {
|
||||
// Clear the selectedDate if no timeSlot has been selected
|
||||
if (this.selectedTimeSlotInfo.timeSlot.routeCode == null) {
|
||||
this.selectedDate = null;
|
||||
}
|
||||
},
|
||||
updateFooterButtonText(timeSlotInfo) {
|
||||
let navbarButtonText;
|
||||
if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) {
|
||||
navbarButtonText = "Continue";
|
||||
} else {
|
||||
navbarButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(
|
||||
timeSlotInfo.timeSlot.date
|
||||
)}`;
|
||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.startTime
|
||||
)}`;
|
||||
} else if (
|
||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||
!timeSlotInfo.isPremiumAppointment
|
||||
return selectedTimeSlotInfo;
|
||||
},
|
||||
timeSlotModalClosed() {
|
||||
// Clear the selectedDate if no timeSlot has been selected
|
||||
if (this.selectedTimeSlotInfo.timeSlot.routeCode == null) {
|
||||
this.selectedDate = null;
|
||||
}
|
||||
},
|
||||
updateFooterButtonText(timeSlotInfo) {
|
||||
let navbarButtonText;
|
||||
if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) {
|
||||
navbarButtonText = 'Continue';
|
||||
} else {
|
||||
navbarButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(timeSlotInfo.timeSlot.date)}`;
|
||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(timeSlotInfo.timeSlot.startTime)}`;
|
||||
} else if (
|
||||
this.appointmentType === AppointmentTypeStrings.MOBILE
|
||||
&& !timeSlotInfo.isPremiumAppointment
|
||||
) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.startTime,
|
||||
true
|
||||
)} - ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.endTime,
|
||||
true
|
||||
)}`;
|
||||
}
|
||||
}
|
||||
this.$refs.navbar.updateButtonText(navbarButtonText);
|
||||
},
|
||||
convertSelectedDateToShortMonthAndDay(selectedDate) {
|
||||
// This conversion ensures we don't get get GMT induced date changes
|
||||
const dateObject = convertDateStringToDate(selectedDate);
|
||||
return dateObject.toLocaleDateString('en-us', {
|
||||
month: 'short',
|
||||
day: 'numeric'
|
||||
});
|
||||
},
|
||||
getDisplayTextForMilitaryTime(
|
||||
militaryTimeInput,
|
||||
shouldTrimMinutesIfEmpty = false
|
||||
) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.startTime,
|
||||
true
|
||||
)} - ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.endTime,
|
||||
true
|
||||
)}`;
|
||||
// Expected input: "HH:MM"
|
||||
let hours = parseInt(militaryTimeInput.split(':')[0], 10);
|
||||
const minutes = militaryTimeInput.split(':')[1];
|
||||
const meridianNotation = hours > 11 ? 'PM' : 'AM';
|
||||
|
||||
if (hours > 12) {
|
||||
hours -= 12;
|
||||
}
|
||||
|
||||
if (shouldTrimMinutesIfEmpty && minutes === '00') {
|
||||
return `${hours} ${meridianNotation}`;
|
||||
}
|
||||
return `${hours}:${minutes} ${meridianNotation}`;
|
||||
},
|
||||
forwardButtonAction() {
|
||||
this.mainStore.saveSchedule(this.selectedTimeSlotInfo.timeSlot);
|
||||
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
}
|
||||
this.$refs.navbar.updateButtonText(navbarButtonText);
|
||||
},
|
||||
convertSelectedDateToShortMonthAndDay(selectedDate) {
|
||||
// This conversion ensures we don't get get GMT induced date changes
|
||||
const dateObject = convertDateStringToDate(selectedDate);
|
||||
return dateObject.toLocaleDateString("en-us", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
});
|
||||
},
|
||||
getDisplayTextForMilitaryTime(
|
||||
militaryTimeInput,
|
||||
shouldTrimMinutesIfEmpty = false
|
||||
) {
|
||||
// Expected input: "HH:MM"
|
||||
let hours = parseInt(militaryTimeInput.split(":")[0], 10);
|
||||
const minutes = militaryTimeInput.split(":")[1];
|
||||
const meridianNotation = hours > 11 ? "PM" : "AM";
|
||||
|
||||
if (hours > 12) {
|
||||
hours -= 12;
|
||||
}
|
||||
|
||||
if (shouldTrimMinutesIfEmpty && minutes === "00") {
|
||||
return `${hours} ${meridianNotation}`;
|
||||
}
|
||||
return `${hours}:${minutes} ${meridianNotation}`;
|
||||
},
|
||||
forwardButtonAction() {
|
||||
this.mainStore.saveSchedule(this.selectedTimeSlotInfo.timeSlot);
|
||||
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader class="mb-2 header" cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteHeader
|
||||
class="mb-2 header"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -16,8 +17,7 @@
|
|||
<siteSubHeader
|
||||
id="sub-header"
|
||||
cmsWidgetName="SiteSubHeader"
|
||||
class="mb-5 mt-4"
|
||||
/>
|
||||
class="mb-5 mt-4" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -28,44 +28,38 @@
|
|||
modalWidgetName="ServiceZipModalWidget"
|
||||
:onZipUpdateCallback="reloadShopData"
|
||||
@updatedServiceability="setServiceabilityDetails"
|
||||
@updatedContainsMilitaryBase="setContainsMilitaryBase"
|
||||
/>
|
||||
@updatedContainsMilitaryBase="setContainsMilitaryBase" />
|
||||
<alert
|
||||
v-if="displayMilitaryZipAlert"
|
||||
ref="alertMilitaryBaseZip"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
||||
alertClass="alert-warning"
|
||||
/>
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayServiceableMobileOnly"
|
||||
ref="alertMobileOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
alertClass="alert-warning"
|
||||
/>
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayRecalibrationWarning"
|
||||
ref="alertRecalNoMobile"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||
alertClass="alert-warning"
|
||||
@text-link-clicked="openModalAction"
|
||||
/>
|
||||
@text-link-clicked="openModalAction" />
|
||||
<alert
|
||||
v-if="displayServiceableInshopOnly"
|
||||
ref="alertInshopOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
alertClass="alert-warning"
|
||||
/>
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayNoShopsAlert"
|
||||
ref="alertNoShops"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertNoShopsWidget"
|
||||
alertClass="alert-warning"
|
||||
/>
|
||||
alertClass="alert-warning" />
|
||||
<appointmentTypeQuestion
|
||||
v-show="isAppointmentTypeDisplayed"
|
||||
ref="appointmentTypeQuestion"
|
||||
|
|
@ -75,8 +69,7 @@
|
|||
:isDisplayed="isAppointmentTypeDisplayed"
|
||||
groupName="appointmentTypeQuestion"
|
||||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||
validationRules="option-required"
|
||||
/>
|
||||
validationRules="option-required" />
|
||||
<mobileLocationModalQuestions
|
||||
v-if="isMobileLocationDisplayed"
|
||||
ref="mobileLocationQuestions"
|
||||
|
|
@ -89,8 +82,7 @@
|
|||
:onZipUpdateCallback="reloadShopData"
|
||||
@updated-mobile-fee-part="setMobileFeePart"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
@updated-contains-military-base="setContainsMilitaryBase"
|
||||
/>
|
||||
@updated-contains-military-base="setContainsMilitaryBase" />
|
||||
<shopQuestion
|
||||
v-show="isShopQuestionDisplayed"
|
||||
ref="shopQuestion"
|
||||
|
|
@ -98,10 +90,11 @@
|
|||
:selectedAppointmentType="selectedAppointmentType"
|
||||
:isDisplayed="isShopQuestionDisplayed"
|
||||
cmsWidgetName="ShopQuestionWidget"
|
||||
@updatedMobileProviderNumber="setMobileProviderNumber"
|
||||
/>
|
||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
</div>
|
||||
@updatedMobileProviderNumber="setMobileProviderNumber" />
|
||||
<contentGroupModal
|
||||
ref="RecalModal"
|
||||
cmsWidgetName="RecalModal" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
|
|
@ -111,8 +104,7 @@
|
|||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid || displayNoShopsAlert"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
/>
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -120,395 +112,393 @@
|
|||
</template>
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
import { AppointmentTypeStrings } from "@/constants/schedule-constants.js";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import settleAllPromises from "@/helpers/layout-helper";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import errorMessages from "@/constants/error-messages";
|
||||
import { useMainStore } from "@/store";
|
||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { useMainStore } from '@/store';
|
||||
import {
|
||||
getPricedMobileFeePart,
|
||||
getServiceabilityDetails,
|
||||
getZipCodeData,
|
||||
} from "@/helpers/service-location-helper";
|
||||
getPricedMobileFeePart,
|
||||
getServiceabilityDetails,
|
||||
getZipCodeData
|
||||
} from '@/helpers/service-location-helper';
|
||||
|
||||
// Import Component
|
||||
import alert from "@/ux-components/alert/alert.vue";
|
||||
import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question.vue";
|
||||
import baseFormMixin from "@/mixins/base-form-mixin";
|
||||
import contentGroupModal from "@/iss-components/content-group-modal/content-group-modal.vue";
|
||||
import mobileLocationModalQuestions from "@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import shopQuestion from "@/layouts/service-location/shop-question/shop-question.vue";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
|
||||
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue";
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import appointmentTypeQuestion from '@/layouts/service-location/appointment-type-question/appointment-type-question.vue';
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
||||
import mobileLocationModalQuestions from '@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue';
|
||||
import { Form, defineRule } from 'vee-validate';
|
||||
import shopQuestion from '@/layouts/service-location/shop-question/shop-question.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import serviceZipModalQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule("mobile-location-required", (value) => {
|
||||
if (
|
||||
value.addressQuestions.streetAddress === "" ||
|
||||
value.addressQuestions.city === "" ||
|
||||
value.addressQuestions.state === "" ||
|
||||
value.addressQuestions.zipCode === "" ||
|
||||
value.isVehicleProtected == null
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
return true;
|
||||
defineRule('mobile-location-required', (value) => {
|
||||
if (
|
||||
value.addressQuestions.streetAddress === ''
|
||||
|| value.addressQuestions.city === ''
|
||||
|| value.addressQuestions.state === ''
|
||||
|| value.addressQuestions.zipCode === ''
|
||||
|| value.isVehicleProtected == null
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
defineRule("selection-required", required(errorMessages.OPTION_REQUIRED));
|
||||
defineRule('selection-required', required(errorMessages.OPTION_REQUIRED));
|
||||
export default {
|
||||
name: "service-location",
|
||||
components: {
|
||||
alert,
|
||||
appointmentTypeQuestion,
|
||||
contentGroupModal,
|
||||
mobileLocationModalQuestions,
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
serviceZipModalQuestion,
|
||||
shopQuestion,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
name: 'service-location',
|
||||
components: {
|
||||
alert,
|
||||
appointmentTypeQuestion,
|
||||
contentGroupModal,
|
||||
mobileLocationModalQuestions,
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
serviceZipModalQuestion,
|
||||
shopQuestion
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
const serviceZipCode =
|
||||
useMainStore().order.serviceLocation.zipCode ||
|
||||
useMainStore().order.customer.address.zipCode;
|
||||
const zipCodeData = getZipCodeData(serviceZipCode);
|
||||
const serviceZipCode =
|
||||
useMainStore().order.serviceLocation.zipCode
|
||||
|| useMainStore().order.customer.address.zipCode;
|
||||
const zipCodeData = getZipCodeData(serviceZipCode);
|
||||
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
||||
const serviceabilityDetailsPromise =
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
||||
const serviceabilityDetailsPromise =
|
||||
getServiceabilityDetails(serviceZipCode);
|
||||
const shopQuestionInitialDataPromise =
|
||||
const shopQuestionInitialDataPromise =
|
||||
shopQuestion.methods.loadInitialData(serviceZipCode);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "mobileFeePart",
|
||||
promise: mobileFeePartPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "serviceabilityDetails",
|
||||
promise: serviceabilityDetailsPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "shopQuestionInitialData",
|
||||
promise: shopQuestionInitialDataPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "zipCodeData",
|
||||
promise: zipCodeData,
|
||||
},
|
||||
];
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'mobileFeePart',
|
||||
promise: mobileFeePartPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'serviceabilityDetails',
|
||||
promise: serviceabilityDetailsPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'shopQuestionInitialData',
|
||||
promise: shopQuestionInitialDataPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'zipCodeData',
|
||||
promise: zipCodeData
|
||||
}
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.setData(
|
||||
resultMap.zipCodeData,
|
||||
resultMap.serviceabilityDetails,
|
||||
resultMap.mobileFeePart,
|
||||
resultMap.shopQuestionInitialData?.mobileProviderNumber
|
||||
);
|
||||
vm.$refs.shopQuestion.initializeComponent(
|
||||
resultMap.shopQuestionInitialData
|
||||
);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
streetAddress: this.getServiceAddressFromStore(),
|
||||
streetAddress2: this.getServiceAddress2FromStore(),
|
||||
city: this.getServiceCityFromStore(),
|
||||
state: this.getServiceStateFromStore(),
|
||||
zipCode: this.getServiceZipCodeFromStore(),
|
||||
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
|
||||
isGlassServiceableInshop: null,
|
||||
isRecalibrationServiceableInshop: null,
|
||||
isGlassServiceableMobile: null,
|
||||
isRecalibrationServiceableMobile: null,
|
||||
selectedAppointmentType: this.getSelectedAppointmentType(),
|
||||
selectedProvider: this.getSelectedProvider(),
|
||||
mobileFeePart: null,
|
||||
mobileProviderNumber: null,
|
||||
zipContainsMilitaryBase: false,
|
||||
zipCodeCtu: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent("ServiceTypeQuestionWidget", "QuestionText");
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.setData(
|
||||
resultMap.zipCodeData,
|
||||
resultMap.serviceabilityDetails,
|
||||
resultMap.mobileFeePart,
|
||||
resultMap.shopQuestionInitialData?.mobileProviderNumber
|
||||
);
|
||||
vm.$refs.shopQuestion.initializeComponent(resultMap.shopQuestionInitialData);
|
||||
});
|
||||
},
|
||||
answersFromCms() {
|
||||
return this.getCmsContent("ServiceTypeQuestionWidget", "Answers");
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
serviceZipCodeQuestion: {
|
||||
get() {
|
||||
data() {
|
||||
return {
|
||||
state: this.state,
|
||||
zipCode: this.zipCode,
|
||||
streetAddress: this.getServiceAddressFromStore(),
|
||||
streetAddress2: this.getServiceAddress2FromStore(),
|
||||
city: this.getServiceCityFromStore(),
|
||||
state: this.getServiceStateFromStore(),
|
||||
zipCode: this.getServiceZipCodeFromStore(),
|
||||
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
|
||||
isGlassServiceableInshop: null,
|
||||
isRecalibrationServiceableInshop: null,
|
||||
isGlassServiceableMobile: null,
|
||||
isRecalibrationServiceableMobile: null,
|
||||
selectedAppointmentType: this.getSelectedAppointmentType(),
|
||||
selectedProvider: this.getSelectedProvider(),
|
||||
mobileFeePart: null,
|
||||
mobileProviderNumber: null,
|
||||
zipContainsMilitaryBase: false,
|
||||
zipCodeCtu: null
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
this.resetMobileLocation();
|
||||
this.selectedAppointmentType = null;
|
||||
this.selectedProvider = null;
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent('ServiceTypeQuestionWidget', 'QuestionText');
|
||||
},
|
||||
answersFromCms() {
|
||||
return this.getCmsContent('ServiceTypeQuestionWidget', 'Answers');
|
||||
},
|
||||
serviceZipCodeQuestion: {
|
||||
get() {
|
||||
return {
|
||||
state: this.state,
|
||||
zipCode: this.zipCode
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
this.resetMobileLocation();
|
||||
this.selectedAppointmentType = null;
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
|
||||
this.state = newValue.state;
|
||||
this.zipCode = newValue.zipCode;
|
||||
|
||||
// eslint-disable-next-line vue/valid-next-tick
|
||||
this.$nextTick();
|
||||
}
|
||||
},
|
||||
mobileLocationQuestions: {
|
||||
get() {
|
||||
return {
|
||||
addressQuestions: {
|
||||
streetAddress: this.streetAddress,
|
||||
streetAddress2: this.streetAddress2,
|
||||
city: this.city,
|
||||
state: this.state,
|
||||
zipCode: this.zipCode
|
||||
},
|
||||
isVehicleProtected: this.isVehicleProtected
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
this.streetAddress = newValue.addressQuestions.streetAddress;
|
||||
this.streetAddress2 = newValue.addressQuestions.streetAddress2;
|
||||
this.city = newValue.addressQuestions.city;
|
||||
this.state = newValue.addressQuestions.state;
|
||||
this.zipCode = newValue.addressQuestions.zipCode;
|
||||
this.isVehicleProtected = newValue.isVehicleProtected;
|
||||
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
if (
|
||||
!(
|
||||
this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType
|
||||
=== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
)
|
||||
) {
|
||||
this.selectedAppointmentType = null;
|
||||
}
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
isServiceableMobile() {
|
||||
if (this.isRecalibrationServiceableMobile !== null) {
|
||||
return (
|
||||
this.isGlassServiceableMobile && this.isRecalibrationServiceableMobile
|
||||
);
|
||||
}
|
||||
return this.isGlassServiceableMobile;
|
||||
},
|
||||
isServiceableInshop() {
|
||||
if (this.isRecalibrationServiceableInshop !== null) {
|
||||
return (
|
||||
this.isGlassServiceableInshop && this.isRecalibrationServiceableInshop
|
||||
);
|
||||
}
|
||||
|
||||
return this.isGlassServiceableInshop;
|
||||
},
|
||||
isShopQuestionDisplayed() {
|
||||
return (
|
||||
this.selectedAppointmentType === 'Inshop'
|
||||
|| this.selectedAppointmentType === 'Dropoff'
|
||||
);
|
||||
},
|
||||
isAppointmentTypeDisplayed() {
|
||||
return this.zipCode && !this.displayNoShopsAlert;
|
||||
},
|
||||
isMobileLocationDisplayed() {
|
||||
return (
|
||||
this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType
|
||||
=== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
);
|
||||
},
|
||||
requiresInshopRecalibration() {
|
||||
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
||||
return (
|
||||
this.isServiceableInshop
|
||||
&& this.isGlassServiceableMobile
|
||||
&& this.isRecalibrationServiceableMobile === false
|
||||
);
|
||||
},
|
||||
displayMilitaryZipAlert() {
|
||||
return this.zipContainsMilitaryBase && this.isServiceableMobile;
|
||||
},
|
||||
displayNoShopsAlert() {
|
||||
return !this.isServiceableInshop && !this.isServiceableMobile;
|
||||
},
|
||||
displayRecalibrationWarning() {
|
||||
return this.requiresInshopRecalibration;
|
||||
},
|
||||
displayServiceableInshopOnly() {
|
||||
return (
|
||||
!this.displayRecalibrationWarning
|
||||
&& this.isServiceableInshop
|
||||
&& !this.isServiceableMobile
|
||||
);
|
||||
},
|
||||
displayServiceableMobileOnly() {
|
||||
return this.isServiceableMobile && !this.isServiceableInshop;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return (
|
||||
useMainStore().lineItems.supportingItems !== null
|
||||
&& useMainStore().order.serviceLocation.zipCode !== null
|
||||
);
|
||||
},
|
||||
async reloadShopData(zipCode) {
|
||||
await this.$refs.shopQuestion.reloadShopData(zipCode);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
let provider = this.selectedProvider;
|
||||
this.mainStore.updateMobileFee(null);
|
||||
if (this.isMobileLocationDisplayed) {
|
||||
if (this.mainStore.isNoComp || this.mainStore.isITAC) {
|
||||
this.mainStore.updateMobileFee(this.mobileFeePart);
|
||||
}
|
||||
|
||||
this.state = newValue.state;
|
||||
this.zipCode = newValue.zipCode;
|
||||
provider = {
|
||||
providerNumber: this.mobileProviderNumber,
|
||||
address: {
|
||||
streetAddress: null,
|
||||
city: null,
|
||||
state: null,
|
||||
zipCode: null,
|
||||
zipCodeCtu: null
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line vue/valid-next-tick
|
||||
this.$nextTick();
|
||||
},
|
||||
},
|
||||
mobileLocationQuestions: {
|
||||
get() {
|
||||
return {
|
||||
addressQuestions: {
|
||||
streetAddress: this.streetAddress,
|
||||
streetAddress2: this.streetAddress2,
|
||||
city: this.city,
|
||||
state: this.state,
|
||||
zipCode: this.zipCode,
|
||||
},
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
this.streetAddress = newValue.addressQuestions.streetAddress;
|
||||
this.streetAddress2 = newValue.addressQuestions.streetAddress2;
|
||||
this.city = newValue.addressQuestions.city;
|
||||
this.state = newValue.addressQuestions.state;
|
||||
this.zipCode = newValue.addressQuestions.zipCode;
|
||||
this.isVehicleProtected = newValue.isVehicleProtected;
|
||||
this.mainStore.saveServiceLocation({
|
||||
address: this.streetAddress,
|
||||
address2: this.streetAddress2,
|
||||
city: this.city,
|
||||
state: this.state,
|
||||
zipCode: this.zipCode,
|
||||
zipCodeCtu: this.zipCodeCtu,
|
||||
appointmentType: this.selectedAppointmentType,
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
provider
|
||||
});
|
||||
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
if (
|
||||
!(
|
||||
this.selectedAppointmentType === AppointmentTypeStrings.MOBILE ||
|
||||
this.selectedAppointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
)
|
||||
) {
|
||||
this.selectedAppointmentType = null;
|
||||
}
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
isServiceableMobile() {
|
||||
if (this.isRecalibrationServiceableMobile !== null) {
|
||||
return (
|
||||
this.isGlassServiceableMobile && this.isRecalibrationServiceableMobile
|
||||
);
|
||||
}
|
||||
return this.isGlassServiceableMobile;
|
||||
},
|
||||
isServiceableInshop() {
|
||||
if (this.isRecalibrationServiceableInshop !== null) {
|
||||
return (
|
||||
this.isGlassServiceableInshop && this.isRecalibrationServiceableInshop
|
||||
);
|
||||
}
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
openModalAction(modalName) {
|
||||
this.$refs[modalName].openModal();
|
||||
},
|
||||
resetDependentState() {},
|
||||
getServiceAddressFromStore() {
|
||||
return useMainStore().order.serviceLocation.address;
|
||||
},
|
||||
getServiceAddress2FromStore() {
|
||||
return useMainStore().order.serviceLocation.address2;
|
||||
},
|
||||
getServiceCityFromStore() {
|
||||
return useMainStore().order.serviceLocation.city;
|
||||
},
|
||||
getServiceStateFromStore() {
|
||||
return (
|
||||
useMainStore().order.serviceLocation.state
|
||||
|| useMainStore().order.customer.address.state
|
||||
);
|
||||
},
|
||||
getServiceZipCodeFromStore() {
|
||||
return (
|
||||
useMainStore().order.serviceLocation.zipCode
|
||||
|| useMainStore().order.customer.address.zipCode
|
||||
);
|
||||
},
|
||||
getIsVehicleProtectedFromStore() {
|
||||
return useMainStore().order.serviceLocation.isVehicleProtected;
|
||||
},
|
||||
getSelectedAppointmentType() {
|
||||
return useMainStore().order.serviceLocation.appointmentType;
|
||||
},
|
||||
getSelectedProvider() {
|
||||
return useMainStore().order.serviceLocation.provider;
|
||||
},
|
||||
setData(
|
||||
zipCodeData,
|
||||
serviceabilityDetails,
|
||||
mobileFeePart,
|
||||
mobileProviderNumber
|
||||
) {
|
||||
if (zipCodeData) {
|
||||
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
|
||||
this.zipCodeCtu = zipCodeData.zipCodeCtu;
|
||||
}
|
||||
|
||||
return this.isGlassServiceableInshop;
|
||||
},
|
||||
isShopQuestionDisplayed() {
|
||||
return (
|
||||
this.selectedAppointmentType === "Inshop" ||
|
||||
this.selectedAppointmentType === "Dropoff"
|
||||
);
|
||||
},
|
||||
isAppointmentTypeDisplayed() {
|
||||
return this.zipCode && !this.displayNoShopsAlert;
|
||||
},
|
||||
isMobileLocationDisplayed() {
|
||||
return (
|
||||
this.selectedAppointmentType === AppointmentTypeStrings.MOBILE ||
|
||||
this.selectedAppointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
);
|
||||
},
|
||||
requiresInshopRecalibration() {
|
||||
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
||||
return (
|
||||
this.isServiceableInshop &&
|
||||
this.isGlassServiceableMobile &&
|
||||
this.isRecalibrationServiceableMobile === false
|
||||
);
|
||||
},
|
||||
displayMilitaryZipAlert() {
|
||||
return this.zipContainsMilitaryBase && this.isServiceableMobile;
|
||||
},
|
||||
displayNoShopsAlert() {
|
||||
return !this.isServiceableInshop && !this.isServiceableMobile;
|
||||
},
|
||||
displayRecalibrationWarning() {
|
||||
return this.requiresInshopRecalibration;
|
||||
},
|
||||
displayServiceableInshopOnly() {
|
||||
return (
|
||||
!this.displayRecalibrationWarning &&
|
||||
this.isServiceableInshop &&
|
||||
!this.isServiceableMobile
|
||||
);
|
||||
},
|
||||
displayServiceableMobileOnly() {
|
||||
return this.isServiceableMobile && !this.isServiceableInshop;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return (
|
||||
useMainStore().lineItems.supportingItems !== null &&
|
||||
useMainStore().order.serviceLocation.zipCode !== null
|
||||
);
|
||||
},
|
||||
async reloadShopData(zipCode) {
|
||||
await this.$refs.shopQuestion.reloadShopData(zipCode);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
let provider = this.selectedProvider;
|
||||
this.mainStore.updateMobileFee(null);
|
||||
if (this.isMobileLocationDisplayed) {
|
||||
if (this.mainStore.isNoComp || this.mainStore.isITAC) {
|
||||
this.mainStore.updateMobileFee(this.mobileFeePart);
|
||||
}
|
||||
if (serviceabilityDetails) {
|
||||
this.setServiceabilityDetails(serviceabilityDetails);
|
||||
}
|
||||
|
||||
provider = {
|
||||
providerNumber: this.mobileProviderNumber,
|
||||
address: {
|
||||
streetAddress: null,
|
||||
city: null,
|
||||
state: null,
|
||||
zipCode: null,
|
||||
zipCodeCtu: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (mobileFeePart) {
|
||||
this.mobileFeePart = mobileFeePart;
|
||||
}
|
||||
|
||||
this.mainStore.saveServiceLocation({
|
||||
address: this.streetAddress,
|
||||
address2: this.streetAddress2,
|
||||
city: this.city,
|
||||
state: this.state,
|
||||
zipCode: this.zipCode,
|
||||
zipCodeCtu: this.zipCodeCtu,
|
||||
appointmentType: this.selectedAppointmentType,
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
provider,
|
||||
});
|
||||
if (mobileProviderNumber) {
|
||||
this.setMobileProviderNumber(mobileProviderNumber);
|
||||
}
|
||||
},
|
||||
setContainsMilitaryBase(val) {
|
||||
if (this.zipContainsMilitaryBase !== val) {
|
||||
this.zipContainsMilitaryBase = val;
|
||||
}
|
||||
},
|
||||
setMobileFeePart(mobileFeePart) {
|
||||
this.mobileFeePart = mobileFeePart;
|
||||
},
|
||||
setMobileProviderNumber(providerNumber) {
|
||||
this.mobileProviderNumber = providerNumber;
|
||||
},
|
||||
resetMobileLocation() {
|
||||
this.streetAddress = '';
|
||||
this.streetAddress2 = '';
|
||||
this.city = '';
|
||||
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
openModalAction(modalName) {
|
||||
this.$refs[modalName].openModal();
|
||||
},
|
||||
resetDependentState() {},
|
||||
getServiceAddressFromStore() {
|
||||
return useMainStore().order.serviceLocation.address;
|
||||
},
|
||||
getServiceAddress2FromStore() {
|
||||
return useMainStore().order.serviceLocation.address2;
|
||||
},
|
||||
getServiceCityFromStore() {
|
||||
return useMainStore().order.serviceLocation.city;
|
||||
},
|
||||
getServiceStateFromStore() {
|
||||
return (
|
||||
useMainStore().order.serviceLocation.state ||
|
||||
useMainStore().order.customer.address.state
|
||||
);
|
||||
},
|
||||
getServiceZipCodeFromStore() {
|
||||
return (
|
||||
useMainStore().order.serviceLocation.zipCode ||
|
||||
useMainStore().order.customer.address.zipCode
|
||||
);
|
||||
},
|
||||
getIsVehicleProtectedFromStore() {
|
||||
return useMainStore().order.serviceLocation.isVehicleProtected;
|
||||
},
|
||||
getSelectedAppointmentType() {
|
||||
return useMainStore().order.serviceLocation.appointmentType;
|
||||
},
|
||||
getSelectedProvider() {
|
||||
return useMainStore().order.serviceLocation.provider;
|
||||
},
|
||||
setData(
|
||||
zipCodeData,
|
||||
serviceabilityDetails,
|
||||
mobileFeePart,
|
||||
mobileProviderNumber
|
||||
) {
|
||||
if (zipCodeData) {
|
||||
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
|
||||
this.zipCodeCtu = zipCodeData.zipCodeCtu;
|
||||
}
|
||||
|
||||
if (serviceabilityDetails) {
|
||||
this.setServiceabilityDetails(serviceabilityDetails);
|
||||
}
|
||||
|
||||
if (mobileFeePart) {
|
||||
this.mobileFeePart = mobileFeePart;
|
||||
}
|
||||
|
||||
if (mobileProviderNumber) {
|
||||
this.setMobileProviderNumber(mobileProviderNumber);
|
||||
}
|
||||
},
|
||||
setContainsMilitaryBase(val) {
|
||||
if (this.zipContainsMilitaryBase !== val) {
|
||||
this.zipContainsMilitaryBase = val;
|
||||
}
|
||||
},
|
||||
setMobileFeePart(mobileFeePart) {
|
||||
this.mobileFeePart = mobileFeePart;
|
||||
},
|
||||
setMobileProviderNumber(providerNumber) {
|
||||
this.mobileProviderNumber = providerNumber;
|
||||
},
|
||||
resetMobileLocation() {
|
||||
this.streetAddress = "";
|
||||
this.streetAddress2 = "";
|
||||
this.city = "";
|
||||
|
||||
this.isVehicleProtected = null;
|
||||
},
|
||||
setServiceabilityDetails(serviceabilityDetails) {
|
||||
this.isGlassServiceableInshop =
|
||||
this.isVehicleProtected = null;
|
||||
},
|
||||
setServiceabilityDetails(serviceabilityDetails) {
|
||||
this.isGlassServiceableInshop =
|
||||
serviceabilityDetails.isGlassServiceableInshop;
|
||||
this.isRecalibrationServiceableInshop =
|
||||
this.isRecalibrationServiceableInshop =
|
||||
serviceabilityDetails.isRecalibrationServiceableInshop;
|
||||
this.isGlassServiceableMobile =
|
||||
this.isGlassServiceableMobile =
|
||||
serviceabilityDetails.isGlassServiceableMobile;
|
||||
this.isRecalibrationServiceableMobile =
|
||||
this.isRecalibrationServiceableMobile =
|
||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
|
|
@ -13,520 +12,458 @@
|
|||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<alert
|
||||
v-if="shouldDisplayVehicleChangeAlert"
|
||||
ref="vehicleChangeAlert"
|
||||
class="mt-5 mb-0"
|
||||
cmsWidgetName="VehicleChangeAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
<vehicleBanner
|
||||
class="mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false"
|
||||
/>
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<damageLocationQuestion
|
||||
ref="damageLocation"
|
||||
v-model="selectedDamageLocations"
|
||||
cmsWidgetName="DamageLocationQuestion"
|
||||
groupName="DamageLocationQuestion"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<windshieldOptions
|
||||
ref="windshieldOptions"
|
||||
v-model="selectedWindshieldOptions"
|
||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<alert
|
||||
v-if="hasRepairReplaceConflict"
|
||||
class="my-5"
|
||||
cmsWidgetName="HasReplacementConflict"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<sideDoorOptions
|
||||
v-show="!hasRepairReplaceConflict"
|
||||
ref="sideDoorOptions"
|
||||
v-model="sideDoorOptionsData"
|
||||
cmsWidgetName="SideDoorSideQuestion"
|
||||
groupName="SideDoorSideQuestion"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<replaceOptionsQuestion
|
||||
ref="backGlassOptions"
|
||||
v-model="selectedRearReplaceOptions"
|
||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||
:isAvailable="
|
||||
isRearWindowDamageLocation && !hasRepairReplaceConflict
|
||||
"
|
||||
groupName="BackGlassReplaceOptionsQuestion"
|
||||
validationRules="replace-options-required"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<site-footer
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<alert
|
||||
v-if="shouldDisplayVehicleChangeAlert"
|
||||
ref="vehicleChangeAlert"
|
||||
class="mt-5 mb-0"
|
||||
cmsWidgetName="VehicleChangeAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<vehicleBanner
|
||||
class="mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<damageLocationQuestion
|
||||
ref="damageLocation"
|
||||
v-model="selectedDamageLocations"
|
||||
cmsWidgetName="DamageLocationQuestion"
|
||||
groupName="DamageLocationQuestion" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<windshieldOptions
|
||||
ref="windshieldOptions"
|
||||
v-model="selectedWindshieldOptions"
|
||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-3" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<alert
|
||||
v-if="hasRepairReplaceConflict"
|
||||
class="my-5"
|
||||
cmsWidgetName="HasReplacementConflict"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<sideDoorOptions
|
||||
v-show="!hasRepairReplaceConflict"
|
||||
ref="sideDoorOptions"
|
||||
v-model="sideDoorOptionsData"
|
||||
cmsWidgetName="SideDoorSideQuestion"
|
||||
groupName="SideDoorSideQuestion"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-1" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<replaceOptionsQuestion
|
||||
ref="backGlassOptions"
|
||||
v-model="selectedRearReplaceOptions"
|
||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||
:isAvailable="
|
||||
isRearWindowDamageLocation && !hasRepairReplaceConflict
|
||||
"
|
||||
groupName="BackGlassReplaceOptionsQuestion"
|
||||
validationRules="replace-options-required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<site-footer
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner.vue";
|
||||
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
|
||||
import sideDoorOptions from "@/layouts/vehicle-damage/side-door-options/side-door-options.vue";
|
||||
import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question.vue";
|
||||
import windshieldOptions from "@/layouts/vehicle-damage/windshield-options/windshield-options.vue";
|
||||
import replaceOptionsQuestion from "@/layouts/vehicle-damage/replace-options-question/replace-options-question.vue";
|
||||
import alert from "@/ux-components/alert/alert.vue";
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import sideDoorOptions from '@/layouts/vehicle-damage/side-door-options/side-door-options.vue';
|
||||
import damageLocationQuestion from '@/layouts/vehicle-damage/damage-location-question/damage-location-question.vue';
|
||||
import windshieldOptions from '@/layouts/vehicle-damage/windshield-options/windshield-options.vue';
|
||||
import replaceOptionsQuestion from '@/layouts/vehicle-damage/replace-options-question/replace-options-question.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
|
||||
// Supporting files
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-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 damageLocationsCms from "@/constants/damage-locations-cms.js";
|
||||
import damageLocationsSelected from "@/constants/damage-locations-selected.js";
|
||||
import { useMainStore } from "@/store";
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-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 damageLocationsCms from '@/constants/damage-locations-cms.js';
|
||||
import damageLocationsSelected from '@/constants/damage-locations-selected.js';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule(
|
||||
"replace-options-required",
|
||||
required(errorMessages.REPLACE_OPTIONS_REQUIRED)
|
||||
'replace-options-required',
|
||||
required(errorMessages.REPLACE_OPTIONS_REQUIRED)
|
||||
);
|
||||
|
||||
export default {
|
||||
name: "vehicle-damage",
|
||||
name: 'vehicle-damage',
|
||||
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
sideDoorOptions,
|
||||
damageLocationQuestion,
|
||||
windshieldOptions,
|
||||
replaceOptionsQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
alert,
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const store = useMainStore();
|
||||
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const damageOptionsPromise = store.getDamageOptions(
|
||||
store.order.vehicle.carId
|
||||
);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "damageOptions",
|
||||
promise: damageOptionsPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.damageLocation.initializeComponent(resultMap.damageOptions);
|
||||
vm.$refs.sideDoorOptions.initializeComponent(
|
||||
resultMap.damageOptions.driverSideOptions.availableReplacementOptions,
|
||||
resultMap.damageOptions.passengerSideOptions.availableReplacementOptions
|
||||
);
|
||||
vm.$refs.windshieldOptions.initializeComponent(
|
||||
resultMap.damageOptions.windshieldOptions.availableReplacementOptions
|
||||
);
|
||||
vm.$refs.backGlassOptions.initializeComponent(
|
||||
resultMap.damageOptions.backGlassOptions.availableReplacementOptions
|
||||
);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedDamageLocations: this.getDamageLocationsFromStore(),
|
||||
sideDoorOptionsData: {
|
||||
selectedDoorSides: this.getDoorSidesFromStore(),
|
||||
selectedDriverSideReplaceOptions:
|
||||
this.getDriverSideReplaceOptionsFromStore(),
|
||||
selectedPassengerSideReplaceOptions:
|
||||
this.getPassengerSideReplaceOptionsFromStore(),
|
||||
},
|
||||
selectedWindshieldOptions: this.getWindshieldOptionsFromStore(),
|
||||
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isWindshieldDamageLocation() {
|
||||
return this.selectedDamageLocations.some(
|
||||
(selectedDamages) =>
|
||||
selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD
|
||||
);
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
sideDoorOptions,
|
||||
damageLocationQuestion,
|
||||
windshieldOptions,
|
||||
replaceOptionsQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
alert
|
||||
},
|
||||
isSideDoorDamageLocation() {
|
||||
return this.selectedDamageLocations.some(
|
||||
(selectedDamages) =>
|
||||
selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR
|
||||
);
|
||||
},
|
||||
isRearWindowDamageLocation() {
|
||||
return this.selectedDamageLocations.some(
|
||||
(selectedDamages) =>
|
||||
selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW
|
||||
);
|
||||
},
|
||||
isWindshieldRepair() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation &&
|
||||
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
||||
damageLocationsSelected.REPAIR
|
||||
);
|
||||
},
|
||||
isDriverSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const store = useMainStore();
|
||||
|
||||
return this.sideDoorOptionsData.selectedDoorSides.some(
|
||||
(selectedDriverSide) =>
|
||||
selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE
|
||||
);
|
||||
},
|
||||
isPassengerSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const damageOptionsPromise = store.getDamageOptions(store.order.vehicle.carId);
|
||||
|
||||
return this.sideDoorOptionsData.selectedDoorSides.some(
|
||||
(selectedPassengerSide) =>
|
||||
selectedPassengerSide.toUpperCase() ===
|
||||
damageLocationsCms.PASSENGERSIDE
|
||||
);
|
||||
},
|
||||
hasRepairReplaceConflict() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation &&
|
||||
this.selectedDamageLocations.length > 1 &&
|
||||
this.isWindshieldRepair
|
||||
);
|
||||
},
|
||||
hasSplitSingleConflict() {
|
||||
if (
|
||||
!this.selectedDamageLocations?.includes("Windshield") ||
|
||||
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
||||
damageLocationsSelected.REPAIR ||
|
||||
!this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
|
||||
)
|
||||
return false;
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'damageOptions',
|
||||
promise: damageOptionsPromise
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||
(selectedSingleWindshield) =>
|
||||
selectedSingleWindshield.toUpperCase() ===
|
||||
damageLocationsSelected.SINGLE.toUpperCase()
|
||||
) &&
|
||||
(this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||
(selectedDriverWindshield) =>
|
||||
selectedDriverWindshield.toUpperCase() ===
|
||||
damageLocationsSelected.DRIVER.toUpperCase()
|
||||
) ||
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||
(selectedPassengerWindshield) =>
|
||||
selectedPassengerWindshield.toUpperCase() ===
|
||||
damageLocationsSelected.PASSENGER.toUpperCase()
|
||||
))
|
||||
);
|
||||
},
|
||||
shouldDisplayVehicleChangeAlert() {
|
||||
return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
if (useMainStore().order.vehicle.carId) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getDamageLocationsFromStore() {
|
||||
const glassSelections = [];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) => glass.glassLocation === damageLocationsSelected.WINDSHIELD
|
||||
) ||
|
||||
this.mainStore.order.damage.isRepair
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.WINDSHIELD);
|
||||
}
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.DRIVER ||
|
||||
glass.glassLocation === damageLocationsSelected.PASSENGER
|
||||
)
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.SIDEDOOR);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) => glass.glassLocation === damageLocationsSelected.REAR
|
||||
)
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.REARWINDOW);
|
||||
}
|
||||
|
||||
return glassSelections;
|
||||
},
|
||||
getWindshieldOptionsFromStore() {
|
||||
const windShieldOptions = {
|
||||
selectedWindshieldDamageType: "",
|
||||
selectedWindshieldChipCount: null,
|
||||
selectedWindshieldReplaceOptions: [],
|
||||
};
|
||||
|
||||
if (this.mainStore.order.damage.isRepair === undefined)
|
||||
return windshieldOptions;
|
||||
|
||||
if (this.mainStore.order.damage.isRepair) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPAIR;
|
||||
windShieldOptions.selectedWindshieldChipCount =
|
||||
this.mainStore.order.damage.numberOfChips;
|
||||
} else {
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.SINGLE
|
||||
)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.SINGLE
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.DRIVER
|
||||
)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.DRIVER
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.PASSENGER
|
||||
)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.PASSENGER
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return windShieldOptions;
|
||||
},
|
||||
getDoorSidesFromStore() {
|
||||
const doorSides = [];
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) => glass.glassLocation === damageLocationsSelected.DRIVER
|
||||
)
|
||||
) {
|
||||
doorSides.push(damageLocationsSelected.DRIVERSIDE);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) => glass.glassLocation === damageLocationsSelected.PASSENGER
|
||||
)
|
||||
) {
|
||||
doorSides.push(damageLocationsSelected.PASSENGERSIDE);
|
||||
}
|
||||
|
||||
return doorSides;
|
||||
},
|
||||
getDriverSideReplaceOptionsFromStore() {
|
||||
const driverSideReplaceOptions = [];
|
||||
|
||||
this.mainStore.order.damage.glassToReplace?.forEach((glass) => {
|
||||
if (glass.glassLocation === damageLocationsSelected.DRIVER) {
|
||||
driverSideReplaceOptions.push(glass.glassName);
|
||||
}
|
||||
});
|
||||
|
||||
return driverSideReplaceOptions;
|
||||
},
|
||||
getPassengerSideReplaceOptionsFromStore() {
|
||||
const passengerSideReplaceOptions = [];
|
||||
|
||||
this.mainStore.order.damage.glassToReplace?.forEach((glass) => {
|
||||
if (glass.glassLocation === damageLocationsSelected.PASSENGER) {
|
||||
passengerSideReplaceOptions.push(glass.glassName);
|
||||
}
|
||||
});
|
||||
|
||||
return passengerSideReplaceOptions;
|
||||
},
|
||||
getRearReplaceOptionsFromStore() {
|
||||
const rearReplaceOptions =
|
||||
this.mainStore.order.damage.glassToReplace?.filter(
|
||||
(glass) => glass.glassLocation === damageLocationsSelected.REAR
|
||||
)[0]?.glassName;
|
||||
|
||||
return rearReplaceOptions;
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
this.mainStore.saveVehicleDamage(
|
||||
this.isWindshieldRepair,
|
||||
this.selectedGlassToReplace(),
|
||||
this.selectedWindshieldOptions.selectedWindshieldChipCount
|
||||
);
|
||||
|
||||
if (this.isWindshieldRepair) {
|
||||
const supportingItems = await useMainStore().getSupportingItems();
|
||||
useMainStore().updateSupportingItems(supportingItems.data);
|
||||
}
|
||||
|
||||
if (this.mainStore.damage.isRepair) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
|
||||
this.$route
|
||||
);
|
||||
} else if (this.mainStore.order.vehicle.vin) {
|
||||
// If vin already exists, navigate directly to vin-lookup
|
||||
|
||||
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
||||
if (partsOrQuestionsResponse.error) {
|
||||
// To Do: Need requirement on what to do here
|
||||
window.console.error("Error on retrieving PartsOrQuestions");
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||
await this.navigateForward(
|
||||
partsOrQuestionsResponse.data.partsOrQuestions,
|
||||
this
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
selectedGlassToReplace() {
|
||||
const selectedGlassToReplace = [];
|
||||
if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) {
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach(
|
||||
(wsItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.WINDSHIELD,
|
||||
glassName: wsItem,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isDriverSideReplace) {
|
||||
this.sideDoorOptionsData.selectedDriverSideReplaceOptions.forEach(
|
||||
(driverItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.DRIVER,
|
||||
glassName: driverItem,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isPassengerSideReplace) {
|
||||
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach(
|
||||
(passengerItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.PASSENGER,
|
||||
glassName: passengerItem,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isRearWindowDamageLocation) {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.REAR,
|
||||
glassName: this.selectedRearReplaceOptions,
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.damageLocation.initializeComponent(resultMap.damageOptions);
|
||||
vm.$refs.sideDoorOptions.initializeComponent(
|
||||
resultMap.damageOptions.driverSideOptions.availableReplacementOptions,
|
||||
resultMap.damageOptions.passengerSideOptions.availableReplacementOptions
|
||||
);
|
||||
vm.$refs.windshieldOptions.initializeComponent(resultMap.damageOptions.windshieldOptions.availableReplacementOptions);
|
||||
vm.$refs.backGlassOptions.initializeComponent(resultMap.damageOptions.backGlassOptions.availableReplacementOptions);
|
||||
});
|
||||
}
|
||||
|
||||
return selectedGlassToReplace;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedDamageLocations: this.getDamageLocationsFromStore(),
|
||||
sideDoorOptionsData: {
|
||||
selectedDoorSides: this.getDoorSidesFromStore(),
|
||||
selectedDriverSideReplaceOptions:
|
||||
this.getDriverSideReplaceOptionsFromStore(),
|
||||
selectedPassengerSideReplaceOptions:
|
||||
this.getPassengerSideReplaceOptionsFromStore()
|
||||
},
|
||||
selectedWindshieldOptions: this.getWindshieldOptionsFromStore(),
|
||||
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore()
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isWindshieldDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) =>
|
||||
selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD);
|
||||
},
|
||||
isSideDoorDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) =>
|
||||
selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR);
|
||||
},
|
||||
isRearWindowDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) =>
|
||||
selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW);
|
||||
},
|
||||
isWindshieldRepair() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation
|
||||
&& this.selectedWindshieldOptions.selectedWindshieldDamageType
|
||||
=== damageLocationsSelected.REPAIR
|
||||
);
|
||||
},
|
||||
isDriverSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
|
||||
return this.sideDoorOptionsData.selectedDoorSides.some((selectedDriverSide) =>
|
||||
selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE);
|
||||
},
|
||||
isPassengerSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
|
||||
return this.sideDoorOptionsData.selectedDoorSides.some((selectedPassengerSide) =>
|
||||
selectedPassengerSide.toUpperCase()
|
||||
=== damageLocationsCms.PASSENGERSIDE);
|
||||
},
|
||||
hasRepairReplaceConflict() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation
|
||||
&& this.selectedDamageLocations.length > 1
|
||||
&& this.isWindshieldRepair
|
||||
);
|
||||
},
|
||||
hasSplitSingleConflict() {
|
||||
if (
|
||||
!this.selectedDamageLocations?.includes('Windshield')
|
||||
|| this.selectedWindshieldOptions.selectedWindshieldDamageType
|
||||
=== damageLocationsSelected.REPAIR
|
||||
|| !this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
|
||||
) return false;
|
||||
|
||||
return (
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some((selectedSingleWindshield) =>
|
||||
selectedSingleWindshield.toUpperCase()
|
||||
=== damageLocationsSelected.SINGLE.toUpperCase())
|
||||
&& (this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some((selectedDriverWindshield) =>
|
||||
selectedDriverWindshield.toUpperCase()
|
||||
=== damageLocationsSelected.DRIVER.toUpperCase())
|
||||
|| this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some((selectedPassengerWindshield) =>
|
||||
selectedPassengerWindshield.toUpperCase()
|
||||
=== damageLocationsSelected.PASSENGER.toUpperCase()))
|
||||
);
|
||||
},
|
||||
shouldDisplayVehicleChangeAlert() {
|
||||
return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
if (useMainStore().order.vehicle.carId) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getDamageLocationsFromStore() {
|
||||
const glassSelections = [];
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.WINDSHIELD)
|
||||
|| this.mainStore.order.damage.isRepair
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.WINDSHIELD);
|
||||
}
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.DRIVER
|
||||
|| glass.glassLocation === damageLocationsSelected.PASSENGER)
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.SIDEDOOR);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.REAR)
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.REARWINDOW);
|
||||
}
|
||||
|
||||
return glassSelections;
|
||||
},
|
||||
getWindshieldOptionsFromStore() {
|
||||
const windShieldOptions = {
|
||||
selectedWindshieldDamageType: '',
|
||||
selectedWindshieldChipCount: null,
|
||||
selectedWindshieldReplaceOptions: []
|
||||
};
|
||||
|
||||
if (this.mainStore.order.damage.isRepair === undefined) return windshieldOptions;
|
||||
|
||||
if (this.mainStore.order.damage.isRepair) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPAIR;
|
||||
windShieldOptions.selectedWindshieldChipCount =
|
||||
this.mainStore.order.damage.numberOfChips;
|
||||
} else {
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD
|
||||
&& glass.glassName === damageLocationsSelected.SINGLE)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(damageLocationsSelected.SINGLE);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD
|
||||
&& glass.glassName === damageLocationsSelected.DRIVER)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(damageLocationsSelected.DRIVER);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD
|
||||
&& glass.glassName === damageLocationsSelected.PASSENGER)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(damageLocationsSelected.PASSENGER);
|
||||
}
|
||||
}
|
||||
|
||||
return windShieldOptions;
|
||||
},
|
||||
getDoorSidesFromStore() {
|
||||
const doorSides = [];
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.DRIVER)
|
||||
) {
|
||||
doorSides.push(damageLocationsSelected.DRIVERSIDE);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.PASSENGER)
|
||||
) {
|
||||
doorSides.push(damageLocationsSelected.PASSENGERSIDE);
|
||||
}
|
||||
|
||||
return doorSides;
|
||||
},
|
||||
getDriverSideReplaceOptionsFromStore() {
|
||||
const driverSideReplaceOptions = [];
|
||||
|
||||
this.mainStore.order.damage.glassToReplace?.forEach((glass) => {
|
||||
if (glass.glassLocation === damageLocationsSelected.DRIVER) {
|
||||
driverSideReplaceOptions.push(glass.glassName);
|
||||
}
|
||||
});
|
||||
|
||||
return driverSideReplaceOptions;
|
||||
},
|
||||
getPassengerSideReplaceOptionsFromStore() {
|
||||
const passengerSideReplaceOptions = [];
|
||||
|
||||
this.mainStore.order.damage.glassToReplace?.forEach((glass) => {
|
||||
if (glass.glassLocation === damageLocationsSelected.PASSENGER) {
|
||||
passengerSideReplaceOptions.push(glass.glassName);
|
||||
}
|
||||
});
|
||||
|
||||
return passengerSideReplaceOptions;
|
||||
},
|
||||
getRearReplaceOptionsFromStore() {
|
||||
const rearReplaceOptions =
|
||||
this.mainStore.order.damage.glassToReplace?.filter((glass) => glass.glassLocation === damageLocationsSelected.REAR)[0]?.glassName;
|
||||
|
||||
return rearReplaceOptions;
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
this.mainStore.saveVehicleDamage(
|
||||
this.isWindshieldRepair,
|
||||
this.selectedGlassToReplace(),
|
||||
this.selectedWindshieldOptions.selectedWindshieldChipCount
|
||||
);
|
||||
|
||||
if (this.isWindshieldRepair) {
|
||||
const supportingItems = await useMainStore().getSupportingItems();
|
||||
useMainStore().updateSupportingItems(supportingItems.data);
|
||||
}
|
||||
|
||||
if (this.mainStore.damage.isRepair) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
|
||||
this.$route
|
||||
);
|
||||
} else if (this.mainStore.order.vehicle.vin) {
|
||||
// If vin already exists, navigate directly to vin-lookup
|
||||
|
||||
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
||||
if (partsOrQuestionsResponse.error) {
|
||||
// To Do: Need requirement on what to do here
|
||||
window.console.error('Error on retrieving PartsOrQuestions');
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||
await this.navigateForward(
|
||||
partsOrQuestionsResponse.data.partsOrQuestions,
|
||||
this
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
selectedGlassToReplace() {
|
||||
const selectedGlassToReplace = [];
|
||||
if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) {
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach((wsItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.WINDSHIELD,
|
||||
glassName: wsItem
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isDriverSideReplace) {
|
||||
this.sideDoorOptionsData.selectedDriverSideReplaceOptions.forEach((driverItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.DRIVER,
|
||||
glassName: driverItem
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isPassengerSideReplace) {
|
||||
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach((passengerItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.PASSENGER,
|
||||
glassName: passengerItem
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isRearWindowDamageLocation) {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.REAR,
|
||||
glassName: this.selectedRearReplaceOptions
|
||||
});
|
||||
}
|
||||
|
||||
return selectedGlassToReplace;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalidSubmit="onInvalidSubmit">
|
||||
<Form
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
|
|
@ -12,25 +14,21 @@
|
|||
<VehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false"
|
||||
/>
|
||||
:displayGenericVehicleImage="false" />
|
||||
<SiteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-5 mb-2"
|
||||
/>
|
||||
class="mt-5 mb-2" />
|
||||
<VinLookupMethods
|
||||
ref="VinLookupMethods"
|
||||
v-model="selectedVinLookupMethod"
|
||||
cmsWidgetName="VINLookupMethod"
|
||||
groupName="VinLookupMethods"
|
||||
/>
|
||||
groupName="VinLookupMethods" />
|
||||
<SiteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
class="mt-5"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
/>
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -39,88 +37,88 @@
|
|||
</template>
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import settleAllPromises from "@/helpers/layout-helper";
|
||||
import { Form } from "vee-validate";
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin";
|
||||
import vinLookupMethodSelections from "@/constants/vin-lookup-methods";
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin';
|
||||
import vinLookupMethodSelections from '@/constants/vin-lookup-methods';
|
||||
|
||||
// Import Component
|
||||
import SiteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import SiteHeader from "@/iss-components/site-header/site-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 VinLookupMethods from "@/layouts/vehicle-lookup/vin-lookup-methods/vin-lookup-methods.vue";
|
||||
import SiteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import SiteHeader from '@/iss-components/site-header/site-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 VinLookupMethods from '@/layouts/vehicle-lookup/vin-lookup-methods/vin-lookup-methods.vue';
|
||||
|
||||
export default {
|
||||
name: "vehicle-lookup",
|
||||
components: {
|
||||
name: 'vehicle-lookup',
|
||||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
SiteFooter,
|
||||
SiteHeader,
|
||||
SiteSubHeader,
|
||||
VehicleBanner,
|
||||
VinLookupMethods,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.VinLookupMethods.initializeComponent();
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedVinLookupMethod: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedVinLookupMethod === null;
|
||||
Form,
|
||||
SiteFooter,
|
||||
SiteHeader,
|
||||
SiteSubHeader,
|
||||
VehicleBanner,
|
||||
VinLookupMethods
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisiteValid() {
|
||||
return true;
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.VinLookupMethods.initializeComponent();
|
||||
});
|
||||
},
|
||||
forwardButtonAction() {
|
||||
switch (this.selectedVinLookupMethod) {
|
||||
case vinLookupMethodSelections.MANUALVIN:
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_MANUAL_VIN,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
case vinLookupMethodSelections.LICENSEPLATE:
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_LICENSE_PLATE,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
case vinLookupMethodSelections.HOMEADDRESS:
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_HOME_ADDRESS,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
data() {
|
||||
return {
|
||||
selectedVinLookupMethod: null
|
||||
};
|
||||
},
|
||||
resetDependentState() {},
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedVinLookupMethod === null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisiteValid() {
|
||||
return true;
|
||||
},
|
||||
forwardButtonAction() {
|
||||
switch (this.selectedVinLookupMethod) {
|
||||
case vinLookupMethodSelections.MANUALVIN:
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_MANUAL_VIN,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
case vinLookupMethodSelections.LICENSEPLATE:
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_LICENSE_PLATE,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
case vinLookupMethodSelections.HOMEADDRESS:
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_HOME_ADDRESS,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
resetDependentState() {}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<template>
|
||||
<Form ref="theForm" @submit="onSubmit" @invalidSubmit="onInvalidSubmit">
|
||||
<Form
|
||||
ref="theForm"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
|
|
@ -12,12 +15,10 @@
|
|||
ref="vehicleBanner"
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false"
|
||||
/>
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
/>
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -27,9 +28,10 @@
|
|||
class="mt-3 mb-3"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertWidget"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
||||
:isDismissible="false" />
|
||||
<div
|
||||
v-for="(item, i) in PartsOrQuestions"
|
||||
:key="i">
|
||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||
<hr v-if="i > 0" />
|
||||
<glassPartQuestion
|
||||
|
|
@ -40,8 +42,7 @@
|
|||
:glassLocation="item.glassLocation"
|
||||
:glassName="item.glassName"
|
||||
:colorAnswers="item.colorAnswers"
|
||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData"
|
||||
/>
|
||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
|
|
@ -49,8 +50,7 @@
|
|||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
@backClicked="navigateBackByVehicleQuestions"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -59,187 +59,182 @@
|
|||
|
||||
<script>
|
||||
// Components
|
||||
import glassPartQuestion from "@/layouts/vehicle-parts/glass-part-question/glass-part-question.vue";
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner.vue";
|
||||
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import alert from "@/ux-components/alert/alert.vue";
|
||||
import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass-part-question.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
|
||||
// Supporting Files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import settleAllPromises from "@/helpers/layout-helper";
|
||||
import issPageValues from "@/router/router-constants/issPage-values";
|
||||
import { Form } from "vee-validate";
|
||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import { useMainStore } from "@/store";
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import issPageValues from '@/router/router-constants/issPage-values';
|
||||
import { Form } from 'vee-validate';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
export default {
|
||||
name: "vehicle-parts",
|
||||
components: {
|
||||
name: 'vehicle-parts',
|
||||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
glassPartQuestion,
|
||||
siteHeader,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
siteFooter,
|
||||
alert,
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
Form,
|
||||
glassPartQuestion,
|
||||
siteHeader,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
siteFooter,
|
||||
alert
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
|
||||
// Glass Part Question dynamic component
|
||||
Object.keys(vm.$refs)
|
||||
.filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined)
|
||||
.forEach((c) =>
|
||||
vm.$refs[c][0].initializeComponent({
|
||||
ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget,
|
||||
FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedGlassParts: {},
|
||||
alertWidgetData: Object,
|
||||
alreadyPopulatedPartsData: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return (
|
||||
this.selectedGlassPartNumbers?.length !==
|
||||
this.PartsFromApi.partsOrQuestions?.length
|
||||
);
|
||||
// Glass Part Question dynamic component
|
||||
Object.keys(vm.$refs)
|
||||
.filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined)
|
||||
.forEach((c) =>
|
||||
vm.$refs[c][0].initializeComponent({
|
||||
ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget,
|
||||
FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget
|
||||
}));
|
||||
});
|
||||
},
|
||||
selectedGlassPartNumbers() {
|
||||
// Compile all selected parts from the page.
|
||||
const numberArray = [];
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const glassPart of Object.values(this.selectedGlassParts)) {
|
||||
if (glassPart?.partNumber) {
|
||||
numberArray.push(glassPart.partNumber);
|
||||
data() {
|
||||
return {
|
||||
selectedGlassParts: {},
|
||||
alertWidgetData: Object,
|
||||
alreadyPopulatedPartsData: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return (
|
||||
this.selectedGlassPartNumbers?.length
|
||||
!== this.PartsFromApi.partsOrQuestions?.length
|
||||
);
|
||||
},
|
||||
selectedGlassPartNumbers() {
|
||||
// Compile all selected parts from the page.
|
||||
const numberArray = [];
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const glassPart of Object.values(this.selectedGlassParts)) {
|
||||
if (glassPart?.partNumber) {
|
||||
numberArray.push(glassPart.partNumber);
|
||||
}
|
||||
}
|
||||
return numberArray;
|
||||
},
|
||||
PartsOrQuestions() {
|
||||
const partsData = this.PartsFromApi;
|
||||
|
||||
// Map API result data, to vehicle-parts data structure
|
||||
const mappedData = partsData.partsOrQuestions?.map((g) => ({
|
||||
glassName: g.glassName,
|
||||
glassLocation: g.glassLocation,
|
||||
colorAnswers: g.parts?.reduce((arr, p) => {
|
||||
arr.push({
|
||||
ColorAnswerText: p.color,
|
||||
FeatureAnswers: [
|
||||
{
|
||||
FeatureAnswerText:
|
||||
p.description === '' ? p.color : p.description,
|
||||
PartNumber: p.partNumber
|
||||
}
|
||||
]
|
||||
});
|
||||
return arr;
|
||||
}, [])
|
||||
}));
|
||||
|
||||
return mappedData;
|
||||
},
|
||||
|
||||
PartsFromApi() {
|
||||
return this.mainStore.pageData(issPageValues.VEHICLE_PARTS);
|
||||
},
|
||||
|
||||
RefPrefix() {
|
||||
return 'partQuestion';
|
||||
}
|
||||
}
|
||||
return numberArray;
|
||||
},
|
||||
PartsOrQuestions() {
|
||||
const partsData = this.PartsFromApi;
|
||||
|
||||
// Map API result data, to vehicle-parts data structure
|
||||
const mappedData = partsData.partsOrQuestions?.map((g) => ({
|
||||
glassName: g.glassName,
|
||||
glassLocation: g.glassLocation,
|
||||
colorAnswers: g.parts?.reduce((arr, p) => {
|
||||
arr.push({
|
||||
ColorAnswerText: p.color,
|
||||
FeatureAnswers: [
|
||||
{
|
||||
FeatureAnswerText:
|
||||
p.description === "" ? p.color : p.description,
|
||||
PartNumber: p.partNumber,
|
||||
},
|
||||
],
|
||||
});
|
||||
return arr;
|
||||
}, []),
|
||||
}));
|
||||
|
||||
return mappedData;
|
||||
mounted() {
|
||||
this.LoadInitialPartsData();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// Check if isRepair is populated and if the pageData we need is here (Parts data)
|
||||
return (
|
||||
useMainStore().damage.isRepair != null
|
||||
&& useMainStore().pageData(issPageValues.VEHICLE_PARTS)
|
||||
&& Object.keys(useMainStore().pageData(issPageValues.VEHICLE_PARTS))
|
||||
.length !== 0
|
||||
);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
const matchedParts = [];
|
||||
|
||||
PartsFromApi() {
|
||||
return this.mainStore.pageData(issPageValues.VEHICLE_PARTS);
|
||||
},
|
||||
|
||||
RefPrefix() {
|
||||
return "partQuestion";
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.LoadInitialPartsData();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// Check if isRepair is populated and if the pageData we need is here (Parts data)
|
||||
return (
|
||||
useMainStore().damage.isRepair != null &&
|
||||
useMainStore().pageData(issPageValues.VEHICLE_PARTS) &&
|
||||
Object.keys(useMainStore().pageData(issPageValues.VEHICLE_PARTS))
|
||||
.length !== 0
|
||||
);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
const matchedParts = [];
|
||||
|
||||
// Match them to the parts from the API.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const [key, value] of Object.entries(
|
||||
this.PartsFromApi.partsOrQuestions
|
||||
)) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const [partKey, partValue] of Object.entries(value.parts)) {
|
||||
const currentPart =
|
||||
// Match them to the parts from the API.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const [key, value] of Object.entries(this.PartsFromApi.partsOrQuestions)) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const [partKey, partValue] of Object.entries(value.parts)) {
|
||||
const currentPart =
|
||||
this.PartsFromApi.partsOrQuestions[key].parts[partKey];
|
||||
|
||||
const isMatched = this.selectedGlassPartNumbers.some(
|
||||
(p) => p === currentPart.partNumber
|
||||
);
|
||||
const isMatched = this.selectedGlassPartNumbers.some((p) => p === currentPart.partNumber);
|
||||
|
||||
if (isMatched) {
|
||||
matchedParts.push({
|
||||
glassLocation: value.glassLocation,
|
||||
glassName: value.glassName,
|
||||
parts: [currentPart],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// If no parts could be matched, throw an error (isForwardActionDisabled is based off of matchedParts)
|
||||
if (this.isForwardActionDisabled) {
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
throw new Error("Could not match any parts to the selected parts");
|
||||
}
|
||||
|
||||
this.navigateForward(matchedParts, null);
|
||||
},
|
||||
|
||||
LoadInitialPartsData() {
|
||||
const partsData = this.PartsFromApi;
|
||||
this.alreadyPopulatedPartsData =
|
||||
this.mainStore.lineItems.glassParts === null
|
||||
? []
|
||||
: this.mainStore.lineItems.glassParts;
|
||||
|
||||
partsData.partsOrQuestions.map((g) => {
|
||||
// If the part is already populated, use the value from the store and populate the v-model.
|
||||
Object.keys(this.alreadyPopulatedPartsData).forEach((key) => {
|
||||
const { partNumber } = this.alreadyPopulatedPartsData[key];
|
||||
g.parts.forEach((p) => {
|
||||
if (p.partNumber === partNumber) {
|
||||
this.selectedGlassParts[`${g.glassLocation}-${g.glassName}`] = p;
|
||||
if (isMatched) {
|
||||
matchedParts.push({
|
||||
glassLocation: value.glassLocation,
|
||||
glassName: value.glassName,
|
||||
parts: [currentPart]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
// If no parts could be matched, throw an error (isForwardActionDisabled is based off of matchedParts)
|
||||
if (this.isForwardActionDisabled) {
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
throw new Error('Could not match any parts to the selected parts');
|
||||
}
|
||||
|
||||
this.navigateForward(matchedParts, null);
|
||||
},
|
||||
|
||||
LoadInitialPartsData() {
|
||||
const partsData = this.PartsFromApi;
|
||||
this.alreadyPopulatedPartsData =
|
||||
this.mainStore.lineItems.glassParts === null
|
||||
? []
|
||||
: this.mainStore.lineItems.glassParts;
|
||||
|
||||
partsData.partsOrQuestions.map((g) => {
|
||||
// If the part is already populated, use the value from the store and populate the v-model.
|
||||
Object.keys(this.alreadyPopulatedPartsData).forEach((key) => {
|
||||
const { partNumber } = this.alreadyPopulatedPartsData[key];
|
||||
g.parts.forEach((p) => {
|
||||
if (p.partNumber === partNumber) {
|
||||
this.selectedGlassParts[`${g.glassLocation}-${g.glassName}`] = p;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader class="mb-2 header" cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteHeader
|
||||
class="mb-2 header"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -17,8 +18,7 @@
|
|||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="siteSubHeader"
|
||||
justification="center"
|
||||
darkGraySubText
|
||||
/>
|
||||
darkGraySubText />
|
||||
|
||||
<vehicleQuestion
|
||||
ref="vehicleYearQuestion"
|
||||
|
|
@ -27,8 +27,7 @@
|
|||
cmsWidgetName="VehicleYearQuestion"
|
||||
:updateValues="updateYearValues"
|
||||
validationRules="year-required"
|
||||
inputId="yearQuestionField"
|
||||
/>
|
||||
inputId="yearQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleMakeQuestion"
|
||||
v-model="selectedMake"
|
||||
|
|
@ -36,8 +35,7 @@
|
|||
cmsWidgetName="VehicleMakeQuestion"
|
||||
:updateValues="updateMakeValues"
|
||||
validationRules="make-required"
|
||||
inputId="makeQuestionField"
|
||||
/>
|
||||
inputId="makeQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleModelQuestion"
|
||||
v-model="selectedModel"
|
||||
|
|
@ -45,8 +43,7 @@
|
|||
cmsWidgetName="VehicleModelQuestion"
|
||||
:updateValues="updateModelValues"
|
||||
validationRules="model-required"
|
||||
inputId="modelQuestionField"
|
||||
/>
|
||||
inputId="modelQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleStyleQuestion"
|
||||
v-model="selectedStyle"
|
||||
|
|
@ -54,15 +51,13 @@
|
|||
cmsWidgetName="VehicleStyleQuestion"
|
||||
:updateValues="updateStyleValues"
|
||||
validationRules="style-required"
|
||||
inputId="styleQuestionField"
|
||||
/>
|
||||
inputId="styleQuestionField" />
|
||||
|
||||
<vehicleBanner
|
||||
ref="banner"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
class="mt-5 mb-3"
|
||||
/>
|
||||
class="mt-5 mb-3" />
|
||||
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
|
|
@ -70,8 +65,7 @@
|
|||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack"
|
||||
/>
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -80,154 +74,154 @@
|
|||
|
||||
<script>
|
||||
// Components
|
||||
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 vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner.vue";
|
||||
import vehicleQuestion from "@/layouts/vehicle-selection/vehicle-question/vehicle-question.vue";
|
||||
import { useMainStore } from "@/store";
|
||||
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 vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import vehicleQuestion from '@/layouts/vehicle-selection/vehicle-question/vehicle-question.vue';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
// Supporting files
|
||||
import baseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-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 baseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-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';
|
||||
|
||||
// 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));
|
||||
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-selection",
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
vehicleBanner,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleQuestion,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
name: 'vehicle-selection',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
vehicleBanner,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleQuestion
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
validationRules: String,
|
||||
},
|
||||
data() {
|
||||
const { year, make, model, style } = useMainStore().order.vehicle;
|
||||
return {
|
||||
selectedYear: year,
|
||||
selectedMake: make,
|
||||
selectedModel: model,
|
||||
selectedStyle: style,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
displayGeneric() {
|
||||
return !this.selectedStyle;
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
selectedYear(value) {
|
||||
this.mainStore.updateVehicleYear(value);
|
||||
this.$refs.vehicleMakeQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs.vehicleMakeQuestion.getNewValues();
|
||||
}
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
validationRules: String
|
||||
},
|
||||
selectedMake(value) {
|
||||
this.mainStore.updateVehicleMake(value);
|
||||
this.$refs.vehicleModelQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs.vehicleModelQuestion.getNewValues();
|
||||
}
|
||||
data() {
|
||||
const { year, make, model, style } = useMainStore().order.vehicle;
|
||||
return {
|
||||
selectedYear: year,
|
||||
selectedMake: make,
|
||||
selectedModel: model,
|
||||
selectedStyle: style
|
||||
};
|
||||
},
|
||||
selectedModel(value) {
|
||||
this.mainStore.updateVehicleModel(value);
|
||||
this.$refs.vehicleStyleQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs.vehicleStyleQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
selectedStyle(value) {
|
||||
this.mainStore.updateVehicleStyle(value);
|
||||
this.mainStore.setVehicle();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.vehicleYearQuestion.getNewValues();
|
||||
if (this.selectedYear) {
|
||||
this.$refs.vehicleMakeQuestion.getNewValues();
|
||||
}
|
||||
if (this.selectedMake) {
|
||||
this.$refs.vehicleModelQuestion.getNewValues();
|
||||
}
|
||||
if (this.selectedModel) {
|
||||
this.$refs.vehicleStyleQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return true;
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
return this.navigateForward();
|
||||
},
|
||||
|
||||
navigateForward() {
|
||||
this.mainStore.setVehicle().then(() => {
|
||||
if (this.mainStore.isBailout) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
this.$route
|
||||
);
|
||||
return;
|
||||
computed: {
|
||||
displayGeneric() {
|
||||
return !this.selectedStyle;
|
||||
}
|
||||
},
|
||||
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
});
|
||||
watch: {
|
||||
selectedYear(value) {
|
||||
this.mainStore.updateVehicleYear(value);
|
||||
this.$refs.vehicleMakeQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs.vehicleMakeQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
selectedMake(value) {
|
||||
this.mainStore.updateVehicleMake(value);
|
||||
this.$refs.vehicleModelQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs.vehicleModelQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
selectedModel(value) {
|
||||
this.mainStore.updateVehicleModel(value);
|
||||
this.$refs.vehicleStyleQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs.vehicleStyleQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
selectedStyle(value) {
|
||||
this.mainStore.updateVehicleStyle(value);
|
||||
this.mainStore.setVehicle();
|
||||
}
|
||||
},
|
||||
async updateYearValues() {
|
||||
return useMainStore().getVehicleYears();
|
||||
mounted() {
|
||||
this.$refs.vehicleYearQuestion.getNewValues();
|
||||
if (this.selectedYear) {
|
||||
this.$refs.vehicleMakeQuestion.getNewValues();
|
||||
}
|
||||
if (this.selectedMake) {
|
||||
this.$refs.vehicleModelQuestion.getNewValues();
|
||||
}
|
||||
if (this.selectedModel) {
|
||||
this.$refs.vehicleStyleQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
async updateMakeValues() {
|
||||
return this.mainStore.getVehicleMakes();
|
||||
},
|
||||
async updateModelValues() {
|
||||
return this.mainStore.getVehicleModels();
|
||||
},
|
||||
async updateStyleValues() {
|
||||
return this.mainStore.getVehicleStyles();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return true;
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
return this.navigateForward();
|
||||
},
|
||||
|
||||
navigateForward() {
|
||||
this.mainStore.setVehicle().then(() => {
|
||||
if (this.mainStore.isBailout) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
this.$route
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
});
|
||||
},
|
||||
async updateYearValues() {
|
||||
return useMainStore().getVehicleYears();
|
||||
},
|
||||
async updateMakeValues() {
|
||||
return this.mainStore.getVehicleMakes();
|
||||
},
|
||||
async updateModelValues() {
|
||||
return this.mainStore.getVehicleModels();
|
||||
},
|
||||
async updateStyleValues() {
|
||||
return this.mainStore.getVehicleStyles();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
|
|
@ -17,19 +16,16 @@
|
|||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="!carIdIsValid"
|
||||
/>
|
||||
:displayGenericVehicleImage="!carIdIsValid" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<vinLookupAlerts
|
||||
class="mt-5"
|
||||
:activeAlertType="activeVehicleLookupAlertType"
|
||||
/>
|
||||
:activeAlertType="activeVehicleLookupAlertType" />
|
||||
<vinQuestion
|
||||
v-model="vin"
|
||||
:mask="vinMask"
|
||||
:isDisabled="vinPopulatedOnPageLoad"
|
||||
textPosition="left"
|
||||
/>
|
||||
textPosition="left" />
|
||||
<vinLocationInformation />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
|
|
@ -37,8 +33,7 @@
|
|||
:isForwardActionDisabled="!meta.valid"
|
||||
class="mt-5"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
/>
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -47,262 +42,256 @@
|
|||
</template>
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
import { computed } from "vue";
|
||||
import vehicleLookupAlertTypes from "@/constants/vehicle-lookup-alert-types";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||
import settleAllPromises from "@/helpers/layout-helper";
|
||||
import routerParams from "@/router/router-constants/router-params";
|
||||
import { useMainStore } from "@/store";
|
||||
import { computed } from 'vue';
|
||||
import vehicleLookupAlertTypes from '@/constants/vehicle-lookup-alert-types';
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import { isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import routerParams from '@/router/router-constants/router-params';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
// Import Component
|
||||
import baseFormMixin from "@/mixins/base-form-mixin";
|
||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||
import { Form } from "vee-validate";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import siteHeader from "@/iss-components/site-header/site-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 vinLocationInformation from "@/layouts/vin-lookup/vin-location-information/vin-location-information.vue";
|
||||
import vinLookupAlerts from "@/layouts/vin-lookup/vin-lookup-alerts/vin-lookup-alerts.vue";
|
||||
import vinQuestion from "@/layouts/vin-lookup/vin-question/vin-question.vue";
|
||||
import bailoutCode from "@/constants/bailoutCode";
|
||||
import bailoutMessage from "@/constants/bailoutMessage";
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import { Form } from 'vee-validate';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-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 vinLocationInformation from '@/layouts/vin-lookup/vin-location-information/vin-location-information.vue';
|
||||
import vinLookupAlerts from '@/layouts/vin-lookup/vin-lookup-alerts/vin-lookup-alerts.vue';
|
||||
import vinQuestion from '@/layouts/vin-lookup/vin-question/vin-question.vue';
|
||||
import bailoutCode from '@/constants/bailoutCode';
|
||||
import bailoutMessage from '@/constants/bailoutMessage';
|
||||
|
||||
export default {
|
||||
name: "vin-lookup",
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleBanner,
|
||||
vinLocationInformation,
|
||||
vinLookupAlerts,
|
||||
vinQuestion,
|
||||
},
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
provide() {
|
||||
return {
|
||||
vehicleFromLookup: computed(() => this.vehicleFromLookup),
|
||||
};
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
const vin = this.getVinFromStore();
|
||||
return {
|
||||
activeVehicleLookupAlertType:
|
||||
vin?.length > 0 && !this.hasValidCarId()
|
||||
? vehicleLookupAlertTypes.NOT_FOUND
|
||||
: null,
|
||||
needToLookupVehicle: true,
|
||||
vehicleFromLookup: null,
|
||||
vinWithNonMatchingCarId: vin?.length > 0 && !this.hasValidCarId(),
|
||||
vin,
|
||||
forwardButtonCarStyle: "",
|
||||
vinPopulatedOnPageLoad: vin?.length > 0 && this.hasValidCarId(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isCarIdDifferentFromTheStore() {
|
||||
return (
|
||||
this.vehicleFromLookup !== null &&
|
||||
this.hasValidCarId() &&
|
||||
this.vehicleFromLookup.carId !== this.mainStore.vehicle.carId
|
||||
);
|
||||
name: 'vin-lookup',
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleBanner,
|
||||
vinLocationInformation,
|
||||
vinLookupAlerts,
|
||||
vinQuestion
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
if (this.vehicleFromLookup === null) {
|
||||
return false;
|
||||
}
|
||||
const vinYmmFound = `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
provide() {
|
||||
return {
|
||||
vehicleFromLookup: computed(() => this.vehicleFromLookup)
|
||||
};
|
||||
},
|
||||
vinMask() {
|
||||
// TODO: Side effects in computed.
|
||||
if (this.vinPopulatedOnPageLoad) {
|
||||
// TODO: Modify to remove side effects in computed
|
||||
this.activeVehicleLookupAlertType =
|
||||
vehicleLookupAlertTypes.PERFECT_MATCH;
|
||||
this.needToLookupVehicle = false;
|
||||
const lastSixChars = this.vin.substring(11, this.vin.length);
|
||||
return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`;
|
||||
}
|
||||
return "*****************";
|
||||
},
|
||||
carIdIsValid() {
|
||||
return this.hasValidCarId();
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
vin() {
|
||||
this.resetActiveAlert();
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
this.needToLookupVehicle = true;
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent("SiteFooterWidget", "ForwardButtonText")
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisiteValid() {
|
||||
return true;
|
||||
},
|
||||
getVinFromStore() {
|
||||
return this.mainStore.vehicle.vin;
|
||||
},
|
||||
hasValidCarId() {
|
||||
return (
|
||||
this.mainStore.vehicle.carId && this.mainStore.vehicle.carId !== "0"
|
||||
);
|
||||
},
|
||||
// NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
|
||||
async forwardButtonAction() {
|
||||
this.resetActiveAlert();
|
||||
// Temp solution to reset the 'disabled' style on the Continue button
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
if (this.needToLookupVehicle) {
|
||||
const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
];
|
||||
|
||||
if (vehicleLookupResponse.error) {
|
||||
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
|
||||
this.mainStore.setBailout(bailoutMessage.vehicleNotFound(this.vin));
|
||||
this.resetVehicleFromLookup();
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
// Temp solution to turn on 'disabled' style on the Continue button
|
||||
// because the form itself actually passes its client-side validation.
|
||||
// SSR-189 Scenario #4.
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
return;
|
||||
}
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
this.mainStore.resetBailout();
|
||||
|
||||
// Add vin bcs the response from the service doesn't contain vin
|
||||
this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, {
|
||||
vin: this.vin,
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
}
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
if (this.needToLookupVehicle && this.isCarIdDifferentFromTheStore) {
|
||||
if (this.isTwoIdenticalYMMVehicleFound) {
|
||||
this.activeVehicleLookupAlertType =
|
||||
vehicleLookupAlertTypes.TWO_IDENTICAL_YMM_MATCHED;
|
||||
this.forwardButtonCarStyle = this.vehicleFromLookup.style;
|
||||
} else {
|
||||
this.activeVehicleLookupAlertType =
|
||||
vehicleLookupAlertTypes.NOT_MATCHED;
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
const vin = this.getVinFromStore();
|
||||
return {
|
||||
activeVehicleLookupAlertType:
|
||||
vin?.length > 0 && !this.hasValidCarId()
|
||||
? vehicleLookupAlertTypes.NOT_FOUND
|
||||
: null,
|
||||
needToLookupVehicle: true,
|
||||
vehicleFromLookup: null,
|
||||
vinWithNonMatchingCarId: vin?.length > 0 && !this.hasValidCarId(),
|
||||
vin,
|
||||
forwardButtonCarStyle: '',
|
||||
vinPopulatedOnPageLoad: vin?.length > 0 && this.hasValidCarId()
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isCarIdDifferentFromTheStore() {
|
||||
return (
|
||||
this.vehicleFromLookup !== null
|
||||
&& this.hasValidCarId()
|
||||
&& this.vehicleFromLookup.carId !== this.mainStore.vehicle.carId
|
||||
);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
if (this.vehicleFromLookup === null) {
|
||||
return false;
|
||||
}
|
||||
const vinYmmFound = `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
|
||||
},
|
||||
vinMask() {
|
||||
// TODO: Side effects in computed.
|
||||
if (this.vinPopulatedOnPageLoad) {
|
||||
// TODO: Modify to remove side effects in computed
|
||||
this.activeVehicleLookupAlertType =
|
||||
vehicleLookupAlertTypes.PERFECT_MATCH;
|
||||
this.needToLookupVehicle = false;
|
||||
const lastSixChars = this.vin.substring(11, this.vin.length);
|
||||
return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`;
|
||||
}
|
||||
return '*****************';
|
||||
},
|
||||
carIdIsValid() {
|
||||
return this.hasValidCarId();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
vin() {
|
||||
this.resetActiveAlert();
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
this.needToLookupVehicle = true;
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisiteValid() {
|
||||
return true;
|
||||
},
|
||||
getVinFromStore() {
|
||||
return this.mainStore.vehicle.vin;
|
||||
},
|
||||
hasValidCarId() {
|
||||
return (
|
||||
this.mainStore.vehicle.carId && this.mainStore.vehicle.carId !== '0'
|
||||
);
|
||||
},
|
||||
// NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
|
||||
async forwardButtonAction() {
|
||||
this.resetActiveAlert();
|
||||
// Temp solution to reset the 'disabled' style on the Continue button
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
|
||||
const vehicleYearMakeModelStyle =
|
||||
if (this.needToLookupVehicle) {
|
||||
const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);
|
||||
|
||||
if (vehicleLookupResponse.error) {
|
||||
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
|
||||
this.mainStore.setBailout(bailoutMessage.vehicleNotFound(this.vin));
|
||||
this.resetVehicleFromLookup();
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
// Temp solution to turn on 'disabled' style on the Continue button
|
||||
// because the form itself actually passes its client-side validation.
|
||||
// SSR-189 Scenario #4.
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
return;
|
||||
}
|
||||
|
||||
this.mainStore.resetBailout();
|
||||
|
||||
// Add vin bcs the response from the service doesn't contain vin
|
||||
this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, {
|
||||
vin: this.vin
|
||||
});
|
||||
}
|
||||
|
||||
if (this.needToLookupVehicle && this.isCarIdDifferentFromTheStore) {
|
||||
if (this.isTwoIdenticalYMMVehicleFound) {
|
||||
this.activeVehicleLookupAlertType =
|
||||
vehicleLookupAlertTypes.TWO_IDENTICAL_YMM_MATCHED;
|
||||
this.forwardButtonCarStyle = this.vehicleFromLookup.style;
|
||||
} else {
|
||||
this.activeVehicleLookupAlertType =
|
||||
vehicleLookupAlertTypes.NOT_MATCHED;
|
||||
}
|
||||
|
||||
const vehicleYearMakeModelStyle =
|
||||
// eslint-disable-next-line max-len
|
||||
`${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model} ${this.forwardButtonCarStyle}`;
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
`Continue with ${vehicleYearMakeModelStyle}`
|
||||
);
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
this.$refs.siteFooter.updateButtonText(`Continue with ${vehicleYearMakeModelStyle}`);
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
|
||||
this.needToLookupVehicle = false;
|
||||
this.needToLookupVehicle = false;
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
let isSelectedGlassAvailableForVehicle = true;
|
||||
if (this.isCarIdDifferentFromTheStore) {
|
||||
isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
|
||||
this.vehicleFromLookup.carId
|
||||
);
|
||||
}
|
||||
let isSelectedGlassAvailableForVehicle = true;
|
||||
if (this.isCarIdDifferentFromTheStore) {
|
||||
isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(this.vehicleFromLookup.carId);
|
||||
}
|
||||
|
||||
// navigate back to vehicle-damage
|
||||
if (
|
||||
this.isCarIdDifferentFromTheStore &&
|
||||
!isSelectedGlassAvailableForVehicle
|
||||
) {
|
||||
this.mainStore.updateVehicle(this.vehicleFromLookup);
|
||||
this.mainStore.resetDamageState();
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||
);
|
||||
// navigate back to vehicle-damage
|
||||
if (
|
||||
this.isCarIdDifferentFromTheStore
|
||||
&& !isSelectedGlassAvailableForVehicle
|
||||
) {
|
||||
this.mainStore.updateVehicle(this.vehicleFromLookup);
|
||||
this.mainStore.resetDamageState();
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||
);
|
||||
|
||||
// navigate() doesn't stop the processing flow
|
||||
return null;
|
||||
}
|
||||
// navigate() doesn't stop the processing flow
|
||||
return null;
|
||||
}
|
||||
|
||||
// save vehicle to store if it hasn't already been saved
|
||||
if (!this.vinPopulatedOnPageLoad) {
|
||||
this.mainStore.updateVehicle(this.vehicleFromLookup);
|
||||
}
|
||||
// save vehicle to store if it hasn't already been saved
|
||||
if (!this.vinPopulatedOnPageLoad) {
|
||||
this.mainStore.updateVehicle(this.vehicleFromLookup);
|
||||
}
|
||||
|
||||
if (this.vinWithNonMatchingCarId) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CORRECTED_VIN_FROM_POLICY_VEHICLE,
|
||||
this.$route
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (this.vinWithNonMatchingCarId) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CORRECTED_VIN_FROM_POLICY_VEHICLE,
|
||||
this.$route
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
||||
if (partsOrQuestionsResponse.error) {
|
||||
// To Do: Need requirement on what to do here
|
||||
window.console.error("Error on retrieving PartsOrQuestions");
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return null;
|
||||
}
|
||||
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
||||
if (partsOrQuestionsResponse.error) {
|
||||
// To Do: Need requirement on what to do here
|
||||
window.console.error('Error on retrieving PartsOrQuestions');
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||
await this.navigateForward(
|
||||
partsOrQuestionsResponse.data.partsOrQuestions,
|
||||
this
|
||||
);
|
||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||
await this.navigateForward(
|
||||
partsOrQuestionsResponse.data.partsOrQuestions,
|
||||
this
|
||||
);
|
||||
|
||||
return null;
|
||||
},
|
||||
async lookupVehicleByVin(vin) {
|
||||
try {
|
||||
return await this.mainStore.lookupVehicleByVin(vin);
|
||||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
resetActiveAlert() {
|
||||
this.activeVehicleLookupAlertType = null;
|
||||
},
|
||||
resetVehicleFromLookup() {
|
||||
this.vehicleFromLookup = null;
|
||||
},
|
||||
resetDependentState() {},
|
||||
},
|
||||
return null;
|
||||
},
|
||||
async lookupVehicleByVin(vin) {
|
||||
try {
|
||||
return await this.mainStore.lookupVehicleByVin(vin);
|
||||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
resetActiveAlert() {
|
||||
this.activeVehicleLookupAlertType = null;
|
||||
},
|
||||
resetVehicleFromLookup() {
|
||||
this.vehicleFromLookup = null;
|
||||
},
|
||||
resetDependentState() {}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
>
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
|
|
@ -13,7 +12,9 @@
|
|||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" class="mt-4" />
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-4" />
|
||||
<textboxQuestion
|
||||
ref="policyNumber"
|
||||
v-model="welcomePageModel.policyNumber"
|
||||
|
|
@ -22,8 +23,7 @@
|
|||
isRequired
|
||||
disableAutoFill
|
||||
:isDisabled="isPolicyHolderDisabled"
|
||||
:validationRules="rules.policyNumber"
|
||||
/>
|
||||
:validationRules="rules.policyNumber" />
|
||||
<textboxQuestion
|
||||
ref="policyZip"
|
||||
v-model="welcomePageModel.policyZipCode"
|
||||
|
|
@ -32,8 +32,7 @@
|
|||
isRequired
|
||||
mask="#####"
|
||||
:isDisabled="isPolicyZipDisabled"
|
||||
:validationRules="rules.policyZip"
|
||||
/>
|
||||
:validationRules="rules.policyZip" />
|
||||
<textboxQuestion
|
||||
ref="dateOfLoss"
|
||||
v-model="welcomePageModel.dateOfLoss"
|
||||
|
|
@ -45,13 +44,11 @@
|
|||
disableAutoFill
|
||||
:max="new Date().toJSON().slice(0, 10)"
|
||||
:min="'1972-12-01'"
|
||||
:validationRules="rules.lossDate"
|
||||
/>
|
||||
:validationRules="rules.lossDate" />
|
||||
<textBlock
|
||||
cmsWidgetName="DamageDateEstimateWidget"
|
||||
typeStyle="small"
|
||||
class="mt-2"
|
||||
/>
|
||||
class="mt-2" />
|
||||
<dropdownQuestion
|
||||
id="welcomeDropdown"
|
||||
ref="damageCause"
|
||||
|
|
@ -61,8 +58,7 @@
|
|||
:options="DamageCauseOptions"
|
||||
disableAutoFill
|
||||
:validationRules="rules.damageOption"
|
||||
placeHolderText="Select an option"
|
||||
/>
|
||||
placeHolderText="Select an option" />
|
||||
<textboxQuestion
|
||||
ref="phoneNumber"
|
||||
v-model="welcomePageModel.phoneNumber"
|
||||
|
|
@ -71,8 +67,7 @@
|
|||
:validationRules="rules.phoneNumber"
|
||||
isRequired
|
||||
:mask="phoneMask"
|
||||
disableAutoFill
|
||||
/>
|
||||
disableAutoFill />
|
||||
<textboxQuestion
|
||||
ref="email"
|
||||
v-model="welcomePageModel.email"
|
||||
|
|
@ -80,8 +75,7 @@
|
|||
cmsWidgetName="EmailAddressQuestion"
|
||||
:validationRules="rules.email"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
/>
|
||||
disableAutoFill />
|
||||
<textboxQuestion
|
||||
v-if="displayDamageCityQuestion"
|
||||
ref="damageCity"
|
||||
|
|
@ -91,8 +85,7 @@
|
|||
cmsWidgetName="DamageCityQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.lossCity"
|
||||
/>
|
||||
:validationRules="rules.lossCity" />
|
||||
<dropdownQuestion
|
||||
v-if="displayDamageStateQuestion"
|
||||
id="welcomeDropdown"
|
||||
|
|
@ -105,8 +98,7 @@
|
|||
:validationRules="rules.lossState"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
placeHolderText="Select an option"
|
||||
/>
|
||||
placeHolderText="Select an option" />
|
||||
<buttonQuestion
|
||||
v-if="displayGlassOnlyQuestion"
|
||||
ref="glassOnlyDamage"
|
||||
|
|
@ -121,289 +113,287 @@
|
|||
:validationRules="rules.damageOption"
|
||||
isRequired
|
||||
isSmallQuestionLabelText
|
||||
disableAutoFill
|
||||
/>
|
||||
<div id="welcomeFooter" class="row">
|
||||
disableAutoFill />
|
||||
<div
|
||||
id="welcomeFooter"
|
||||
class="row">
|
||||
<alert
|
||||
v-if="displayInvalidZipAlert"
|
||||
ref="alertInvalidZip"
|
||||
class="my-4"
|
||||
cmsWidgetName="AlertInvalidZipWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
:isDismissible="false" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-3"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Footer image component must have parent (usually container-fluid)
|
||||
set to display: flex and height 100dvh or height 100% -->
|
||||
<footerImage
|
||||
cmsWidgetName="SiteFooterWidget" />
|
||||
<footerImage cmsWidgetName="SiteFooterWidget" />
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import siteHeader from "@/iss-components/site-header/site-header.vue";
|
||||
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
|
||||
import siteFooter from "@/iss-components/site-footer/site-footer.vue";
|
||||
import alert from "@/ux-components/alert/alert.vue";
|
||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question.vue";
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question.vue";
|
||||
import dropdownQuestion from "@/digital-components/dropdown-question/dropdown-question.vue";
|
||||
import textBlock from "@/digital-components/text-block/text-block.vue";
|
||||
import footerImage from "@/iss-components/site-footer/footer-image/footer-image.vue";
|
||||
import { Form, defineRule } from 'vee-validate';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||
import footerImage from '@/iss-components/site-footer/footer-image/footer-image.vue';
|
||||
|
||||
// Supporting files
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
fetchGlobalCmsContent,
|
||||
updateCmsSiteHeader,
|
||||
} from "@/helpers/cms-content-helper";
|
||||
import settleAllPromises from "@/helpers/layout-helper";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import errorMessages from "@/constants/error-messages";
|
||||
import BaseFormMixin from "@/mixins/base-form-mixin.js";
|
||||
import { useMainStore } from "@/store";
|
||||
import states from "@/constants/states";
|
||||
import globalRules from "@/constants/global-rules";
|
||||
import routerParams from "@/router/router-constants/router-params";
|
||||
import MaskaFormattedMasks from "@/constants/maska-masks";
|
||||
fetchCmsContentForPage,
|
||||
fetchGlobalCmsContent,
|
||||
updateCmsSiteHeader
|
||||
} from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import states from '@/constants/states';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
import routerParams from '@/router/router-constants/router-params';
|
||||
import MaskaFormattedMasks from '@/constants/maska-masks';
|
||||
|
||||
// define validation rules
|
||||
defineRule(
|
||||
"damage-option-required",
|
||||
required(errorMessages.DAMAGE_OPTION_REQUIRED)
|
||||
'damage-option-required',
|
||||
required(errorMessages.DAMAGE_OPTION_REQUIRED)
|
||||
);
|
||||
|
||||
export default {
|
||||
name: "welcome-page",
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
footerImage,
|
||||
alert,
|
||||
buttonQuestion,
|
||||
textboxQuestion,
|
||||
dropdownQuestion,
|
||||
siteFooter,
|
||||
textBlock,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
name: 'welcome-page',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
footerImage,
|
||||
alert,
|
||||
buttonQuestion,
|
||||
textboxQuestion,
|
||||
dropdownQuestion,
|
||||
siteFooter,
|
||||
textBlock,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const cmsGlobalSiteHeaderContentPromise =
|
||||
fetchGlobalCmsContent("iss-siteheader");
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const cmsGlobalSiteHeaderContentPromise =
|
||||
fetchGlobalCmsContent('iss-siteheader');
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "globalSiteHeaderCmsContent",
|
||||
promise: cmsGlobalSiteHeaderContentPromise,
|
||||
},
|
||||
];
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'globalSiteHeaderCmsContent',
|
||||
promise: cmsGlobalSiteHeaderContentPromise
|
||||
}
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
updateCmsSiteHeader(resultMap.globalSiteHeaderCmsContent);
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
// Set order account number from the issConfig.
|
||||
mainStore.order.accountNumber = mainStore.issConfig.parentAccountNumber;
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
welcomePageModel: this.getWelcomePageModelFromStore(),
|
||||
displayInvalidZipAlert: false,
|
||||
duplicates: [],
|
||||
rules: {
|
||||
damageOption: "damage-option-required",
|
||||
email: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||
lossCity: `${globalRules.DATE_OF_LOSS_CITY_REQUIRED}|${globalRules.DATE_OF_LOSS_CITY_FORMAT}`,
|
||||
// eslint-disable-next-line max-len
|
||||
lossDate: `${globalRules.DATE_OF_LOSS_REQUIRED}|${globalRules.DATE_OF_LOSS_NOT_TEN_YEARS_PAST}|${globalRules.DATE_OF_LOSS_NOT_FUTURE}`,
|
||||
lossState: `${globalRules.DATE_OF_LOSS_STATE_REQUIRED}`,
|
||||
policyNumber: `${globalRules.POLICY_NUMBER_REQUIRED}|${globalRules.POLICY_NUMBER_FORMAT}`,
|
||||
policyZip: `${globalRules.POLICY_ZIP_REQUIRED}|${globalRules.POLICY_ZIP_FORMAT}`,
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
DamageCauseOptions() {
|
||||
const damageCauseAnswers = this.getCmsContent(
|
||||
"DamageCauseQuestion",
|
||||
"Answers"
|
||||
);
|
||||
const damageCauseAnswersObj = {};
|
||||
if (damageCauseAnswers) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const answer of Object.values(damageCauseAnswers)) {
|
||||
if (answer?.Name) {
|
||||
damageCauseAnswersObj[answer.Name] = answer.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return damageCauseAnswersObj;
|
||||
},
|
||||
DamageGlassOnlyOptions() {
|
||||
return this.getCmsContent("GlassOnlyQuestion", "Answers");
|
||||
},
|
||||
DamageGlassOnlyQuestion() {
|
||||
return this.getCmsContent("GlassOnlyQuestion", "QuestionText");
|
||||
},
|
||||
displayDamageCityQuestion() {
|
||||
return !!this.getCmsContent("DamageCityQuestion", "QuestionText");
|
||||
},
|
||||
displayDamageStateQuestion() {
|
||||
return !!this.getCmsContent("DamageStateQuestion", "QuestionText");
|
||||
},
|
||||
displayGlassOnlyQuestion() {
|
||||
return !!this.getCmsContent("GlassOnlyQuestion", "QuestionText");
|
||||
},
|
||||
getStates() {
|
||||
return states;
|
||||
},
|
||||
isPolicyHolderDisabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.policyNumber;
|
||||
},
|
||||
isPolicyZipDisabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.policyZipCode;
|
||||
},
|
||||
isDateOfLossDisabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.dateOfLoss;
|
||||
},
|
||||
isCoverageEnabled() {
|
||||
return this.mainStore.issConfig.isCoverageEnabled;
|
||||
},
|
||||
maxCoverageLookupAttemptsReached() {
|
||||
return this.mainStore.applicationUser.coverageLookupAttempts >= 11;
|
||||
},
|
||||
phoneMask() {
|
||||
return MaskaFormattedMasks.PHONE_NUMBER;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async forwardButtonAction() {
|
||||
await this.mainStore
|
||||
.validateZip({ zip: this.welcomePageModel.policyZipCode })
|
||||
.then(async (zipInfo) => {
|
||||
if (zipInfo?.data?.isValid === true) {
|
||||
this.mainStore.updatePolicyData(this.welcomePageModel);
|
||||
await this.mainStore
|
||||
.getDuplicateReferrals()
|
||||
.then(
|
||||
() => {},
|
||||
() => {}
|
||||
)
|
||||
.finally(async () => {
|
||||
if (
|
||||
this.isCoverageEnabled &&
|
||||
!this.maxCoverageLookupAttemptsReached
|
||||
) {
|
||||
await this.mainStore.getCoveragePolicyInfo()?.then(
|
||||
() => {},
|
||||
() => {}
|
||||
);
|
||||
} else {
|
||||
this.mainStore.order.policy.policyLookupSuccessful = false;
|
||||
}
|
||||
this.navigateForward();
|
||||
});
|
||||
} else {
|
||||
this.displayInvalidZipAlert = true;
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
}
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
updateCmsSiteHeader(resultMap.globalSiteHeaderCmsContent);
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
navigateForward() {
|
||||
if (this.mainStore.applicationUser.duplicateOrders?.length > 0 ?? false) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
} else if (this.mainStore.policy.policyLookupSuccessful) {
|
||||
if (this.mainStore.order.policy.vehicles?.length > 0 ?? false) {
|
||||
// navigate to policy-vehicles page
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
} else {
|
||||
// navigate to vehicle-selection page (manual entry)
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
// Set order account number from the issConfig.
|
||||
mainStore.order.accountNumber = mainStore.issConfig.parentAccountNumber;
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
welcomePageModel: this.getWelcomePageModelFromStore(),
|
||||
displayInvalidZipAlert: false,
|
||||
duplicates: [],
|
||||
rules: {
|
||||
damageOption: 'damage-option-required',
|
||||
email: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||
lossCity: `${globalRules.DATE_OF_LOSS_CITY_REQUIRED}|${globalRules.DATE_OF_LOSS_CITY_FORMAT}`,
|
||||
// eslint-disable-next-line max-len
|
||||
lossDate: `${globalRules.DATE_OF_LOSS_REQUIRED}|${globalRules.DATE_OF_LOSS_NOT_TEN_YEARS_PAST}|${globalRules.DATE_OF_LOSS_NOT_FUTURE}`,
|
||||
lossState: `${globalRules.DATE_OF_LOSS_STATE_REQUIRED}`,
|
||||
policyNumber: `${globalRules.POLICY_NUMBER_REQUIRED}|${globalRules.POLICY_NUMBER_FORMAT}`,
|
||||
policyZip: `${globalRules.POLICY_ZIP_REQUIRED}|${globalRules.POLICY_ZIP_FORMAT}`,
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
DamageCauseOptions() {
|
||||
const damageCauseAnswers = this.getCmsContent(
|
||||
'DamageCauseQuestion',
|
||||
'Answers'
|
||||
);
|
||||
const damageCauseAnswersObj = {};
|
||||
if (damageCauseAnswers) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const answer of Object.values(damageCauseAnswers)) {
|
||||
if (answer?.Name) {
|
||||
damageCauseAnswersObj[answer.Name] = answer.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return damageCauseAnswersObj;
|
||||
},
|
||||
DamageGlassOnlyOptions() {
|
||||
return this.getCmsContent('GlassOnlyQuestion', 'Answers');
|
||||
},
|
||||
DamageGlassOnlyQuestion() {
|
||||
return this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
|
||||
},
|
||||
displayDamageCityQuestion() {
|
||||
return !!this.getCmsContent('DamageCityQuestion', 'QuestionText');
|
||||
},
|
||||
displayDamageStateQuestion() {
|
||||
return !!this.getCmsContent('DamageStateQuestion', 'QuestionText');
|
||||
},
|
||||
displayGlassOnlyQuestion() {
|
||||
return !!this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
|
||||
},
|
||||
getStates() {
|
||||
return states;
|
||||
},
|
||||
isPolicyHolderDisabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.policyNumber;
|
||||
},
|
||||
isPolicyZipDisabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.policyZipCode;
|
||||
},
|
||||
isDateOfLossDisabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.dateOfLoss;
|
||||
},
|
||||
isCoverageEnabled() {
|
||||
return this.mainStore.issConfig.isCoverageEnabled;
|
||||
},
|
||||
maxCoverageLookupAttemptsReached() {
|
||||
return this.mainStore.applicationUser.coverageLookupAttempts >= 11;
|
||||
},
|
||||
phoneMask() {
|
||||
return MaskaFormattedMasks.PHONE_NUMBER;
|
||||
}
|
||||
} else {
|
||||
// if policy lookup is unsuccessful, navigate to policy-holder-details page
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
}
|
||||
},
|
||||
getWelcomePageModelFromStore() {
|
||||
return {
|
||||
policyNumber: this.mainStore.order.policy.policyNumber,
|
||||
policyZipCode: this.mainStore.order.policy.policyZipCode,
|
||||
dateOfLoss: this.mainStore.order.policy.dateOfLoss,
|
||||
damageCause: this.mainStore.order.policy.damageCause,
|
||||
damageState: this.mainStore.order.policy.damageState,
|
||||
damageCity: this.mainStore.order.policy.damageCity,
|
||||
isDamageGlassOnly: this.mainStore.order.policy.isDamageGlassOnly,
|
||||
phoneNumber: this.mainStore.order.customer.phoneNumber,
|
||||
email: this.mainStore.order.customer.emailAddress,
|
||||
isPolicyNumberDisabled:
|
||||
this.mainStore.order.policy.isPolicyNumberDisabled,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async forwardButtonAction() {
|
||||
await this.mainStore
|
||||
.validateZip({ zip: this.welcomePageModel.policyZipCode })
|
||||
.then(async (zipInfo) => {
|
||||
if (zipInfo?.data?.isValid === true) {
|
||||
this.mainStore.updatePolicyData(this.welcomePageModel);
|
||||
await this.mainStore
|
||||
.getDuplicateReferrals()
|
||||
.then(
|
||||
() => {},
|
||||
() => {}
|
||||
)
|
||||
.finally(async () => {
|
||||
if (
|
||||
this.isCoverageEnabled
|
||||
&& !this.maxCoverageLookupAttemptsReached
|
||||
) {
|
||||
await this.mainStore.getCoveragePolicyInfo()?.then(
|
||||
() => {},
|
||||
() => {}
|
||||
);
|
||||
} else {
|
||||
this.mainStore.order.policy.policyLookupSuccessful = false;
|
||||
}
|
||||
this.navigateForward();
|
||||
});
|
||||
} else {
|
||||
this.displayInvalidZipAlert = true;
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
}
|
||||
});
|
||||
},
|
||||
navigateForward() {
|
||||
if (this.mainStore.applicationUser.duplicateOrders?.length > 0 ?? false) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
} else if (this.mainStore.policy.policyLookupSuccessful) {
|
||||
if (this.mainStore.order.policy.vehicles?.length > 0 ?? false) {
|
||||
// navigate to policy-vehicles page
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
} else {
|
||||
// navigate to vehicle-selection page (manual entry)
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// if policy lookup is unsuccessful, navigate to policy-holder-details page
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
);
|
||||
}
|
||||
},
|
||||
getWelcomePageModelFromStore() {
|
||||
return {
|
||||
policyNumber: this.mainStore.order.policy.policyNumber,
|
||||
policyZipCode: this.mainStore.order.policy.policyZipCode,
|
||||
dateOfLoss: this.mainStore.order.policy.dateOfLoss,
|
||||
damageCause: this.mainStore.order.policy.damageCause,
|
||||
damageState: this.mainStore.order.policy.damageState,
|
||||
damageCity: this.mainStore.order.policy.damageCity,
|
||||
isDamageGlassOnly: this.mainStore.order.policy.isDamageGlassOnly,
|
||||
phoneNumber: this.mainStore.order.customer.phoneNumber,
|
||||
email: this.mainStore.order.customer.emailAddress,
|
||||
isPolicyNumberDisabled:
|
||||
this.mainStore.order.policy.isPolicyNumberDisabled
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
form {
|
||||
height: 100dvh;
|
||||
.container-fluid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
height: 100dvh;
|
||||
.container-fluid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
// Temporary solution that prevents the Continue button from being hidden in Firefox
|
||||
|
|
|
|||
Loading…
Reference in a new issue