Merge pull request #616 from Safelite/SSR-1160-add-desktop-functionality
SSR-1160 add desktop functionality
This commit is contained in:
commit
39a1ec1416
43 changed files with 3886 additions and 3052 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ const widgetFields = Object.freeze({
|
|||
NAME: 'Name',
|
||||
BACK_BUTTON_TEXT: 'BackButtonText',
|
||||
FORWARD_BUTTON_TEXT: 'ForwardButtonText',
|
||||
FOOTER_IMAGE: 'FooterImage',
|
||||
ALT_TEXT: 'AltText'
|
||||
ALT_TEXT: 'AltText',
|
||||
FOOTER_IMAGE_URL: 'FooterImageURL'
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
<!-- Documented in confluence https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Component -->
|
||||
<template>
|
||||
<div
|
||||
:class="isOverflowScrollable
|
||||
? 'button-question button-question-overflow'
|
||||
: 'button-question'">
|
||||
:class="
|
||||
isOverflowScrollable
|
||||
? 'button-question button-question-overflow'
|
||||
: 'button-question'
|
||||
">
|
||||
<div
|
||||
v-if="questionText && answers && answers.length > 0"
|
||||
class="question-text d-flex"
|
||||
:class="{'small-question-text': isSmallQuestionText,'small-question-label-text':isSmallQuestionLabelText}">
|
||||
:class="{
|
||||
'small-question-text': isSmallQuestionText,
|
||||
'small-question-label-text': isSmallQuestionLabelText,
|
||||
}">
|
||||
<span class="fw-bold w-100">{{ questionText }}</span>
|
||||
</div>
|
||||
<div class="w-100 d-flex justify-content-center">
|
||||
|
|
@ -22,9 +27,11 @@
|
|||
:data-focus-target="formatString(groupName)"
|
||||
tabindex="-1">
|
||||
{{ questionText }}
|
||||
{{ isMultiSelect && answers && answers.length > 1
|
||||
? "Select one or more options below."
|
||||
: "Select an option below." }}
|
||||
{{
|
||||
isMultiSelect && answers && answers.length > 1
|
||||
? 'Select one or more options below.'
|
||||
: 'Select an option below.'
|
||||
}}
|
||||
</legend>
|
||||
<div :class="getComponentLoopWrapperClasses">
|
||||
<div
|
||||
|
|
@ -54,12 +61,12 @@
|
|||
:setLastValuePushedToGa="setLastValuePushedToGa"
|
||||
:suppressError="suppressError" />
|
||||
<!-- For nested questions -->
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<transition name="fade" mode="out-in">
|
||||
<div
|
||||
v-if="typeof selectedValues == 'string' &&
|
||||
selectedValues == answer.value">
|
||||
v-if="
|
||||
typeof selectedValues == 'string' &&
|
||||
selectedValues == answer.value
|
||||
">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
@ -67,11 +74,8 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div
|
||||
v-if="!suppressError"
|
||||
class="row form-test-error mt-1">
|
||||
<error-message
|
||||
:name="formatString(groupName)"></error-message>
|
||||
<div v-if="!suppressError" class="row form-test-error mt-1">
|
||||
<error-message :name="formatString(groupName)"></error-message>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -92,16 +96,16 @@ export default {
|
|||
listCard,
|
||||
ErrorMessage,
|
||||
radio,
|
||||
providerPrefRadio
|
||||
providerPrefRadio,
|
||||
},
|
||||
props: {
|
||||
buttonTypeString: {
|
||||
type: String,
|
||||
default: 'listButton'
|
||||
default: 'listButton',
|
||||
},
|
||||
buttonTypeObject: {
|
||||
type: Object,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
isMultiSelect: Boolean,
|
||||
groupName: String,
|
||||
|
|
@ -109,16 +113,16 @@ export default {
|
|||
answers: Array,
|
||||
textPosition: {
|
||||
type: String,
|
||||
default: 'text-center'
|
||||
default: 'text-center',
|
||||
},
|
||||
selectingInitiatesLoad: Boolean,
|
||||
loaderColor: {
|
||||
type: String,
|
||||
default: 'blue'
|
||||
default: 'blue',
|
||||
},
|
||||
loaderPosition: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
default: 'right',
|
||||
},
|
||||
isRequired: Boolean,
|
||||
isOverflowScrollable: Boolean,
|
||||
|
|
@ -133,7 +137,7 @@ export default {
|
|||
additionalButtonData: Object,
|
||||
additionalButtonStyling: String,
|
||||
isSmallQuestionText: Boolean,
|
||||
isSmallQuestionLabelText: Boolean
|
||||
isSmallQuestionLabelText: Boolean,
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props) {
|
||||
|
|
@ -142,11 +146,18 @@ export default {
|
|||
|
||||
const fieldOptions = {
|
||||
value: modelValue,
|
||||
initialValue: null
|
||||
initialValue: null,
|
||||
};
|
||||
|
||||
const { errorMessage, handleBlur, handleChange, meta, validate, errors, resetField } =
|
||||
useField(props.groupName, props.validationRules, fieldOptions);
|
||||
const {
|
||||
errorMessage,
|
||||
handleBlur,
|
||||
handleChange,
|
||||
meta,
|
||||
validate,
|
||||
errors,
|
||||
resetField,
|
||||
} = useField(props.groupName, props.validationRules, fieldOptions);
|
||||
|
||||
return {
|
||||
errorMessage,
|
||||
|
|
@ -155,12 +166,12 @@ export default {
|
|||
validate,
|
||||
meta,
|
||||
errors,
|
||||
resetField
|
||||
resetField,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lastValuePushedToGa: null
|
||||
lastValuePushedToGa: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -169,8 +180,8 @@ export default {
|
|||
const baseClasses = this.isOverflowScrollable
|
||||
? 'container-fluid overflow-scroll position-absolute px-5 pt-1 py-0'
|
||||
: this.buttonTypeString === 'listCard'
|
||||
? 'w-100'
|
||||
: '';
|
||||
? 'w-100'
|
||||
: '';
|
||||
|
||||
const SmallQuestionTextClass = this.isSmallQuestionText
|
||||
? `${baseClasses}small-question-text`
|
||||
|
|
@ -191,7 +202,8 @@ export default {
|
|||
classes = 'd-flex flex-row p-0';
|
||||
break;
|
||||
case 'listCard':
|
||||
classes = 'row g-2 justify-content-center';
|
||||
classes =
|
||||
'row g-2 g-md-5 justify-content-center mb-1 flex-nowrap';
|
||||
if (this.isWide) {
|
||||
classes += ' flex-column';
|
||||
}
|
||||
|
|
@ -226,25 +238,50 @@ export default {
|
|||
break;
|
||||
default:
|
||||
}
|
||||
// Determine number of buttons and add class accordingly.
|
||||
// This is to accommodate unique spacing per design specs.
|
||||
if (
|
||||
this.buttonTypeString === 'listCard' &&
|
||||
this.buttonsInfo.length > 2
|
||||
) {
|
||||
classes += ' two-list-card-width';
|
||||
}
|
||||
|
||||
if (
|
||||
this.buttonTypeString === 'listCard' &&
|
||||
this.buttonsInfo.length === 1
|
||||
) {
|
||||
classes += ' one-list-card-width';
|
||||
}
|
||||
|
||||
return classes;
|
||||
},
|
||||
buttonsInfo() {
|
||||
return (Array.isArray(this.answers) ? this.answers : [])?.map((answer) => ({
|
||||
buttonLabel: answer.buttonLabel ?? answer.Text ?? answer,
|
||||
altText: answer.altText ?? (answer.Name ? answer.Name : answer),
|
||||
buttonLabelSubCopy: answer.buttonLabelSubCopy ?? answer.SubText,
|
||||
buttonBodyCopy: answer.buttonBodyCopy ?? answer.buttonBodyCopy,
|
||||
buttonAuxiliaryCopy: answer.buttonAuxiliaryCopy ?? answer.buttonAuxiliaryCopy,
|
||||
buttonFooterCopy: answer.buttonFooterCopy ?? answer.buttonFooterCopy,
|
||||
buttonImage: answer.buttonImage ?? answer.AnswerImageUrl,
|
||||
buttonImageId: answer.buttonImageId ?? answer.ImageId,
|
||||
groupName: this.formatString(this.groupName),
|
||||
value:
|
||||
answer.value
|
||||
?? (this.useTextForValue && answer.Text ? answer.Text : answer.Name)
|
||||
?? (typeof answer !== 'object' ? answer : null)
|
||||
}));
|
||||
return (Array.isArray(this.answers) ? this.answers : [])?.map(
|
||||
(answer) => ({
|
||||
buttonLabel: answer.buttonLabel ?? answer.Text ?? answer,
|
||||
altText:
|
||||
answer.altText ?? (answer.Name ? answer.Name : answer),
|
||||
buttonLabelSubCopy:
|
||||
answer.buttonLabelSubCopy ?? answer.SubText,
|
||||
buttonBodyCopy:
|
||||
answer.buttonBodyCopy ?? answer.buttonBodyCopy,
|
||||
buttonAuxiliaryCopy:
|
||||
answer.buttonAuxiliaryCopy ??
|
||||
answer.buttonAuxiliaryCopy,
|
||||
buttonFooterCopy:
|
||||
answer.buttonFooterCopy ?? answer.buttonFooterCopy,
|
||||
buttonImage: answer.buttonImage ?? answer.AnswerImageUrl,
|
||||
buttonImageId: answer.buttonImageId ?? answer.ImageId,
|
||||
groupName: this.formatString(this.groupName),
|
||||
value:
|
||||
answer.value ??
|
||||
(this.useTextForValue && answer.Text
|
||||
? answer.Text
|
||||
: answer.Name) ??
|
||||
(typeof answer !== 'object' ? answer : null),
|
||||
})
|
||||
);
|
||||
},
|
||||
selectedValues: {
|
||||
get() {
|
||||
|
|
@ -252,24 +289,25 @@ export default {
|
|||
},
|
||||
set(selectedAnswers) {
|
||||
this.$emit('update:modelValue', selectedAnswers);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue(newValue) {
|
||||
this.resetField({
|
||||
value: newValue
|
||||
value: newValue,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
if (this.buttonTypeObject) {
|
||||
this.$options.components[this.buttonTypeString] = this.buttonTypeObject;
|
||||
this.$options.components[this.buttonTypeString] =
|
||||
this.buttonTypeObject;
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.resetField({
|
||||
value: ''
|
||||
value: '',
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -278,8 +316,8 @@ export default {
|
|||
},
|
||||
setLastValuePushedToGa(lastValuePushedToGa) {
|
||||
this.lastValuePushedToGa = lastValuePushedToGa;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -325,17 +363,17 @@ export default {
|
|||
.small-question-label-text {
|
||||
&.question-text {
|
||||
span {
|
||||
text-align: left;
|
||||
margin: 0 0 0.25rem 0;
|
||||
}
|
||||
}
|
||||
&.question-text {
|
||||
margin: 0;
|
||||
}
|
||||
&fieldset {
|
||||
.ui-radio {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
text-align: left;
|
||||
margin: 0 0 0.25rem 0;
|
||||
}
|
||||
}
|
||||
&.question-text {
|
||||
margin: 0;
|
||||
}
|
||||
&fieldset {
|
||||
.ui-radio {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
tabindex="-1"
|
||||
aria-labelledby="ModalComponentLabel"
|
||||
aria-hidden="true"
|
||||
v-on="{ 'hidden.bs.modal': onModalClosed, 'shown.bs.modal': onModalOpened }">
|
||||
v-on="{
|
||||
'hidden.bs.modal': onModalClosed,
|
||||
'shown.bs.modal': onModalOpened,
|
||||
}">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header mb-2 mt-2">
|
||||
|
|
@ -33,7 +36,10 @@
|
|||
class="w-100"
|
||||
loaderColor="white"
|
||||
:buttonText="footerButtonText"
|
||||
:class="(isButtonDisabled || isFooterButtonDisabled) && 'form-test-invalid'"
|
||||
:class="
|
||||
(isButtonDisabled || isFooterButtonDisabled) &&
|
||||
'form-test-invalid'
|
||||
"
|
||||
@clickEvent="validateAndEmit" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -50,23 +56,25 @@ export default {
|
|||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
name: 'modal',
|
||||
components: {
|
||||
modalButtonMain
|
||||
modalButtonMain,
|
||||
},
|
||||
props: {
|
||||
modalId: String,
|
||||
headerText: String,
|
||||
footerButtonText: String,
|
||||
onModalOpenedCallback: {
|
||||
type: Function
|
||||
type: Function,
|
||||
},
|
||||
onModalClosedCallback: {
|
||||
type: Function
|
||||
type: Function,
|
||||
},
|
||||
isButtonDisabled: Boolean
|
||||
isButtonDisabled: Boolean,
|
||||
},
|
||||
emits: ['footer-button-event', 'isModalOpened'],
|
||||
setup(props) {
|
||||
const modalId = props.modalId ? props.modalId : `modal-${crypto.randomUUID()}`;
|
||||
const modalId = props.modalId
|
||||
? props.modalId
|
||||
: `modal-${crypto.randomUUID()}`;
|
||||
|
||||
const { meta, validate, resetForm } = useForm();
|
||||
|
||||
|
|
@ -75,7 +83,7 @@ export default {
|
|||
modalId,
|
||||
meta,
|
||||
validate,
|
||||
resetForm
|
||||
resetForm,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -84,7 +92,7 @@ export default {
|
|||
return !this.meta.valid;
|
||||
}
|
||||
return !this.meta.dirty || !this.meta.valid;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async validateAndEmit() {
|
||||
|
|
@ -106,38 +114,34 @@ export default {
|
|||
this.onModalClosedCallback?.();
|
||||
},
|
||||
openModal() {
|
||||
const modal = Modal.getOrCreateInstance(document.getElementById(this.modalId));
|
||||
const modal = Modal.getOrCreateInstance(
|
||||
document.getElementById(this.modalId)
|
||||
);
|
||||
modal?.show();
|
||||
this.$emit('isModalOpened', true);
|
||||
},
|
||||
closeModal() {
|
||||
const modal = Modal.getInstance(document.getElementById(this.modalId));
|
||||
const modal = Modal.getInstance(
|
||||
document.getElementById(this.modalId)
|
||||
);
|
||||
modal?.hide();
|
||||
this.$emit('isModalOpened', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<style lang="scss">
|
||||
.modal {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
|
||||
:deep(h5) {
|
||||
color: $black;
|
||||
}
|
||||
|
||||
:deep(p) {
|
||||
strong {
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
|
||||
h5,
|
||||
strong,
|
||||
.subheader-text {
|
||||
color: $black;
|
||||
}
|
||||
.modal-header {
|
||||
padding: 1rem 0 0.5rem 0;
|
||||
border-bottom: none;
|
||||
.btn-close {
|
||||
position: absolute;
|
||||
|
|
@ -145,10 +149,13 @@ export default {
|
|||
top: 1rem;
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.6874 1.82179L9.50889 8L15.6874 14.1782C16.1042 14.595 16.1042 15.2707 15.6874 15.6875C15.4843 15.8907 15.2146 16 14.9328 16C14.6514 16 14.3818 15.8906 14.1787 15.6875L8.00017 9.50934L1.82171 15.6875C1.6182 15.8907 1.34876 16 1.06708 16C0.785733 16 0.516056 15.8906 0.312965 15.6875C-0.10429 15.2706 -0.10429 14.5952 0.312797 14.1784L6.03276 8.45867L6.49146 8L0.312945 1.82177C-0.10429 1.40483 -0.10429 0.729418 0.312797 0.31262C0.728936 -0.104145 1.40489 -0.104051 1.82185 0.31262L7.54152 6.03202L8.00017 6.49065L14.1786 0.312472C14.5955 -0.104107 15.2707 -0.104201 15.6874 0.312452C16.1042 0.729289 16.1042 1.40496 15.6874 1.82179Z' fill='%231574A1'/%3E%3C/svg%3E%0A");
|
||||
opacity: 1;
|
||||
margin: 0.3rem -0.5rem -0.5rem auto;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-weight: 500;
|
||||
font-size: 1.25rem;
|
||||
line-height: 32px;
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
|
|
@ -157,17 +164,31 @@ export default {
|
|||
width: 100%;
|
||||
bottom: 0;
|
||||
z-index: 5;
|
||||
background-color: $gray-100;
|
||||
}
|
||||
&.modal-component {
|
||||
.modal-dialog {
|
||||
max-width: 576px;
|
||||
max-width: 767px;
|
||||
margin: 0 auto;
|
||||
@include media-breakpoint-up(md) {
|
||||
width: 376px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: translate(100%, 0);
|
||||
}
|
||||
.modal-content {
|
||||
margin: 0 auto;
|
||||
margin: 1.5rem auto 0 auto;
|
||||
box-shadow: 0px 16px 48px -16px rgba(0, 0, 0, 0.25);
|
||||
border-radius: 1.5rem 1.5rem 0 0;
|
||||
@include media-breakpoint-up(md) {
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.modal-body {
|
||||
.col {
|
||||
max-width: 100%;
|
||||
}
|
||||
.modal-sub-body {
|
||||
color: $gray-600;
|
||||
}
|
||||
|
|
@ -179,22 +200,36 @@ export default {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
@include media-breakpoint-up(md) {
|
||||
overflow: auto;
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.modal-dialog-centered {
|
||||
align-items: flex-end;
|
||||
min-height: 100%;
|
||||
@include media-breakpoint-up(md) {
|
||||
align-items: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal-footer {
|
||||
border-top: none;
|
||||
background-color: $gray-100;
|
||||
box-shadow: 0px -1px 0px rgba(179, 180, 181, 0.3);
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.show .modal-dialog {
|
||||
transform: translateY(0);
|
||||
}
|
||||
@include media-breakpoint-up(md) {
|
||||
&.fade {
|
||||
transition: opacity 0.25s linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
body {
|
||||
.modal-backdrop {
|
||||
|
|
|
|||
|
|
@ -1,51 +1,45 @@
|
|||
<template>
|
||||
<div :class="`page-container-grouped-styles questions-page`">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<loadingModal
|
||||
ref="loadingModal"
|
||||
:textSlides="loadingText" />
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
ref="alertFewMoreQuestions"
|
||||
cmsWidgetName="alertWidget"
|
||||
alertClass="alert-warning"
|
||||
:manualHeadline="alertFewMoreQuestionsHeader"
|
||||
:manualCopy="alertFewMoreQuestionsCopy"
|
||||
:isDismissible="false"
|
||||
class="mt-5" />
|
||||
<div
|
||||
v-for="(questionsDatum, i) in questionsData"
|
||||
:key="questionsDatum.key">
|
||||
<questionChain
|
||||
v-if="showThisQuestionChain(questionsDatum, i)"
|
||||
ref="questionChain"
|
||||
v-model="selectedAnswers[questionsDatum.answerKey]"
|
||||
:questionData="questionsDatum.questions"
|
||||
:index="i"
|
||||
:answerKey="questionsDatum.answerKey"
|
||||
:validationRules="validationRules" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!isMetaValid"
|
||||
@backClicked="handleBackButtonAction"
|
||||
@ForwardClicked="handleForwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
ref="alertFewMoreQuestions"
|
||||
cmsWidgetName="alertWidget"
|
||||
alertClass="alert-warning"
|
||||
:manualHeadline="alertFewMoreQuestionsHeader"
|
||||
:manualCopy="alertFewMoreQuestionsCopy"
|
||||
:isDismissible="false"
|
||||
class="mt-5" />
|
||||
<div
|
||||
v-for="(questionsDatum, i) in questionsData"
|
||||
:key="questionsDatum.key">
|
||||
<questionChain
|
||||
v-if="showThisQuestionChain(questionsDatum, i)"
|
||||
ref="questionChain"
|
||||
v-model="selectedAnswers[questionsDatum.answerKey]"
|
||||
:questionData="questionsDatum.questions"
|
||||
:index="i"
|
||||
:answerKey="questionsDatum.answerKey"
|
||||
:validationRules="validationRules" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!isMetaValid"
|
||||
@backClicked="handleBackButtonAction"
|
||||
@ForwardClicked="handleForwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -70,7 +64,7 @@ export default {
|
|||
questionChain,
|
||||
siteSubHeader,
|
||||
siteFooter,
|
||||
loadingModal
|
||||
loadingModal,
|
||||
},
|
||||
props: {
|
||||
isMetaValid: Boolean,
|
||||
|
|
@ -80,7 +74,7 @@ export default {
|
|||
validationRules: String,
|
||||
modelValue: Object,
|
||||
loadingText: Array,
|
||||
index: Number
|
||||
index: Number,
|
||||
},
|
||||
emits: ['update:modelValue', 'forwardButtonAction', 'back-click'],
|
||||
computed: {
|
||||
|
|
@ -90,16 +84,22 @@ export default {
|
|||
},
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showThisQuestionChain(glass, i) {
|
||||
// return false if no questions or if suppressed
|
||||
if (!glass.questions || glass.questions?.length < 1 || glass.isSuppressedPart) {
|
||||
if (
|
||||
!glass.questions ||
|
||||
glass.questions?.length < 1 ||
|
||||
glass.isSuppressedPart
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return this.index === i || glass.answerData?.answerResult?.length > 0;
|
||||
return (
|
||||
this.index === i || glass.answerData?.answerResult?.length > 0
|
||||
);
|
||||
},
|
||||
handleForwardButtonAction() {
|
||||
this.$emit('forwardButtonAction');
|
||||
|
|
@ -109,8 +109,8 @@ export default {
|
|||
},
|
||||
showLoadingModal() {
|
||||
this.$refs.loadingModal.showModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
38
src/iss-components/site-footer/footer-image/footer-image.vue
Normal file
38
src/iss-components/site-footer/footer-image/footer-image.vue
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<div class="footerImage">
|
||||
<img :src="footerImageURL" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
|
||||
export default {
|
||||
name: 'footer-image',
|
||||
data() {
|
||||
return {
|
||||
widget: {
|
||||
footer: 'SiteFooterWidget',
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
footerImageURL() {
|
||||
return this.getCmsContent(
|
||||
this.widget.footer,
|
||||
widgetFields.FOOTER_WIDGET.FOOTER_IMAGE_URL
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.footerImage {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: auto;
|
||||
img {
|
||||
max-width: 23.4375rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,25 +1,24 @@
|
|||
<template>
|
||||
<div>
|
||||
<footer
|
||||
id="infoBox"
|
||||
class="footer container-fluid g-5 my-5 px-0">
|
||||
<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'
|
||||
: 'flex-row-reverse align-items-center',
|
||||
]">
|
||||
<div
|
||||
id="stacked"
|
||||
class="col button-col d-flex px-0">
|
||||
<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'"
|
||||
:class="
|
||||
(disableForwardAction || isForwardActionDisabled) &&
|
||||
'form-test-invalid'
|
||||
"
|
||||
:aria-disabled="isForwardActionDisabled"
|
||||
:isDisabled="isForwardActionDisabled"
|
||||
data-bs-target="#footerModal"
|
||||
|
|
@ -41,14 +40,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div
|
||||
v-if="footerImageURL"
|
||||
id="imgCity"
|
||||
class="footerImage">
|
||||
<img
|
||||
id="siteFooterImage"
|
||||
:src="footerImageURL" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -61,21 +52,21 @@ export default {
|
|||
name: 'site-footer',
|
||||
components: {
|
||||
textLink,
|
||||
buttonMain
|
||||
buttonMain,
|
||||
},
|
||||
props: {
|
||||
isForwardActionDisabled: Boolean,
|
||||
isBackButtonHidden: { type: Boolean, default: false },
|
||||
isForwardButtonHidden: { type: Boolean, default: false },
|
||||
cmsWidgetName: String,
|
||||
isStackedVertically: { type: Boolean, default: false }
|
||||
isStackedVertically: { type: Boolean, default: false },
|
||||
},
|
||||
emits: ['backClicked', 'forwardClicked'],
|
||||
data() {
|
||||
return {
|
||||
paddingHeight: 0,
|
||||
customButtontext: '',
|
||||
disableForwardAction: false
|
||||
disableForwardAction: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -88,15 +79,21 @@ export default {
|
|||
: this.getCmsContent(this.cmsWidgetName, 'ForwardButtonText');
|
||||
},
|
||||
footerImageURL() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'FooterImageURL');
|
||||
const output = this.getCmsContent(
|
||||
this.cmsWidgetName,
|
||||
'FooterImageURL'
|
||||
);
|
||||
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);
|
||||
});
|
||||
|
|
@ -131,8 +128,8 @@ export default {
|
|||
},
|
||||
enableForwardAction() {
|
||||
this.disableForwardAction = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -180,21 +177,18 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
.footerImage
|
||||
{
|
||||
.footerImage {
|
||||
text-align: center;
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 340px) {
|
||||
.footerImage
|
||||
{
|
||||
.footerImage {
|
||||
bottom: 78px;
|
||||
}
|
||||
}
|
||||
|
||||
#siteFooterImage
|
||||
{
|
||||
#siteFooterImage {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ describe('menu-modal.vue', () => {
|
|||
expect(modalFooter.text()).toContain('Safelite Group');
|
||||
});
|
||||
|
||||
it('Should return Terms of service text link text', async () => {
|
||||
it('Should return Terms of use text link text', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(menuModal);
|
||||
|
||||
// Expect
|
||||
expect(wrapper.html()).toContain('Terms of service');
|
||||
expect(wrapper.html()).toContain('Terms of use');
|
||||
});
|
||||
|
||||
it('Should return "Your privacy choices" text link text', async () => {
|
||||
|
|
@ -40,22 +40,6 @@ describe('menu-modal.vue', () => {
|
|||
expect(wrapper.html()).toContain('Your privacy choices');
|
||||
});
|
||||
|
||||
test('Icon for link to "Privacy Policies" page is displayed with the correct alternate text', () => {
|
||||
// NOTE: We need a way to target a specific <textLink> component so we can be sure that
|
||||
// an icon is coming from a specific <textLink> component.
|
||||
// That requires an additional prop in the <textLink> component. Will hold off on adding the prop
|
||||
// until there is more clarity on how we handle shared components.
|
||||
// For now the test is below is the best we can do.
|
||||
|
||||
// Arrange
|
||||
const wrapper = mount(menuModal);
|
||||
|
||||
// Expect
|
||||
const icon = wrapper.find('[data-id="ccpa-icon"]');
|
||||
expect(icon.isVisible()).toBe(true);
|
||||
expect(icon.attributes('alt')).toBe('Your privacy choices');
|
||||
});
|
||||
|
||||
it('Should return Warranty text link text', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(menuModal);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,21 @@
|
|||
type="button"
|
||||
:class="[isActive ? 'active' : '']"
|
||||
aria-label="Hamburger Menu (modal window)"
|
||||
@click="toggle()">
|
||||
@click="toggleModal">
|
||||
<div class="bar1"></div>
|
||||
<div class="bar2"></div>
|
||||
<div class="bar3"></div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="menu-modal-container">
|
||||
<button
|
||||
aria-hidden="true"
|
||||
tabindex="-1"
|
||||
class="menu-button"
|
||||
type="button"
|
||||
:class="[isActive ? 'active' : '']"
|
||||
aria-label="Hamburger Menu (modal window)"
|
||||
@click="toggleModal">
|
||||
<div class="bar1"></div>
|
||||
<div class="bar2"></div>
|
||||
<div class="bar3"></div>
|
||||
|
|
@ -18,107 +32,99 @@
|
|||
data-bs-backdrop="false"
|
||||
tabindex="-1"
|
||||
aria-labelledby="footerModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="menu-modal-container">
|
||||
<button
|
||||
class="menu-button"
|
||||
type="button"
|
||||
:class="[isActive ? 'active' : '']"
|
||||
aria-label="Hamburger Menu (modal window)"
|
||||
@click="toggle()">
|
||||
<div class="bar1"></div>
|
||||
<div class="bar2"></div>
|
||||
<div class="bar3"></div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-dialog modal-fullscreen">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header visually-hidden">
|
||||
<h5
|
||||
id="footerModalLabel"
|
||||
class="modal-title">
|
||||
Footer Navigation
|
||||
</h5>
|
||||
aria-hidden="true"
|
||||
v-on="{ 'show.bs.modal': show, 'hide.bs.modal': hide }">
|
||||
<div class="modal-dialog modal-fullscreen">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header visually-hidden">
|
||||
<h5 id="footerModalLabel" class="modal-title">
|
||||
Footer Navigation
|
||||
</h5>
|
||||
</div>
|
||||
<div class="modal-body d-flex flex-column">
|
||||
<textLink
|
||||
linkType="newWindowLink"
|
||||
text="Terms of use"
|
||||
href="//www.safelite.com/terms-of-use"
|
||||
target="_blank" />
|
||||
<textLink
|
||||
linkType="newWindowLink"
|
||||
text="Your privacy choices"
|
||||
href="//www.safelite.com/privacy-center"
|
||||
target="_blank">
|
||||
<template #after-text>
|
||||
<img
|
||||
class="ccpa-icon"
|
||||
src="~@/assets/img/icons/ccpa-icon.svg"
|
||||
alt="Your privacy choices" />
|
||||
</template>
|
||||
</textLink>
|
||||
<textLink
|
||||
linkType="newWindowLink"
|
||||
text="Warranty"
|
||||
href="//www.safelite.com/national-lifetime-warranty"
|
||||
target="_blank" />
|
||||
<textLink
|
||||
linkType="newWindowLink"
|
||||
text="Notice at collection"
|
||||
href="https://www.safelite.com/ccpa-privacy-policy"
|
||||
target="_blank" />
|
||||
</div>
|
||||
<div class="modal-footer d-flex justify-content-start">
|
||||
© {{ new Date().getFullYear() }} Safelite Group
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body d-flex flex-column">
|
||||
<textLink
|
||||
linkType="navigation"
|
||||
text="Terms of service"
|
||||
href="//www.safelite.com/terms-of-use"
|
||||
target="_blank" />
|
||||
<textLink
|
||||
linkType="navigation"
|
||||
text="Your privacy choices"
|
||||
href="//www.safelite.com/privacy-center"
|
||||
target="_blank">
|
||||
<template #after-text>
|
||||
<img
|
||||
class="ccpa-icon"
|
||||
data-id="ccpa-icon"
|
||||
src="~@/assets/img/icons/ccpa-icon.svg"
|
||||
alt="Your privacy choices" />
|
||||
</template>
|
||||
</textLink>
|
||||
<textLink
|
||||
linkType="navigation"
|
||||
text="Warranty"
|
||||
href="//www.safelite.com/national-lifetime-warranty"
|
||||
target="_blank" />
|
||||
<textLink
|
||||
linkType="navigation"
|
||||
text="Notice at collection"
|
||||
href="https://www.safelite.com/ccpa-privacy-policy"
|
||||
target="_blank" />
|
||||
</div>
|
||||
<div class="modal-footer d-flex justify-content-start">
|
||||
© {{ new Date().getFullYear() }} Safelite Group
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
import textLink from '@/ux-components/text-link/text-link';
|
||||
import { Modal } from 'bootstrap';
|
||||
import baseMixin from '@/mixins/base-mixin.js';
|
||||
|
||||
export default {
|
||||
name: 'menu-modal',
|
||||
components: {
|
||||
textLink
|
||||
textLink,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isActive: false,
|
||||
currentFooterAndHeaderHeight: 0
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
toggleModal() {
|
||||
if (this.isActive) {
|
||||
// hide modal
|
||||
this.isActive = false;
|
||||
const modal = Modal.getInstance(document.getElementById('footerModal'));
|
||||
modal?.hide();
|
||||
this.closeModal();
|
||||
} else {
|
||||
// show modal
|
||||
this.currentFooterAndHeaderHeight = this.getFooterInfoBoxHeight() + 56;
|
||||
this.isActive = true;
|
||||
const modal = Modal.getOrCreateInstance(document.getElementById('footerModal'));
|
||||
modal?.show();
|
||||
document.querySelector('.fade-on-route-transition').scrollTo({
|
||||
top: 0, behavior: 'instant'
|
||||
});
|
||||
this.openModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
openModal() {
|
||||
Modal.getOrCreateInstance(
|
||||
document.getElementById('footerModal')
|
||||
).show();
|
||||
},
|
||||
closeModal() {
|
||||
Modal.getInstance(document.getElementById('footerModal')).hide();
|
||||
},
|
||||
show() {
|
||||
this.isActive = true;
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
|
||||
},
|
||||
hide() {
|
||||
const self = this;
|
||||
self.isActive = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu-modal-container {
|
||||
position: absolute;
|
||||
padding: 1.47rem 1rem 1.47rem 1.47rem;
|
||||
padding: 1.47rem 0.5rem 1.47rem 1.47rem;
|
||||
right: 0;
|
||||
button {
|
||||
border: none;
|
||||
|
|
@ -126,14 +132,15 @@ export default {
|
|||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 8px 0 rgba(0,0,0,0.2);
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2);
|
||||
background-color: $white;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;//Required to prevent 'squish' on iPhone
|
||||
padding: 0; //Required to prevent 'squish' on iPhone
|
||||
z-index: 1050;
|
||||
.bar1,
|
||||
.bar2,
|
||||
.bar3 {
|
||||
|
|
@ -146,7 +153,9 @@ export default {
|
|||
&.active .bar1 {
|
||||
transform: rotate(-45deg) translate(-3px, 3px);
|
||||
}
|
||||
&.active .bar2 {opacity: 0;}
|
||||
&.active .bar2 {
|
||||
opacity: 0;
|
||||
}
|
||||
&.active .bar3 {
|
||||
transform: rotate(45deg) translate(-3px, -3px);
|
||||
}
|
||||
|
|
@ -155,14 +164,12 @@ export default {
|
|||
}
|
||||
.modal {
|
||||
&.menu-modal {
|
||||
max-width: 576px;
|
||||
left: auto;
|
||||
height: calc(100% - 56px);
|
||||
top: 56px;
|
||||
border-top: 1px solid $gray-300;
|
||||
overflow-x: visible;
|
||||
overflow-y: visible;
|
||||
z-index: 3;
|
||||
.modal-body {
|
||||
padding: 2rem;
|
||||
.ccpa-icon {
|
||||
|
|
@ -173,10 +180,6 @@ export default {
|
|||
}
|
||||
.modal-fullscreen {
|
||||
width: 100vw;
|
||||
max-width: 576px;
|
||||
}
|
||||
.navigation-link {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.modal-footer {
|
||||
border-top: none;
|
||||
|
|
@ -184,9 +187,9 @@ export default {
|
|||
}
|
||||
.menu-modal-container {
|
||||
position: absolute;
|
||||
padding: 1.47rem 1rem 1.47rem 1.47rem;
|
||||
right: .5rem;
|
||||
top: -4.5rem;
|
||||
padding: 1.47rem 0 1.47rem 1.47rem;
|
||||
right: 0;
|
||||
top: -5rem;
|
||||
button {
|
||||
border: none;
|
||||
&.menu-button {
|
||||
|
|
@ -196,8 +199,6 @@ export default {
|
|||
box-shadow: none;
|
||||
background-color: $white;
|
||||
position: relative;
|
||||
right: -.5rem;
|
||||
top: .5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -4,69 +4,67 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
ref="vehicleBanner"
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mb-5" />
|
||||
<alert
|
||||
v-if="displayVinNotFoundAlert"
|
||||
ref="alertVinNotFound"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
class="mb-4 mt-4"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||
ref="alertVinLookupsByHomeAddressNotAllowed"
|
||||
class="mt-4"
|
||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<customerQuestions
|
||||
ref="customerQuestions"
|
||||
v-model="customerQuestions" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isDisabled="!meta.valid"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
ref="vehicleBanner"
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mb-5" />
|
||||
<alert
|
||||
v-if="displayVinNotFoundAlert"
|
||||
ref="alertVinNotFound"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
class="mb-4 mt-4"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="
|
||||
AlertMatchedTwoIdenticalYMMVehicleHeader
|
||||
"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||
ref="alertVinLookupsByHomeAddressNotAllowed"
|
||||
class="mt-4"
|
||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<customerQuestions
|
||||
ref="customerQuestions"
|
||||
v-model="customerQuestions" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isDisabled="!meta.valid"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -89,7 +87,10 @@ import { Form } from 'vee-validate';
|
|||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import routerParams from '@/router/router-constants/router-params';
|
||||
import { getDamageString, isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
||||
import {
|
||||
getDamageString,
|
||||
isGlassAvailableForCarId,
|
||||
} from '@/helpers/damage-helper';
|
||||
|
||||
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
|
|
@ -104,7 +105,7 @@ export default {
|
|||
customerQuestions,
|
||||
alert,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [baseFormMixin, vinPagesMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -115,8 +116,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -137,7 +138,7 @@ export default {
|
|||
isCarIdDifferent: false,
|
||||
isSelectedGlassAvailableForVehicle: true,
|
||||
customAlertData: {},
|
||||
forwardButtonCarStyle: ''
|
||||
forwardButtonCarStyle: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -151,10 +152,14 @@ export default {
|
|||
const vinYmmFound =
|
||||
// eslint-disable-next-line max-len
|
||||
`${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected =
|
||||
`${useMainStore().order.vehicle.year} ${useMainStore().order.vehicle.make} ${useMainStore().order.vehicle.model}`;
|
||||
const vinYmmExpected = `${useMainStore().order.vehicle.year} ${
|
||||
useMainStore().order.vehicle.make
|
||||
} ${useMainStore().order.vehicle.model}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'BodyText')
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedDifferentVehicleWidget',
|
||||
'BodyText'
|
||||
)
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmFound}', vinYmmFound)
|
||||
.replaceAll('{custom:vinYmmExpected}', vinYmmExpected);
|
||||
|
|
@ -171,9 +176,16 @@ export default {
|
|||
`${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
|
||||
const vinYmmsExpected =
|
||||
// eslint-disable-next-line max-len
|
||||
`${useMainStore().order.vehicle.year} ${useMainStore().order.vehicle.make} ${useMainStore().order.vehicle.model} ${useMainStore().order.vehicle.style}`;
|
||||
`${useMainStore().order.vehicle.year} ${
|
||||
useMainStore().order.vehicle.make
|
||||
} ${useMainStore().order.vehicle.model} ${
|
||||
useMainStore().order.vehicle.style
|
||||
}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget', 'BodyText')
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'BodyText'
|
||||
)
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmsFound}', vinYmmsFound)
|
||||
.replaceAll('{custom:vinYmmsExpected}', vinYmmsExpected);
|
||||
|
|
@ -182,21 +194,24 @@ export default {
|
|||
const vinYmmFound =
|
||||
// eslint-disable-next-line max-len
|
||||
`${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected =
|
||||
`${useMainStore().order.vehicle.year} ${useMainStore().order.vehicle.make} ${useMainStore().order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase());
|
||||
}
|
||||
const vinYmmExpected = `${useMainStore().order.vehicle.year} ${
|
||||
useMainStore().order.vehicle.make
|
||||
} ${useMainStore().order.vehicle.model}`;
|
||||
return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
customerQuestions: {
|
||||
handler() {
|
||||
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName),
|
||||
// then modify the button text back to "Get my personalized quote"
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('siteFooterWidget', 'ForwardButtonText'));
|
||||
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName),
|
||||
// then modify the button text back to "Get my personalized quote"
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('siteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
this.resetWarningsAndErrors();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
|
|
@ -224,23 +239,24 @@ export default {
|
|||
|
||||
const vinLookupResponse = useMainStore().lookupVinByAddress({
|
||||
licenseLastName: this.customerQuestions.lastName,
|
||||
licenseStreetAddress: this.customerQuestions.addressQuestions.streetAddress,
|
||||
licenseStreetAddress:
|
||||
this.customerQuestions.addressQuestions.streetAddress,
|
||||
licenseZip: this.customerQuestions.addressQuestions.zipCode,
|
||||
licenseState: this.customerQuestions.addressQuestions.state
|
||||
licenseState: this.customerQuestions.addressQuestions.state,
|
||||
});
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'vinLookupResponse',
|
||||
promise: vinLookupResponse
|
||||
}
|
||||
promise: vinLookupResponse,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
// If VIN Lookup by address is forbidden by State Restrictions then show an alert
|
||||
if (!resultMap.vinLookupResponse.isStatePermissible) {
|
||||
// State Restrictions forbid lookup by address
|
||||
// State Restrictions forbid lookup by address
|
||||
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
|
||||
this.$refs.siteFooter.disableForwardButton();
|
||||
return this.$refs.siteFooter.removeLoader();
|
||||
|
|
@ -250,12 +266,16 @@ export default {
|
|||
|
||||
// Handle cases for different amounts of VINS found for the address.
|
||||
if (carsFound.length === 1) {
|
||||
// Single VIN found
|
||||
// Single VIN found
|
||||
const carFound = carsFound[0].vehicle;
|
||||
|
||||
this.isCarIdDifferent = carFound.carId !== useMainStore().order.vehicle.carId;
|
||||
if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) {
|
||||
// Display Alert
|
||||
this.isCarIdDifferent =
|
||||
carFound.carId !== useMainStore().order.vehicle.carId;
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
carFound.carId !== this.previouslyEnteredCarId
|
||||
) {
|
||||
// Display Alert
|
||||
this.previouslyEnteredCarId = carFound.carId;
|
||||
this.customAlertData.vehicleInfo = carFound;
|
||||
if (this.isTwoIdenticalYMMVehicleFound) {
|
||||
|
|
@ -265,28 +285,39 @@ export default {
|
|||
this.displayMatchedDifferentVehicleAlert = true;
|
||||
}
|
||||
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(carFound.carId);
|
||||
this.isSelectedGlassAvailableForVehicle =
|
||||
await isGlassAvailableForCarId(carFound.carId);
|
||||
|
||||
// Update button "Continue with..."
|
||||
this.$refs.siteFooter
|
||||
// eslint-disable-next-line max-len
|
||||
.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model} ${this.forwardButtonCarStyle}`);
|
||||
.updateButtonText(
|
||||
`Continue with ${carFound.year} ${carFound.make} ${carFound.model} ${this.forwardButtonCarStyle}`
|
||||
);
|
||||
return this.$refs.siteFooter.removeLoader();
|
||||
}
|
||||
|
||||
// update data
|
||||
vehicleInfoToCommit = Object.assign(carFound, { vin: carsFound[0].vin });
|
||||
vehicleInfoToCommit = Object.assign(carFound, {
|
||||
vin: carsFound[0].vin,
|
||||
});
|
||||
} else if (carsFound.length > 1) {
|
||||
// If multiple cars were found and one and only one of them matches the carId entered, save the vehicle info
|
||||
const matchingCars = carsFound.filter((vin) => vin.vehicle.carId === useMainStore().order.vehicle.carId);
|
||||
const matchingCars = carsFound.filter(
|
||||
(vin) =>
|
||||
vin.vehicle.carId === useMainStore().order.vehicle.carId
|
||||
);
|
||||
|
||||
if (matchingCars.length === 1) {
|
||||
vehicleInfoToCommit = Object.assign(matchingCars[0].vehicle, {
|
||||
vin: matchingCars[0].vin
|
||||
});
|
||||
vehicleInfoToCommit = Object.assign(
|
||||
matchingCars[0].vehicle,
|
||||
{
|
||||
vin: matchingCars[0].vin,
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// No VINS found.
|
||||
// No VINS found.
|
||||
this.displayVinNotFoundAlert = true;
|
||||
this.$refs.siteFooter.disableForwardButton();
|
||||
return this.$refs.siteFooter.removeLoader();
|
||||
|
|
@ -295,19 +326,23 @@ export default {
|
|||
// Save vehicle, customer, service and registration information
|
||||
await useMainStore().saveRegistrationAddressLookup(
|
||||
{
|
||||
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||
isSelectedGlassAvailableForVehicle:
|
||||
this.isSelectedGlassAvailableForVehicle,
|
||||
vehicleInfo:
|
||||
Object.keys(vehicleInfoToCommit).length === 0
|
||||
? null
|
||||
: vehicleInfoToCommit,
|
||||
Object.keys(vehicleInfoToCommit).length === 0
|
||||
? null
|
||||
: vehicleInfoToCommit,
|
||||
registrationInfo: {
|
||||
firstName: this.customerQuestions.firstName,
|
||||
lastName: this.customerQuestions.lastName,
|
||||
address: this.customerQuestions.addressQuestions.streetAddress,
|
||||
address:
|
||||
this.customerQuestions.addressQuestions
|
||||
.streetAddress,
|
||||
city: this.customerQuestions.addressQuestions.city,
|
||||
state: this.customerQuestions.addressQuestions.state,
|
||||
zipCode: this.customerQuestions.addressQuestions.zipCode
|
||||
}
|
||||
zipCode:
|
||||
this.customerQuestions.addressQuestions.zipCode,
|
||||
},
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
@ -315,15 +350,18 @@ export default {
|
|||
return this.navigateForward(carsFound);
|
||||
},
|
||||
async navigateForward(carsFound) {
|
||||
// Match vehicles found to vehicles in state.
|
||||
const matchingCars = carsFound.filter((car) => car.vehicle.carId === useMainStore().order.vehicle.carId);
|
||||
// Match vehicles found to vehicles in state.
|
||||
const matchingCars = carsFound.filter(
|
||||
(car) =>
|
||||
car.vehicle.carId === useMainStore().order.vehicle.carId
|
||||
);
|
||||
|
||||
// If a different vehicle is found than the one entered and the selected glass
|
||||
// is not available for that vehicle then navigate back to "vehicle-damage"
|
||||
// display vehicle changed alert on that page.
|
||||
if (
|
||||
this.isCarIdDifferent
|
||||
&& !this.isSelectedGlassAvailableForVehicle
|
||||
this.isCarIdDifferent &&
|
||||
!this.isSelectedGlassAvailableForVehicle
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
|
|
@ -335,7 +373,8 @@ export default {
|
|||
await this.navigateForwardWithSingleCarMatch();
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{},
|
||||
|
|
@ -348,7 +387,7 @@ export default {
|
|||
this.displayMatchedDifferentVehicleAlert = false;
|
||||
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,66 +1,84 @@
|
|||
<template>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="fade-on-route-transition sub-container overflow-scroll px-5">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
id="multiple-vehicles-alert"
|
||||
ref="alertFoundMultipleVehicles"
|
||||
cmsWidgetName="FoundMultipleVehicles"
|
||||
class="my-5"
|
||||
alertClass="alert-warning"
|
||||
:manualHeadline="AlertFoundMultipleVehiclesHeader"
|
||||
manualCopy=""
|
||||
:isDismissible="false" />
|
||||
<addressVehiclesQuestion
|
||||
ref="addressVehiclesQuestion"
|
||||
v-model="selectedVehicleVin"
|
||||
cmsWidgetName="VehicleConfirmationQuestion"
|
||||
:vehicles="VehiclesForQuestions"
|
||||
:vehicleSelected="VehicleSelected"
|
||||
validationRules="vehicle-required"
|
||||
:isCarIdDifferent="isCarIdDifferent"
|
||||
:displayMatchedDifferentVehicleAlert="displayMatchedDifferentVehicleAlert"
|
||||
:displayMatchedTwoIdenticalYMMVehicleAlert="displayMatchedTwoIdenticalYMMVehicleAlert" />
|
||||
<div
|
||||
v-if="splitAlertProvideVinBodyForLink.length"
|
||||
class="alert-provide-vin my-3">
|
||||
<span
|
||||
v-for="copy in splitAlertProvideVinBodyForLink"
|
||||
:key="copy">
|
||||
<span
|
||||
v-if="doesCopyContainRouterLink(copy)"
|
||||
class="text-body">
|
||||
<router-link
|
||||
:to="{
|
||||
query: { issPage: `${getRouterLinkRouteFromCopy(copy)}` },
|
||||
name: 'root',
|
||||
}">{{ getRouterLinkDisplayTextFromCopy(copy) }}</router-link>
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="m-0 text-body"
|
||||
v-html="copy"></span>
|
||||
</span>
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
id="multiple-vehicles-alert"
|
||||
ref="alertFoundMultipleVehicles"
|
||||
cmsWidgetName="FoundMultipleVehicles"
|
||||
class="my-5"
|
||||
alertClass="alert-warning"
|
||||
:manualHeadline="AlertFoundMultipleVehiclesHeader"
|
||||
manualCopy=""
|
||||
:isDismissible="false" />
|
||||
<addressVehiclesQuestion
|
||||
ref="addressVehiclesQuestion"
|
||||
v-model="selectedVehicleVin"
|
||||
cmsWidgetName="VehicleConfirmationQuestion"
|
||||
:vehicles="VehiclesForQuestions"
|
||||
:vehicleSelected="VehicleSelected"
|
||||
validationRules="vehicle-required"
|
||||
:isCarIdDifferent="isCarIdDifferent"
|
||||
:displayMatchedDifferentVehicleAlert="
|
||||
displayMatchedDifferentVehicleAlert
|
||||
"
|
||||
:displayMatchedTwoIdenticalYMMVehicleAlert="
|
||||
displayMatchedTwoIdenticalYMMVehicleAlert
|
||||
" />
|
||||
<div
|
||||
v-if="splitAlertProvideVinBodyForLink.length"
|
||||
class="alert-provide-vin my-3">
|
||||
<span
|
||||
v-for="copy in splitAlertProvideVinBodyForLink"
|
||||
:key="copy">
|
||||
<span
|
||||
v-if="doesCopyContainRouterLink(copy)"
|
||||
class="text-body">
|
||||
<router-link
|
||||
:to="{
|
||||
query: {
|
||||
issPage: `${getRouterLinkRouteFromCopy(
|
||||
copy
|
||||
)}`,
|
||||
},
|
||||
name: 'root',
|
||||
}"
|
||||
>{{
|
||||
getRouterLinkDisplayTextFromCopy(copy)
|
||||
}}</router-link
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="m-0 text-body"
|
||||
v-html="copy"></span>
|
||||
</span>
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -77,7 +95,7 @@ import {
|
|||
doesCopyContainRouterLink,
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
getRouterLinkRouteFromCopy,
|
||||
getRouterLinkDisplayTextFromCopy
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
} from '@/helpers/cms-content-helper.js';
|
||||
import routerParams from '@/router/router-constants/router-params';
|
||||
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||
|
|
@ -104,7 +122,7 @@ export default {
|
|||
Form,
|
||||
vehicleBanner,
|
||||
alert,
|
||||
addressVehiclesQuestion
|
||||
addressVehiclesQuestion,
|
||||
},
|
||||
mixins: [baseFormMixin, vinPagesMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -114,8 +132,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -125,7 +143,7 @@ export default {
|
|||
});
|
||||
},
|
||||
props: {
|
||||
validationRules: String
|
||||
validationRules: String,
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
|
@ -140,7 +158,7 @@ export default {
|
|||
displayMatchedDifferentVehicleAlert: false,
|
||||
displayMatchedTwoIdenticalYMMVehicleAlert: false,
|
||||
previouslyEnteredCarId: '',
|
||||
forwardButtonCarStyle: ''
|
||||
forwardButtonCarStyle: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -154,11 +172,9 @@ export default {
|
|||
).replaceAll('{custom:vehicleCount}', this.vehicleCount);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
const vinYmmFound =
|
||||
`${this.selectedVehicle?.vehicle.year} ${this.selectedVehicle?.vehicle.make} ${this.selectedVehicle?.vehicle.model}`;
|
||||
const vinYmmExpected =
|
||||
`${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase());
|
||||
const vinYmmFound = `${this.selectedVehicle?.vehicle.year} ${this.selectedVehicle?.vehicle.make} ${this.selectedVehicle?.vehicle.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
|
||||
},
|
||||
AlertProvideVinBody() {
|
||||
return this.getCmsContent('ProvideVinAlert', 'BodyText');
|
||||
|
|
@ -178,7 +194,7 @@ export default {
|
|||
vehicle: v.vehicle,
|
||||
Text: `${v.vehicle.year} ${v.vehicle.make} ${v.vehicle.model}`,
|
||||
Name: v.vin,
|
||||
SubText: `VIN ${vinStart}${vinEnd}`
|
||||
SubText: `VIN ${vinStart}${vinEnd}`,
|
||||
};
|
||||
});
|
||||
return mappedData;
|
||||
|
|
@ -187,11 +203,13 @@ export default {
|
|||
return useMainStore().pageData(issPageValues.ADDRESS_VEHICLES);
|
||||
},
|
||||
selectedVehicle() {
|
||||
return this.VehiclesForQuestions.find(({ vin }) => vin === this.selectedVehicleVin);
|
||||
return this.VehiclesForQuestions.find(
|
||||
({ vin }) => vin === this.selectedVehicleVin
|
||||
);
|
||||
},
|
||||
VehicleSelected() {
|
||||
return this.mainStore.order.vehicle;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedVehicleVin: {
|
||||
|
|
@ -199,10 +217,15 @@ export default {
|
|||
this.resetWarningsAndErrors();
|
||||
// does this vehicle match the previously selected carId?
|
||||
this.isCarIdDifferent =
|
||||
this.selectedVehicle?.vehicle.carId !== useMainStore().vehicle.carId;
|
||||
if (this.isCarIdDifferent
|
||||
&& this.selectedVehicle?.vehicle.carId !== this.previouslyEnteredCarId) {
|
||||
this.previouslyEnteredCarId = this.selectedVehicle?.vehicle.carId;
|
||||
this.selectedVehicle?.vehicle.carId !==
|
||||
useMainStore().vehicle.carId;
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
this.selectedVehicle?.vehicle.carId !==
|
||||
this.previouslyEnteredCarId
|
||||
) {
|
||||
this.previouslyEnteredCarId =
|
||||
this.selectedVehicle?.vehicle.carId;
|
||||
if (this.isTwoIdenticalYMMVehicleFound) {
|
||||
const carStyle = this.selectedVehicle?.vehicle.style;
|
||||
this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
|
||||
|
|
@ -210,15 +233,21 @@ export default {
|
|||
} else {
|
||||
this.displayMatchedDifferentVehicleAlert = true;
|
||||
}
|
||||
this.$refs.siteFooter
|
||||
.updateButtonText(`Continue with ${this.selectedVehicle.vehicle.year} `
|
||||
+ `${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model} ${this.forwardButtonCarStyle}`);
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
`Continue with ${this.selectedVehicle.vehicle.year} ` +
|
||||
`${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model} ${this.forwardButtonCarStyle}`
|
||||
);
|
||||
} else {
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent(
|
||||
'SiteFooterWidget',
|
||||
'ForwardButtonText'
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
doesCopyContainRouterLink,
|
||||
|
|
@ -240,14 +269,15 @@ export default {
|
|||
if (!vinLookup) {
|
||||
return;
|
||||
}
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.carId);
|
||||
this.isSelectedGlassAvailableForVehicle =
|
||||
await isGlassAvailableForCarId(vinLookup.data.carId);
|
||||
await useMainStore().saveVin(
|
||||
{
|
||||
vehicleInfo: Object.assign(this.selectedVehicle.vehicle, {
|
||||
vin: this.selectedVehicle.vin
|
||||
vin: this.selectedVehicle.vin,
|
||||
}),
|
||||
isSelectedGlassAvailableForVehicle:
|
||||
this.isSelectedGlassAvailableForVehicle
|
||||
this.isSelectedGlassAvailableForVehicle,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
@ -257,7 +287,10 @@ export default {
|
|||
async navigateForward() {
|
||||
// If the vehicle selected on this page is different from the one originally entered and the selected glass is not available
|
||||
// for that vehicle, then navigate back to "vehicle-damage" and display vehicle changed alert on that page.
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
!this.isSelectedGlassAvailableForVehicle
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
|
|
@ -272,28 +305,28 @@ export default {
|
|||
this.displayMatchedDifferentVehicleAlert = false;
|
||||
this.displayMatchedTwoIdenticalYMMVehicleAlert = false;
|
||||
this.forwardButtonCarStyle = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.alert-provide-vin {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.4;
|
||||
a {
|
||||
//Per Devyn. This can't be documented in Figma so there is a comment with the Prototype mocks on the Quote page in Figma
|
||||
text-underline-offset: 4px;
|
||||
line-height: inherit;
|
||||
}
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.4;
|
||||
a {
|
||||
//Per Devyn. This can't be documented in Figma so there is a comment with the Prototype mocks on the Quote page in Figma
|
||||
text-underline-offset: 4px;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
#multiple-vehicles-alert p {
|
||||
margin-bottom: 0 !important; // Overrides extra margin-bottom on alert body text
|
||||
margin-bottom: 0 !important; // Overrides extra margin-bottom on alert body text
|
||||
}
|
||||
|
||||
.overflow-scroll {
|
||||
height: calc(100% - 180px);
|
||||
overflow-X: hidden !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,60 +4,66 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="main-content-container">
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
:cmsWidgetName="subHeaderCmsWidgetName"
|
||||
:contentProperty="subHeaderContentProperty"
|
||||
:stripRteStyle="stripRteStyle"
|
||||
:subContentProperty="subContentProperty"
|
||||
class="sub-header-content"
|
||||
justification="left" />
|
||||
<textboxQuestion
|
||||
ref="firstName"
|
||||
v-model="bailoutPageModel.firstName"
|
||||
inputId="firstNameField"
|
||||
cmsWidgetName="FirstNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.firstName" />
|
||||
<textboxQuestion
|
||||
ref="lastName"
|
||||
v-model="bailoutPageModel.lastName"
|
||||
inputId="lastNameField"
|
||||
cmsWidgetName="LastNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.lastName" />
|
||||
<textboxQuestion
|
||||
ref="phoneNumber"
|
||||
v-model="bailoutPageModel.phoneNumber"
|
||||
inputId="phoneNumberField"
|
||||
cmsWidgetName="PhoneNumberQuestion"
|
||||
isRequired
|
||||
:mask="phoneMask"
|
||||
disableAutoFill
|
||||
:validationRules="rules.phoneNumber" />
|
||||
<textboxQuestion
|
||||
ref="emailAddress"
|
||||
v-model="bailoutPageModel.email"
|
||||
inputId="emailAddressField"
|
||||
cmsWidgetName="EmailAddressQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.email" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="footer-content-container"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
:isBackButtonHidden="!canNavigateBack"
|
||||
@backClicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
<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="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
:cmsWidgetName="subHeaderCmsWidgetName"
|
||||
:contentProperty="subHeaderContentProperty"
|
||||
:stripRteStyle="stripRteStyle"
|
||||
:subContentProperty="subContentProperty"
|
||||
class="sub-header-content"
|
||||
justification="left" />
|
||||
<textboxQuestion
|
||||
ref="firstName"
|
||||
v-model="bailoutPageModel.firstName"
|
||||
inputId="firstNameField"
|
||||
cmsWidgetName="FirstNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.firstName" />
|
||||
<textboxQuestion
|
||||
ref="lastName"
|
||||
v-model="bailoutPageModel.lastName"
|
||||
inputId="lastNameField"
|
||||
cmsWidgetName="LastNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.lastName" />
|
||||
<textboxQuestion
|
||||
ref="phoneNumber"
|
||||
v-model="bailoutPageModel.phoneNumber"
|
||||
inputId="phoneNumberField"
|
||||
cmsWidgetName="PhoneNumberQuestion"
|
||||
isRequired
|
||||
:mask="phoneMask"
|
||||
disableAutoFill
|
||||
:validationRules="rules.phoneNumber" />
|
||||
<textboxQuestion
|
||||
ref="emailAddress"
|
||||
v-model="bailoutPageModel.email"
|
||||
inputId="emailAddressField"
|
||||
cmsWidgetName="EmailAddressQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.email" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="footer-content-container"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
:isBackButtonHidden="!canNavigateBack"
|
||||
@backClicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
|
|
@ -90,7 +96,7 @@ export default {
|
|||
siteFooter,
|
||||
textboxQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -100,8 +106,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -121,14 +127,14 @@ export default {
|
|||
widget: {
|
||||
defaultSiteHeader: 'SiteSubHeaderWidget',
|
||||
noTpa: 'ContentGroupNoTPAWidget',
|
||||
notSeeingPreferredShop: 'ContentGroupNotSeeingPreferredShop'
|
||||
notSeeingPreferredShop: 'ContentGroupNotSeeingPreferredShop',
|
||||
},
|
||||
rules: {
|
||||
firstName: globalRules.FIRST_NAME_REQUIRED,
|
||||
lastName: globalRules.LAST_NAME_REQUIRED,
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`,
|
||||
email: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`
|
||||
}
|
||||
email: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -179,13 +185,16 @@ export default {
|
|||
},
|
||||
phoneMask() {
|
||||
return MaskaFormattedMasks.PHONE_NUMBER;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
backButtonAction() {
|
||||
// route to move backwards
|
||||
this.mainStore.resetBailout();
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK_PREVIOUS, this.$route);
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_BACK_PREVIOUS,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
forwardButtonAction() {
|
||||
this.mainStore.setBailoutContactInfo(this.bailoutPageModel);
|
||||
|
|
@ -201,10 +210,10 @@ export default {
|
|||
firstName: useMainStore().order.customer.firstName,
|
||||
lastName: useMainStore().order.customer.lastName,
|
||||
phoneNumber: useMainStore().order.customer.phoneNumber,
|
||||
email: useMainStore().order.customer.emailAddress
|
||||
email: useMainStore().order.customer.emailAddress,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
<template>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<questionsPageLayout
|
||||
ref="questionsPageLayout"
|
||||
v-model="selectedAnswers"
|
||||
isRequired
|
||||
:isMetaValid="meta.valid"
|
||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||
:questionsData="questionsData"
|
||||
:validationRules="rules.optionRequired"
|
||||
:index="currentGlassIndex"
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@backClick="navigateBackByVehicleQuestions" />
|
||||
</Form>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<questionsPageLayout
|
||||
ref="questionsPageLayout"
|
||||
v-model="selectedAnswers"
|
||||
isRequired
|
||||
:isMetaValid="meta.valid"
|
||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||
:questionsData="questionsData"
|
||||
:validationRules="rules.optionRequired"
|
||||
:index="currentGlassIndex"
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@backClick="navigateBackByVehicleQuestions" />
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
|
|
@ -37,7 +37,7 @@ export default {
|
|||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
questionsPageLayout
|
||||
questionsPageLayout,
|
||||
},
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -47,8 +47,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -63,36 +63,49 @@ export default {
|
|||
selectedAnswers: {},
|
||||
currentGlassIndex: 0,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
AlertFewMoreQuestionsHeader() {
|
||||
return this.getCmsContent('AdditionalPartsQuestionsAlert', 'HeadlineText');
|
||||
return this.getCmsContent(
|
||||
'AdditionalPartsQuestionsAlert',
|
||||
'HeadlineText'
|
||||
);
|
||||
},
|
||||
AlertFewMoreQuestionsCopy() {
|
||||
return this.getCmsContent('AdditionalPartsQuestionsAlert', 'BodyText');
|
||||
return this.getCmsContent(
|
||||
'AdditionalPartsQuestionsAlert',
|
||||
'BodyText'
|
||||
);
|
||||
},
|
||||
partsOrQuestionsData() {
|
||||
return useMainStore().pageData(issPageValues.CAPABILITY_QUESTIONS)
|
||||
.partsOrQuestions;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getInitialQuestionData();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
const capabilityQuestionsFromPageData = useMainStore().pageData(issPageValues.CAPABILITY_QUESTIONS);
|
||||
const capabilityQuestionsFromPageData = useMainStore().pageData(
|
||||
issPageValues.CAPABILITY_QUESTIONS
|
||||
);
|
||||
return (
|
||||
capabilityQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName)
|
||||
&& capabilityQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.capabilityQuestions?.length > 0)
|
||||
capabilityQuestionsFromPageData?.partsOrQuestions?.some(
|
||||
(part) => part?.glassName
|
||||
) &&
|
||||
capabilityQuestionsFromPageData?.partsOrQuestions?.some(
|
||||
(part) => part?.capabilityQuestions?.length > 0
|
||||
)
|
||||
);
|
||||
},
|
||||
getInitialQuestionData() {
|
||||
// get any questions that were already answered
|
||||
const alreadyAnsweredQuestions = useMainStore().damage.capabilityQuestionAnswers;
|
||||
const alreadyAnsweredQuestions =
|
||||
useMainStore().damage.capabilityQuestionAnswers;
|
||||
this.questionsData = this.partsOrQuestionsData
|
||||
.filter((x) => x.capabilityQuestions)
|
||||
.map((glass, index) => {
|
||||
|
|
@ -111,7 +124,10 @@ export default {
|
|||
`selectedAnswers.${glass.answerKey}`,
|
||||
(newValue) => {
|
||||
if (newValue && Object.keys(newValue).length > 0) {
|
||||
this.handleAnswerUpdates(newValue, glass.answerKey);
|
||||
this.handleAnswerUpdates(
|
||||
newValue,
|
||||
glass.answerKey
|
||||
);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
|
|
@ -124,7 +140,9 @@ export default {
|
|||
// get answerResult2 of returned answer
|
||||
let selectedAnswerResult2;
|
||||
glass.questions.forEach((q) => {
|
||||
const idx = q.answers.findIndex((a) => a.answerResult === glass.answerData.answerResult);
|
||||
const idx = q.answers.findIndex(
|
||||
(a) => a.answerResult === glass.answerData.answerResult
|
||||
);
|
||||
if (idx !== -1) {
|
||||
selectedAnswerResult2 = q.answers[idx].answerResult2;
|
||||
}
|
||||
|
|
@ -136,7 +154,7 @@ export default {
|
|||
result1: glass.answerData.answerResult,
|
||||
result2: selectedAnswerResult2,
|
||||
answeredQuestions: glass.answerData.answeredQuestions,
|
||||
isSuppressedPart: glass.isSuppressedPart
|
||||
isSuppressedPart: glass.isSuppressedPart,
|
||||
};
|
||||
});
|
||||
// clear out answerData for future page loads; must occur prior to store save
|
||||
|
|
@ -144,22 +162,25 @@ export default {
|
|||
glass.answerData = {};
|
||||
});
|
||||
// save to store as order.damage.moldingQuestionArrays (array)
|
||||
await this.mainStore.saveCapabilityQuestionAnswers(questionAnswersArray);
|
||||
await this.mainStore.saveCapabilityQuestionAnswers(
|
||||
questionAnswersArray
|
||||
);
|
||||
// get parts from the capabilityQuestionAnswers
|
||||
const partsOrQuestions = this.partsOrQuestionsData;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const answer of questionAnswersArray) {
|
||||
partsOrQuestions.find((partOrQuestion) => (
|
||||
partOrQuestion.glassLocation === answer.glassLocation
|
||||
&& partOrQuestion.glassName === answer.glassName
|
||||
)).parts[0].childParts = [
|
||||
partsOrQuestions.find(
|
||||
(partOrQuestion) =>
|
||||
partOrQuestion.glassLocation === answer.glassLocation &&
|
||||
partOrQuestion.glassName === answer.glassName
|
||||
).parts[0].childParts = [
|
||||
{
|
||||
partNumber: answer.partNum
|
||||
}
|
||||
partNumber: answer.partNum,
|
||||
},
|
||||
];
|
||||
}
|
||||
this.navigateForward(partsOrQuestions, null);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
<template>
|
||||
<div class="page-container-grouped-styles">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="main-content-container">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="sub-header-content"
|
||||
justification="left" />
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="sub-header-content"
|
||||
justification="left" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -23,7 +29,7 @@ export default {
|
|||
name: 'contact-confirmation',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader
|
||||
siteSubHeader,
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
|
@ -32,8 +38,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -47,13 +53,15 @@ export default {
|
|||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
const contactConfirmationData = useMainStore().pageData(issPageValues.CONTACT_CONFIRMATION);
|
||||
const contactConfirmationData = useMainStore().pageData(
|
||||
issPageValues.CONTACT_CONFIRMATION
|
||||
);
|
||||
return {
|
||||
contactConfirmationModel: contactConfirmationData
|
||||
contactConfirmationModel: contactConfirmationData,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
methods: {}
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
:cmsWidgetName="widget.siteHeader" />
|
||||
<div class="container-fluid px-6">
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
id="sub-header"
|
||||
ref="siteSubHeader"
|
||||
|
|
@ -66,10 +70,9 @@
|
|||
:cmsWidgetName="widget.notesQuestion"
|
||||
maxLength="250"
|
||||
:inputRows="4" />
|
||||
<p
|
||||
ref="disclaimerText"
|
||||
class="caption dark-gray mt-6">
|
||||
{{ textUpdateDisclaimerText }} I also agree to Safelite's
|
||||
<p ref="disclaimerText" class="caption dark-gray mt-6">
|
||||
{{ textUpdateDisclaimerText }} I also agree to
|
||||
Safelite's
|
||||
<textLink
|
||||
ref="privacyPolicyLink"
|
||||
class="normal-line-height"
|
||||
|
|
@ -125,7 +128,7 @@ export default {
|
|||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
textLink
|
||||
textLink,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -136,12 +139,14 @@ export default {
|
|||
});
|
||||
},
|
||||
data() {
|
||||
const { firstName,
|
||||
const {
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
servicePhone,
|
||||
requestTextUpdates,
|
||||
notesForTechnician } = useMainStore().contactInfo;
|
||||
notesForTechnician,
|
||||
} = useMainStore().contactInfo;
|
||||
return {
|
||||
firstName,
|
||||
lastName,
|
||||
|
|
@ -159,14 +164,14 @@ export default {
|
|||
requestTextUpdates: 'TextContentWidget',
|
||||
notesQuestion: 'NotesQuestionWidget',
|
||||
disclaimer: 'TextUpdateDisclaimerWidget',
|
||||
siteFooter: 'SiteFooterWidget'
|
||||
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}`
|
||||
}
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -174,7 +179,10 @@ export default {
|
|||
* @returns {string} Returns the CMS text associated with the "get text updates" checkbox.
|
||||
*/
|
||||
requestTextUpdatesCheckboxText() {
|
||||
return `${this.getCmsContent(this.widget.requestTextUpdates, 'Text')}*`;
|
||||
return `${this.getCmsContent(
|
||||
this.widget.requestTextUpdates,
|
||||
'Text'
|
||||
)}*`;
|
||||
},
|
||||
/**
|
||||
* @returns {string} Returns the CMS text associated with the "get text updates" checkbox.
|
||||
|
|
@ -184,10 +192,9 @@ export default {
|
|||
},
|
||||
phoneMask() {
|
||||
return MaskaFormattedMasks.PHONE_NUMBER;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods:
|
||||
{
|
||||
methods: {
|
||||
/**
|
||||
* @summary Steps to perform when forward button clicked.
|
||||
*/
|
||||
|
|
@ -197,28 +204,32 @@ export default {
|
|||
lastName: this.lastName,
|
||||
emailAddress: this.emailAddress,
|
||||
requestTextUpdates: this.requestTextUpdates,
|
||||
notesForTechnician: this.notesForTechnician
|
||||
notesForTechnician: this.notesForTechnician,
|
||||
};
|
||||
useMainStore().updateContactInfo(contactInfo);
|
||||
|
||||
if (this.requestTextUpdates) {
|
||||
useMainStore().updatePhoneNumbers({
|
||||
service: this.phoneNumber,
|
||||
alternative: this.phoneNumber
|
||||
alternative: this.phoneNumber,
|
||||
});
|
||||
} else {
|
||||
useMainStore().updatePhoneNumbers({
|
||||
home: this.phoneNumber,
|
||||
service: this.phoneNumber
|
||||
service: this.phoneNumber,
|
||||
});
|
||||
}
|
||||
|
||||
const scenario = useMainStore().order.serviceLocation.IsSafeliteProvider === false
|
||||
? this.navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP
|
||||
: this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP;
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -230,5 +241,4 @@ export default {
|
|||
.normal-line-height {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,111 +1,99 @@
|
|||
<template>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<loadingModal
|
||||
ref="loadingModal"
|
||||
:textSlides="loadingText" />
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="pb-1 mt-4">
|
||||
<h5
|
||||
ref="siteSubHeader"
|
||||
class="text-center text-black"
|
||||
v-html="coverageStatementSubHeader">
|
||||
</h5>
|
||||
<div
|
||||
ref="explanatoryText"
|
||||
class="body-text text-center mt-2"
|
||||
v-html="explanatoryText">
|
||||
</div>
|
||||
<div
|
||||
ref="secondaryText"
|
||||
class="text-center mt-4 mb-1 fw-bold text-black"
|
||||
v-html="secondaryText">
|
||||
</div>
|
||||
<div
|
||||
v-if="isDeductibleVisible"
|
||||
class="d-flex justify-content-center cost">
|
||||
{{ formatAmountInDollars(deductibleValue) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="isQuoteDisplayed"
|
||||
class="d-flex justify-content-center cost mb-0">
|
||||
{{ formatAmountInDollars(totalServicePrice) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="isITACQuoteVisible"
|
||||
class="d-flex justify-content-center mb-4 deductible-text">
|
||||
{{ deductibleText }}
|
||||
<span class="text-success fw-bold">{{ formatAmountInDollars(deductibleValue) }}</span>
|
||||
</div>
|
||||
<alert
|
||||
v-if="isITACQuoteVisible"
|
||||
ref="verifiedITACAlert"
|
||||
class="mb-5"
|
||||
cmsWidgetName="VerifiedITACAlert"
|
||||
:manualHeadline="verifiedItacAlertHeader"
|
||||
:manualCopy="verifiedItacAlertBody"
|
||||
alertClass="alert-success"
|
||||
: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>
|
||||
<buttonQuestion
|
||||
v-if="isQuoteDisplayed"
|
||||
v-model="selectedProvider"
|
||||
cmsWidgetName="ServiceProviderQuestion"
|
||||
:questionText="serviceProviderQuestionText"
|
||||
:answers="serviceProviderQuestionAnswers"
|
||||
groupName="ServiceProviderQuestionOption"
|
||||
buttonTypeString="listButton"
|
||||
isRequired
|
||||
:validationRules="rules.selectionRequired">
|
||||
</buttonQuestion>
|
||||
<text-block
|
||||
v-if="isQuoteDisplayed"
|
||||
cmsWidgetName="DisclaimerWidget"
|
||||
typeStyle="caption" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBackByVehicleQuestions"
|
||||
@forwardClicked="navigateForward" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<recalModal
|
||||
ref="RecalModal"
|
||||
cmsWidgetName="RecalModal" />
|
||||
<contentGroupModal
|
||||
ref="DeductibleModal"
|
||||
cmsWidgetName="DeductibleModal"
|
||||
class="deductible-modal" />
|
||||
</Form>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@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">
|
||||
<loadingModal
|
||||
ref="loadingModal"
|
||||
:textSlides="loadingText" />
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center pt-5">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<h5
|
||||
ref="siteSubHeader"
|
||||
class="text-center text-black"
|
||||
v-html="coverageStatementSubHeader"></h5>
|
||||
<div
|
||||
ref="explanatoryText"
|
||||
class="body-text text-center mt-2"
|
||||
v-html="explanatoryText"></div>
|
||||
<div
|
||||
ref="secondaryText"
|
||||
class="text-center mt-4 mb-1 fw-bold text-black"
|
||||
v-html="secondaryText"></div>
|
||||
<div
|
||||
v-if="verifiedDeductible"
|
||||
class="d-flex justify-content-center cost">
|
||||
{{ deductibleForDisplay }}
|
||||
</div>
|
||||
<div
|
||||
v-if="isQuoteDisplayed"
|
||||
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">
|
||||
{{ deductibleText }}
|
||||
<span class="text-success fw-bold">{{
|
||||
deductibleForDisplay
|
||||
}}</span>
|
||||
</div>
|
||||
<alert
|
||||
v-if="verifiedITAC"
|
||||
ref="verifiedITACAlert"
|
||||
class="mb-5"
|
||||
cmsWidgetName="VerifiedITACAlert"
|
||||
:manualHeadline="verifiedItacAlertHeader"
|
||||
:manualCopy="verifiedItacAlertBody"
|
||||
alertClass="alert-success"
|
||||
: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>
|
||||
<buttonQuestion
|
||||
v-if="isQuoteDisplayed"
|
||||
v-model="selectedProvider"
|
||||
cmsWidgetName="ServiceProviderQuestion"
|
||||
:questionText="serviceProviderQuestionText"
|
||||
:answers="serviceProviderQuestionAnswers"
|
||||
groupName="ServiceProviderQuestionOption"
|
||||
buttonTypeString="listButton"
|
||||
isRequired
|
||||
:validationRules="rules.selectionRequired">
|
||||
</buttonQuestion>
|
||||
<text-block
|
||||
v-if="isQuoteDisplayed"
|
||||
cmsWidgetName="DisclaimerWidget"
|
||||
typeStyle="caption" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBackByVehicleQuestions"
|
||||
@forwardClicked="navigateForward" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<recalModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
<contentGroupModal
|
||||
ref="DeductibleModal"
|
||||
cmsWidgetName="DeductibleModal"
|
||||
class="deductible-modal" />
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
// Import Component
|
||||
import { Form } from 'vee-validate';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
|
|
@ -119,7 +107,11 @@ import textBlock from '@/digital-components/text-block/text-block.vue';
|
|||
import pageVariations from '@/constants/coverage-statement-page-variations';
|
||||
|
||||
// Import Supporting Files
|
||||
import { fetchCmsContentForPage, setupModalLinks, processIfStatements } from '@/helpers/cms-content-helper.js';
|
||||
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';
|
||||
|
|
@ -148,24 +140,25 @@ export default {
|
|||
contentGroupModal,
|
||||
buttonQuestion,
|
||||
loadingModal,
|
||||
textBlock
|
||||
textBlock,
|
||||
},
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to?.query?.issPage);
|
||||
const supportingItemsPromise = await useMainStore().getSupportingItems();
|
||||
const supportingItemsPromise =
|
||||
await useMainStore().getSupportingItems();
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'supportingItems',
|
||||
promise: supportingItemsPromise
|
||||
}
|
||||
promise: supportingItemsPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -175,7 +168,7 @@ export default {
|
|||
// TODO SSR-1165: Recycle fee needs removed from quote calculation
|
||||
const availableLineItems = [
|
||||
...(resultMap.supportingItems ?? []),
|
||||
...(clonedGlassParts ?? [])
|
||||
...(clonedGlassParts ?? []),
|
||||
];
|
||||
|
||||
let hasBailedOut = false;
|
||||
|
|
@ -183,12 +176,19 @@ export default {
|
|||
const { policy, vehicle } = useMainStore();
|
||||
if (policy.policyLookupSuccessful && vehicle.policyVehicleId >= 0) {
|
||||
await useMainStore().getFinalDeductible();
|
||||
pricingResults = await useMainStore().getPriceOrderItems(availableLineItems)
|
||||
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 }
|
||||
));
|
||||
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}`);
|
||||
});
|
||||
|
|
@ -218,10 +218,10 @@ export default {
|
|||
loadingText: [
|
||||
'Connecting to your insurance company',
|
||||
'Nearly there',
|
||||
'Finishing up'
|
||||
'Finishing up',
|
||||
],
|
||||
rules: {
|
||||
selectionRequired: globalRules.OPTION_REQUIRED
|
||||
selectionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
supportingItems: null,
|
||||
widget: {
|
||||
|
|
@ -229,8 +229,8 @@ export default {
|
|||
verifiedItacAlert: 'VerifiedITACAlert',
|
||||
explanatoryText: 'ExplanatoryTextWidget',
|
||||
nextStep: 'NextStepsWidget',
|
||||
serviceProviderQuestion: 'ServiceProviderQuestion'
|
||||
}
|
||||
serviceProviderQuestion: 'ServiceProviderQuestion',
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -240,9 +240,10 @@ export default {
|
|||
issConfig,
|
||||
policy,
|
||||
payment,
|
||||
isClaimRegistrationRequired
|
||||
isClaimRegistrationRequired,
|
||||
} = useMainStore();
|
||||
const registerClaimSuccessful = payment.insuranceCoverage.isVerified;
|
||||
const registerClaimSuccessful =
|
||||
payment.insuranceCoverage.isVerified;
|
||||
|
||||
if (!policy.policyLookupSuccessful) {
|
||||
return pageVariations.UNVERIFIED;
|
||||
|
|
@ -287,12 +288,14 @@ export default {
|
|||
);
|
||||
},
|
||||
verifiedItacAlertBody() {
|
||||
const itacCostSavings = this.deductibleValue - this.totalServicePrice;
|
||||
const itacCostSavings =
|
||||
this.deductibleValue - this.totalServicePrice;
|
||||
return this.getCmsContent(
|
||||
this.widget.verifiedItacAlert,
|
||||
widgetFields.ALERT_WIDGET.BODY_TEXT
|
||||
)?.replaceAll(
|
||||
'{custom:costSavings}',
|
||||
|
||||
formatAmountInDollars(itacCostSavings)
|
||||
);
|
||||
},
|
||||
|
|
@ -336,12 +339,16 @@ export default {
|
|||
isDeductibleVisible() {
|
||||
return this.pageVariation === pageVariations.DEDUCTIBLE;
|
||||
},
|
||||
|
||||
isUnverifiedVisible() {
|
||||
return this.pageVariation === pageVariations.UNVERIFIED;
|
||||
},
|
||||
isADAS() {
|
||||
const { glassParts } = useMainStore().order.lineItems;
|
||||
return glassParts !== null && !!glassParts.find((part) => part.requiresRecalibration);
|
||||
return (
|
||||
glassParts !== null &&
|
||||
!!glassParts.find((part) => part.requiresRecalibration)
|
||||
);
|
||||
},
|
||||
totalServicePrice() {
|
||||
return getPriceOfLineItems(this.baseServiceLineItems);
|
||||
|
|
@ -366,20 +373,25 @@ export default {
|
|||
policy,
|
||||
vehicle,
|
||||
isClaimRegistrationRequired,
|
||||
isClaimAlreadyRegistered
|
||||
isClaimAlreadyRegistered,
|
||||
} = useMainStore();
|
||||
const { policyVehicleId } = vehicle;
|
||||
return policy.policyLookupSuccessful
|
||||
&& policyVehicleId != null
|
||||
&& policyVehicleId >= 0
|
||||
&& isClaimRegistrationRequired
|
||||
&& !isClaimAlreadyRegistered
|
||||
&& !this.isNoCompQuoteVisible;
|
||||
}
|
||||
return (
|
||||
policy.policyLookupSuccessful &&
|
||||
policyVehicleId != null &&
|
||||
policyVehicleId >= 0 &&
|
||||
isClaimRegistrationRequired &&
|
||||
!isClaimAlreadyRegistered &&
|
||||
!this.isNoCompQuoteVisible
|
||||
);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedProvider() {
|
||||
const buttonText = this.selectedProvider === SAFELITE_PROVIDER ? 'Continue with Safelite' : 'Safelite';
|
||||
const buttonText =
|
||||
this.selectedProvider === SAFELITE_PROVIDER
|
||||
? 'Continue with Safelite'
|
||||
: 'Safelite';
|
||||
this.$refs.siteFooter.updateButtonText(buttonText);
|
||||
},
|
||||
nextStepsBody(newValue, oldValue) {
|
||||
|
|
@ -387,7 +399,7 @@ export default {
|
|||
setupModalLinks(this, 'RecalModal');
|
||||
setupModalLinks(this, 'DeductibleModal');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
setupModalLinks(this);
|
||||
|
|
@ -399,12 +411,15 @@ export default {
|
|||
async initializeComponent() {
|
||||
useMainStore().updatePolicyITACFlag(this.isITACQuoteVisible);
|
||||
// TODO how should coverage status be updated
|
||||
const coverageStatus = this.isITACQuoteVisible || this.isNoCompQuoteVisible
|
||||
? coverageStatuses.VERIFIED
|
||||
: coverageStatuses.PENDING;
|
||||
const coverageStatus =
|
||||
this.isITACQuoteVisible || this.isNoCompQuoteVisible
|
||||
? coverageStatuses.VERIFIED
|
||||
: coverageStatuses.PENDING;
|
||||
useMainStore().updateCoverageStatus(coverageStatus);
|
||||
if (this.shouldRegisterClaim) {
|
||||
await useMainStore().registerClaim()?.catch(() => {});
|
||||
await useMainStore()
|
||||
.registerClaim()
|
||||
?.catch(() => {});
|
||||
}
|
||||
this.$refs.loadingModal.hideModal();
|
||||
},
|
||||
|
|
@ -413,17 +428,27 @@ export default {
|
|||
useMainStore().updateSupportingItems(this.supportingItems);
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD);
|
||||
} else if (this.isITACQuoteVisible || this.isNoCompQuoteVisible) {
|
||||
useMainStore().updateIsSafeliteProvider(this.selectedProvider === SAFELITE_PROVIDER);
|
||||
useMainStore().updateIsSafeliteProvider(
|
||||
this.selectedProvider === SAFELITE_PROVIDER
|
||||
);
|
||||
if (this.selectedProvider === SAFELITE_PROVIDER) {
|
||||
useMainStore().updateSupportingItems(this.supportingItems);
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE);
|
||||
this.navigateWithScenario(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE
|
||||
);
|
||||
} else {
|
||||
useMainStore().setBailout(bailoutMessage.RequestCallback());
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP);
|
||||
this.navigateWithScenario(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP
|
||||
);
|
||||
}
|
||||
} else {
|
||||
useMainStore().setBailout(bailoutMessage.coverageStatementInvalidState());
|
||||
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE);
|
||||
useMainStore().setBailout(
|
||||
bailoutMessage.coverageStatementInvalidState()
|
||||
);
|
||||
this.navigateWithScenario(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE
|
||||
);
|
||||
}
|
||||
},
|
||||
navigateWithScenario(scenario) {
|
||||
|
|
@ -431,7 +456,11 @@ export default {
|
|||
},
|
||||
getTextFromCmsWithCustomIfStatements(widgetName, widgetField) {
|
||||
const rawText = this.getCmsContent(widgetName, widgetField);
|
||||
return processIfStatements(rawText, 'custom', this.getCustomValueFromString);
|
||||
return processIfStatements(
|
||||
rawText,
|
||||
'custom',
|
||||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
const { isRepair } = useMainStore().damage;
|
||||
|
|
@ -451,9 +480,13 @@ export default {
|
|||
case 'nonADASRepair':
|
||||
return isRepair;
|
||||
case 'deductibleOverZero':
|
||||
return this.isDeductibleVisible && this.deductibleValue !== 0; // TODO what if deductible is negative?
|
||||
return (
|
||||
this.isDeductibleVisible && this.deductibleValue !== 0
|
||||
); // TODO what if deductible is negative?
|
||||
case 'isDeductibleZero':
|
||||
return this.isDeductibleVisible && this.deductibleValue === 0;
|
||||
return (
|
||||
this.isDeductibleVisible && this.deductibleValue === 0
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -464,17 +497,17 @@ export default {
|
|||
setBaseServiceLineItems(lineItems) {
|
||||
this.baseServiceLineItems = lineItems;
|
||||
},
|
||||
formatAmountInDollars
|
||||
}
|
||||
formatAmountInDollars,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cost {
|
||||
color: $green;
|
||||
font-size: 2rem;
|
||||
font-weight: $font-weight-light;
|
||||
line-height: 2.75rem;
|
||||
color: $green;
|
||||
font-size: 2rem;
|
||||
font-weight: $font-weight-light;
|
||||
line-height: 2.75rem;
|
||||
}
|
||||
|
||||
.deductible-text {
|
||||
|
|
@ -501,23 +534,22 @@ export default {
|
|||
}
|
||||
|
||||
:deep .deductible-modal {
|
||||
p {
|
||||
margin-bottom: 0 !important;
|
||||
font-size: 1rem;
|
||||
line-height: 1.625rem;
|
||||
}
|
||||
img.mb-4 {
|
||||
margin: 0 !important;
|
||||
}
|
||||
h5 {
|
||||
color: black;
|
||||
}
|
||||
p:last-child {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 0 !important;
|
||||
font-size: 1rem;
|
||||
line-height: 1.625rem;
|
||||
}
|
||||
img.mb-4 {
|
||||
margin: 0 !important;
|
||||
}
|
||||
h5 {
|
||||
color: black;
|
||||
}
|
||||
p:last-child {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
.modal {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
:cmsWidgetName="widget.siteHeader" />
|
||||
<div class="container-fluid px-6">
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
id="sub-header"
|
||||
ref="siteSubHeader"
|
||||
|
|
@ -25,8 +29,7 @@
|
|||
groupName="existingOrNewQuestionOption"
|
||||
buttonTypeString="listButton"
|
||||
isRequired
|
||||
:validationRules="rules.selectionRequired">
|
||||
</buttonQuestion>
|
||||
:validationRules="rules.selectionRequired" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="my-5"
|
||||
|
|
@ -63,7 +66,7 @@ export default {
|
|||
buttonQuestion,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -84,47 +87,62 @@ export default {
|
|||
siteHeader: 'SiteHeaderWidget',
|
||||
siteSubHeader: 'SiteSubHeaderWidget',
|
||||
existingOrNewQuestion: 'ExistingOrNewQuestion',
|
||||
siteFooter: 'SiteFooterWidget'
|
||||
siteFooter: 'SiteFooterWidget',
|
||||
},
|
||||
rules: {
|
||||
selectionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
selectionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.widget.existingOrNewQuestion, 'QuestionText');
|
||||
return this.getCmsContent(
|
||||
this.widget.existingOrNewQuestion,
|
||||
'QuestionText'
|
||||
);
|
||||
},
|
||||
answersFromCms() {
|
||||
return this.getCmsContent(this.widget.existingOrNewQuestion, 'Answers') ?? [];
|
||||
return (
|
||||
this.getCmsContent(
|
||||
this.widget.existingOrNewQuestion,
|
||||
'Answers'
|
||||
) ?? []
|
||||
);
|
||||
},
|
||||
getNewOrderSelectionName() {
|
||||
return this.answersFromCms?.[0]?.Name ?? '';
|
||||
},
|
||||
duplicateOrders() {
|
||||
const duplicateOrderText = 'Finish Existing Claim';
|
||||
const orders = this.mainStore.applicationUser.duplicateOrders;
|
||||
return orders?.map((o) => {
|
||||
const vehicle = !!o.vehicleYear && !!o.vehicleMake && !!o.vehicleModel
|
||||
? `${o.vehicleYear} ${o.vehicleMake} ${o.vehicleModel}`
|
||||
: null;
|
||||
const orders = useMainStore().applicationUser.duplicateOrders;
|
||||
return (
|
||||
orders?.map((o) => {
|
||||
const vehicle =
|
||||
!!o.vehicleYear && !!o.vehicleMake && !!o.vehicleModel
|
||||
? `${o.vehicleYear} ${o.vehicleMake} ${o.vehicleModel}`
|
||||
: null;
|
||||
|
||||
const dateOfLoss = o.responseDate == null ? '' : new Date(o.responseDate).toLocaleDateString();
|
||||
const subtext = vehicle && o.responseDate
|
||||
? `${vehicle}, ${dateOfLoss}`
|
||||
: (vehicle ?? '').concat(dateOfLoss);
|
||||
const dateOfLoss =
|
||||
o.responseDate == null
|
||||
? ''
|
||||
: new Date(o.responseDate).toLocaleDateString();
|
||||
const subtext =
|
||||
vehicle && o.responseDate
|
||||
? `${vehicle}, ${dateOfLoss}`
|
||||
: (vehicle ?? '').concat(dateOfLoss);
|
||||
|
||||
return {
|
||||
Text: duplicateOrderText,
|
||||
Name: o.referralNumber,
|
||||
SubText: toTitleCase(subtext),
|
||||
value: o.correlationId
|
||||
};
|
||||
}) ?? [];
|
||||
return {
|
||||
Text: duplicateOrderText,
|
||||
Name: o.referralNumber,
|
||||
SubText: toTitleCase(subtext),
|
||||
value: o.correlationId,
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
},
|
||||
answers() {
|
||||
return [...this.duplicateOrders, ...this.answersFromCms];
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
|
|
@ -132,9 +150,13 @@ export default {
|
|||
*/
|
||||
async forwardButtonAction() {
|
||||
if (this.selectedAnswer !== null) {
|
||||
const selectedReferral = this.mainStore.applicationUser.duplicateOrders.find((o) => o.correlationId === this.selectedAnswer);
|
||||
const selectedReferral =
|
||||
this.mainStore.applicationUser.duplicateOrders.find(
|
||||
(o) => o.correlationId === this.selectedAnswer
|
||||
);
|
||||
if (selectedReferral) {
|
||||
await this.mainStore.loadSession(selectedReferral)
|
||||
await this.mainStore
|
||||
.loadSession(selectedReferral)
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
this.navigateForward();
|
||||
|
|
@ -142,7 +164,6 @@ export default {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
|
|
@ -158,12 +179,14 @@ export default {
|
|||
if (!this.mainStore.order.loadedFromDupeCheck) {
|
||||
if (policyVehicles.length !== 0) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
|
|
@ -172,22 +195,25 @@ export default {
|
|||
|
||||
if (this.mainStore.order.vehicle.vin) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_POLICY_VEHICLE,
|
||||
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.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.navigationScenarios
|
||||
.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_NO_POLICY_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -209,9 +235,8 @@ export default {
|
|||
margin-top: map-get($spacers, 4);
|
||||
margin-bottom: map-get($spacers, 2);
|
||||
}
|
||||
.form-test-error{
|
||||
.form-test-error {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,72 +4,70 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
v-if="displayVinNotFoundAlert"
|
||||
ref="alertVinNotFound"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedDifferentVehicleWidget"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<textboxQuestion
|
||||
id="license-plate-question-wrapper"
|
||||
v-model="licensePlate"
|
||||
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
inputId="license-plate-question"
|
||||
validationRules="license-plate-required" />
|
||||
<dropdownQuestion
|
||||
ref="state"
|
||||
v-model="licenseState"
|
||||
cmsWidgetName="StateQuestionWidget"
|
||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||
:options="stateOptions"
|
||||
disableAutoFill
|
||||
validationRules="state-required"
|
||||
class="mt-4 mb-2" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
v-if="displayVinNotFoundAlert"
|
||||
ref="alertVinNotFound"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedDifferentVehicleWidget"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="
|
||||
AlertMatchedTwoIdenticalYMMVehicleHeader
|
||||
"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<textboxQuestion
|
||||
id="license-plate-question-wrapper"
|
||||
v-model="licensePlate"
|
||||
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
inputId="license-plate-question"
|
||||
validationRules="license-plate-required" />
|
||||
<dropdownQuestion
|
||||
ref="state"
|
||||
v-model="licenseState"
|
||||
cmsWidgetName="StateQuestionWidget"
|
||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||
:options="stateOptions"
|
||||
disableAutoFill
|
||||
validationRules="state-required"
|
||||
class="mt-4 mb-2" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -83,7 +81,10 @@ import { useMainStore } from '@/store';
|
|||
import errorMessages from '@/constants/error-messages';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import { defineRule, Form } from 'vee-validate';
|
||||
import { getDamageString, isGlassAvailableForCarId } from '@/helpers/damage-helper.js';
|
||||
import {
|
||||
getDamageString,
|
||||
isGlassAvailableForCarId,
|
||||
} from '@/helpers/damage-helper.js';
|
||||
import routerParams from '@/router/router-constants/router-params.js';
|
||||
import states from '@/constants/states';
|
||||
|
||||
|
|
@ -100,7 +101,10 @@ import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-qu
|
|||
import alert from '@/ux-components/alert/alert.vue';
|
||||
|
||||
// Define Validation Rules
|
||||
defineRule('license-plate-required', required(errorMessages.LICENSE_PLATE_REQUIRED));
|
||||
defineRule(
|
||||
'license-plate-required',
|
||||
required(errorMessages.LICENSE_PLATE_REQUIRED)
|
||||
);
|
||||
defineRule('state-required', required(errorMessages.STATE_REQUIRED));
|
||||
|
||||
export default {
|
||||
|
|
@ -114,7 +118,7 @@ export default {
|
|||
vehicleBanner,
|
||||
textboxQuestion,
|
||||
dropdownQuestion,
|
||||
alert
|
||||
alert,
|
||||
},
|
||||
mixins: [baseFormMixin, vinPagesMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -125,8 +129,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -149,7 +153,7 @@ export default {
|
|||
isCarIdDifferent: false,
|
||||
customAlertData: {},
|
||||
isSelectedGlassAvailableForVehicle: true,
|
||||
forwardButtonCarStyle: ''
|
||||
forwardButtonCarStyle: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -163,10 +167,12 @@ export default {
|
|||
const vinYmmFound =
|
||||
// eslint-disable-next-line max-len
|
||||
`${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected =
|
||||
`${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'BodyText')
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedDifferentVehicleWidget',
|
||||
'BodyText'
|
||||
)
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmFound}', vinYmmFound)
|
||||
.replaceAll('{custom:vinYmmExpected}', vinYmmExpected);
|
||||
|
|
@ -185,7 +191,10 @@ export default {
|
|||
// eslint-disable-next-line max-len
|
||||
`${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget', 'BodyText')
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'BodyText'
|
||||
)
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmsFound}', vinYmmsFound)
|
||||
.replaceAll('{custom:vinYmmsExpected}', vinYmmsExpected);
|
||||
|
|
@ -194,23 +203,26 @@ export default {
|
|||
const vinYmmFound =
|
||||
// eslint-disable-next-line max-len
|
||||
`${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected =
|
||||
`${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase());
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
|
||||
},
|
||||
stateOptions: {
|
||||
get() {
|
||||
return states;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
licensePlate() {
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('SiteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
},
|
||||
registrationZipCode() {
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
}
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('SiteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
|
|
@ -221,7 +233,8 @@ export default {
|
|||
return useMainStore().order.vehicle.carId !== null;
|
||||
},
|
||||
loadDefaultsFromStore() {
|
||||
this.customerQuestions = this.mainStore.customerData.addressQuestions.state;
|
||||
this.customerQuestions =
|
||||
this.mainStore.customerData.addressQuestions.state;
|
||||
},
|
||||
attachCustomEvents() {
|
||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||
|
|
@ -238,14 +251,17 @@ export default {
|
|||
this.resetWarningsAndErrors();
|
||||
|
||||
// Lookup VIN
|
||||
const vinLookupResponse = await useMainStore().lookupVinByPlate(this.licensePlate, this.licenseState);
|
||||
const vinLookupResponse = await useMainStore().lookupVinByPlate(
|
||||
this.licensePlate,
|
||||
this.licenseState
|
||||
);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'vinLookupResponse',
|
||||
promise: vinLookupResponse
|
||||
}
|
||||
promise: vinLookupResponse,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -265,8 +281,8 @@ export default {
|
|||
vehicleFromLookup.carId !== useMainStore().order.vehicle.carId;
|
||||
// Handle changing car
|
||||
if (
|
||||
this.isCarIdDifferent
|
||||
&& vehicleFromLookup.carId !== this.previouslyEnteredCarId
|
||||
this.isCarIdDifferent &&
|
||||
vehicleFromLookup.carId !== this.previouslyEnteredCarId
|
||||
) {
|
||||
// Display Alert
|
||||
this.previouslyEnteredCarId = vehicleFromLookup.carId;
|
||||
|
|
@ -279,24 +295,30 @@ export default {
|
|||
this.displayMatchedDifferentVehicleAlert = true;
|
||||
}
|
||||
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vehicleFromLookup.carId);
|
||||
this.isSelectedGlassAvailableForVehicle =
|
||||
await isGlassAvailableForCarId(vehicleFromLookup.carId);
|
||||
|
||||
// Update button "Continue with..."
|
||||
this.$refs.siteFooter
|
||||
// eslint-disable-next-line max-len
|
||||
.updateButtonText(`Continue with ${vehicleFromLookup.year} ${vehicleFromLookup.make} ${vehicleFromLookup.model} ${this.forwardButtonCarStyle}`);
|
||||
.updateButtonText(
|
||||
`Continue with ${vehicleFromLookup.year} ${vehicleFromLookup.make} ${vehicleFromLookup.model} ${this.forwardButtonCarStyle}`
|
||||
);
|
||||
return this.$refs.siteFooter.removeLoader();
|
||||
}
|
||||
|
||||
// Save vehicle, license plate, and registration information
|
||||
await useMainStore().saveRegistrationLicensePlateLookup(
|
||||
{
|
||||
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||
vehicleInfo: Object.assign(vinLookupResponse.data.vehicle, { vin: vinLookupResponse.data.vin }),
|
||||
isSelectedGlassAvailableForVehicle:
|
||||
this.isSelectedGlassAvailableForVehicle,
|
||||
vehicleInfo: Object.assign(vinLookupResponse.data.vehicle, {
|
||||
vin: vinLookupResponse.data.vin,
|
||||
}),
|
||||
registrationInfo: {
|
||||
licensePlate: this.licensePlate,
|
||||
state: this.licenseState
|
||||
}
|
||||
state: this.licenseState,
|
||||
},
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
@ -307,7 +329,10 @@ export default {
|
|||
// If a different vehicle is found than the one entered and the selected glass is
|
||||
// not available for that vehicle then navigate back to "vehicle-damage"
|
||||
// display vehicle changed alert on that page.
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
!this.isSelectedGlassAvailableForVehicle
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
|
|
@ -321,8 +346,8 @@ export default {
|
|||
resetWarningsAndErrors() {
|
||||
this.displayVinNotFoundAlert = false;
|
||||
this.displayMatchedDifferentVehicleAlert = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
<template>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<questionsPageLayout
|
||||
id="molding-question-wrapper"
|
||||
ref="questionsPageLayout"
|
||||
v-model="selectedAnswers"
|
||||
isRequired
|
||||
:isMetaValid="meta.valid"
|
||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||
:questionsData="questionsData"
|
||||
:validationRules="rules.optionRequired"
|
||||
:index="currentGlassIndex"
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@backClick="navigateBackByVehicleQuestions" />
|
||||
</Form>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<questionsPageLayout
|
||||
id="molding-question-wrapper"
|
||||
ref="questionsPageLayout"
|
||||
v-model="selectedAnswers"
|
||||
isRequired
|
||||
:isMetaValid="meta.valid"
|
||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||
:questionsData="questionsData"
|
||||
:validationRules="rules.optionRequired"
|
||||
:index="currentGlassIndex"
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@backClick="navigateBackByVehicleQuestions" />
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
|
|
@ -38,7 +38,7 @@ export default {
|
|||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
questionsPageLayout
|
||||
questionsPageLayout,
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -48,8 +48,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -64,8 +64,8 @@ export default {
|
|||
selectedAnswers: {},
|
||||
currentGlassIndex: 0,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -76,23 +76,34 @@ export default {
|
|||
);
|
||||
},
|
||||
AlertFewMoreQuestionsCopy() {
|
||||
return this.getCmsContent('AdditionalPartsQuestionsAlert', 'BodyText');
|
||||
return this.getCmsContent(
|
||||
'AdditionalPartsQuestionsAlert',
|
||||
'BodyText'
|
||||
);
|
||||
},
|
||||
partsOrQuestionsData() {
|
||||
return useMainStore().pageData(issPageValues.MOLDING_QUESTIONS)
|
||||
.partsOrQuestions;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getInitialQuestionData();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
const moldingQuestionsFromPageData = useMainStore().pageData(issPageValues.MOLDING_QUESTIONS);
|
||||
const moldingQuestionsFromPageData = useMainStore().pageData(
|
||||
issPageValues.MOLDING_QUESTIONS
|
||||
);
|
||||
return (
|
||||
// has childPartQuestions array and has glassName not null
|
||||
moldingQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName)
|
||||
&& moldingQuestionsFromPageData.partsOrQuestions.some((glass) => glass.parts?.some((part) => part?.childPartQuestions?.length > 0))
|
||||
// has childPartQuestions array and has glassName not null
|
||||
moldingQuestionsFromPageData?.partsOrQuestions?.some(
|
||||
(part) => part?.glassName
|
||||
) &&
|
||||
moldingQuestionsFromPageData.partsOrQuestions.some((glass) =>
|
||||
glass.parts?.some(
|
||||
(part) => part?.childPartQuestions?.length > 0
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
getInitialQuestionData() {
|
||||
|
|
@ -134,41 +145,44 @@ export default {
|
|||
glassName: glass.glassName,
|
||||
partNum: glass.answerData.answerResult,
|
||||
answeredQuestions: glass.answerData.answeredQuestions,
|
||||
isSuppressedPart: glass.isSuppressedPart
|
||||
isSuppressedPart: glass.isSuppressedPart,
|
||||
}));
|
||||
// clear out answerData for future page loads; must occur prior to store save
|
||||
this.questionsData.forEach((glass) => {
|
||||
glass.answerData = {};
|
||||
});
|
||||
// save to store as order.damage.moldingQuestionArrays (array)
|
||||
await this.mainStore.saveMoldingQuestionAnswers(questionAnswersArray);
|
||||
await this.mainStore.saveMoldingQuestionAnswers(
|
||||
questionAnswersArray
|
||||
);
|
||||
|
||||
// get parts from the questionAnswers
|
||||
const partsOrQuestions = this.partsOrQuestionsData;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const answer of questionAnswersArray) {
|
||||
partsOrQuestions.find((partOrQuestion) => (
|
||||
partOrQuestion.glassLocation === answer.glassLocation
|
||||
&& partOrQuestion.glassName === answer.glassName
|
||||
)).parts[0].childParts = [
|
||||
partsOrQuestions.find(
|
||||
(partOrQuestion) =>
|
||||
partOrQuestion.glassLocation === answer.glassLocation &&
|
||||
partOrQuestion.glassName === answer.glassName
|
||||
).parts[0].childParts = [
|
||||
{
|
||||
partNumber: answer.partNum
|
||||
}
|
||||
partNumber: answer.partNum,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
this.navigateForward(partsOrQuestions, null);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#molding-question-wrapper p.text-body.small {
|
||||
margin-bottom: 0 !important; // Overrides extra margin-bottom on alert body text
|
||||
margin-bottom: 0 !important; // Overrides extra margin-bottom on alert body text
|
||||
}
|
||||
|
||||
#molding-question-wrapper .form-test-error {
|
||||
margin-top: 0 !important; // Overrides extra margin-top on error message text
|
||||
margin-top: 0 !important; // Overrides extra margin-top on error message text
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@
|
|||
overnightDropOffWidgetName="AddToCalendar_OvernightDropOff"
|
||||
allDayDropOffWidgetName="AddToCalendar_AllDayDropOff"
|
||||
sameDayDropOffWidgetName="AddToCalendar_SameDayDropOff"
|
||||
:serviceLocationFullAddress="serviceLocationFullAddress"
|
||||
:serviceLocationFullAddress="
|
||||
serviceLocationFullAddress
|
||||
"
|
||||
:providerFullAddress="providerFullAddress"
|
||||
:appointmentType="appointmentType"
|
||||
:scheduleDate="appointmentDate"
|
||||
|
|
@ -40,12 +42,10 @@
|
|||
:scheduleEndTime="appointmentEndTime" />
|
||||
<div
|
||||
class="appointment-text text-center lh-base"
|
||||
v-html="appointmentWordingText">
|
||||
</div>
|
||||
v-html="appointmentWordingText"></div>
|
||||
<div
|
||||
class="appointment-text text-center lh-base mt-2"
|
||||
v-html="appointmentWordingText2">
|
||||
</div>
|
||||
v-html="appointmentWordingText2"></div>
|
||||
</div>
|
||||
<hr class="mb-0" />
|
||||
<div>
|
||||
|
|
@ -84,15 +84,20 @@ import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-c
|
|||
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage, processIfStatements } from '@/helpers/cms-content-helper';
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
processIfStatements,
|
||||
} from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import { get12HourTimeFormat,
|
||||
import {
|
||||
get12HourTimeFormat,
|
||||
get12HourTimeMobileFormat,
|
||||
convertDateStringToDate,
|
||||
getDisplayTextForDurationLength } from '@/helpers/date-helper.js';
|
||||
getDisplayTextForDurationLength,
|
||||
} from '@/helpers/date-helper.js';
|
||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||
import applicationConfig from '@/constants/application-config';
|
||||
|
|
@ -106,7 +111,7 @@ export default {
|
|||
vehicleBanner,
|
||||
siteFooter,
|
||||
addToCalendar,
|
||||
cartDropdown
|
||||
cartDropdown,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -118,10 +123,9 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
|
|
@ -142,9 +146,18 @@ export default {
|
|||
return this.mainStore.issConfig.successReturnURL;
|
||||
},
|
||||
confirmationEmailText() {
|
||||
return this.getCmsContent('EmailConfirmationWordingWidget', 'BodyText')
|
||||
?.replaceAll('{custom:CUSTOMER_PORTAL_URL}', applicationConfig.CUSTOMER_PORTAL_URL)
|
||||
?.replaceAll('{custom:CUSTOMER_PORTAL_LOGIN_TOKEN}', this.submittedOrder.customerPortalLoginToken)
|
||||
return this.getCmsContent(
|
||||
'EmailConfirmationWordingWidget',
|
||||
'BodyText'
|
||||
)
|
||||
?.replaceAll(
|
||||
'{custom:CUSTOMER_PORTAL_URL}',
|
||||
applicationConfig.CUSTOMER_PORTAL_URL
|
||||
)
|
||||
?.replaceAll(
|
||||
'{custom:CUSTOMER_PORTAL_LOGIN_TOKEN}',
|
||||
this.submittedOrder.customerPortalLoginToken
|
||||
)
|
||||
?.replaceAll('<', '<')
|
||||
?.replaceAll('>', '>');
|
||||
},
|
||||
|
|
@ -173,11 +186,13 @@ export default {
|
|||
return dateObject.toLocaleDateString('en-us', {
|
||||
weekday: 'long',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
day: 'numeric',
|
||||
});
|
||||
},
|
||||
appointmentTimeFormatted() {
|
||||
const formattedTime = this.formatAppointmentTime(this.appointmentType);
|
||||
const formattedTime = this.formatAppointmentTime(
|
||||
this.appointmentType
|
||||
);
|
||||
return formattedTime;
|
||||
},
|
||||
mobileWordingText() {
|
||||
|
|
@ -187,7 +202,10 @@ export default {
|
|||
return this.getCmsContent('MobileWordingWidget', 'BodyText2');
|
||||
},
|
||||
dropOffAndInShopWordingText() {
|
||||
return this.getCmsContent('DropOffAndInShopWordingWidget', 'BodyText');
|
||||
return this.getCmsContent(
|
||||
'DropOffAndInShopWordingWidget',
|
||||
'BodyText'
|
||||
);
|
||||
},
|
||||
dropOffAndInShopWordingText2() {
|
||||
return this.getBodyText2FromCms('DropOffAndInShopWordingWidget');
|
||||
|
|
@ -209,13 +227,24 @@ export default {
|
|||
},
|
||||
serviceLocationFullAddress() {
|
||||
// eslint-disable-next-line max-len
|
||||
return `${this.serviceLocationAddress}, ${this.serviceLocationAddress2 ? `${this.serviceLocationAddress2},` : ''}<br/> ${this.serviceLocationCity}, ${this.serviceLocationState} ${this.serviceLocationZipCode}`;
|
||||
return `${this.serviceLocationAddress}, ${
|
||||
this.serviceLocationAddress2
|
||||
? `${this.serviceLocationAddress2},`
|
||||
: ''
|
||||
}<br/> ${this.serviceLocationCity}, ${this.serviceLocationState} ${
|
||||
this.serviceLocationZipCode
|
||||
}`;
|
||||
},
|
||||
providerAddress() {
|
||||
return toTitleCase(this.submittedOrder.serviceLocation.provider.address.streetAddress);
|
||||
return toTitleCase(
|
||||
this.submittedOrder.serviceLocation.provider.address
|
||||
.streetAddress
|
||||
);
|
||||
},
|
||||
providerCity() {
|
||||
return toTitleCase(this.submittedOrder.serviceLocation.provider.address.city);
|
||||
return toTitleCase(
|
||||
this.submittedOrder.serviceLocation.provider.address.city
|
||||
);
|
||||
},
|
||||
providerState() {
|
||||
return this.submittedOrder.serviceLocation.provider.address.state;
|
||||
|
|
@ -225,7 +254,9 @@ export default {
|
|||
},
|
||||
providerFullAddress() {
|
||||
// eslint-disable-next-line max-len
|
||||
return this.submittedOrder.serviceLocation?.provider?.address ? `${this.providerAddress},<br/> ${this.providerCity}, ${this.providerState} ${this.providerZipCode}` : '';
|
||||
return this.submittedOrder.serviceLocation?.provider?.address
|
||||
? `${this.providerAddress},<br/> ${this.providerCity}, ${this.providerState} ${this.providerZipCode}`
|
||||
: '';
|
||||
},
|
||||
appointmentWordingText() {
|
||||
switch (this.appointmentType) {
|
||||
|
|
@ -266,14 +297,24 @@ export default {
|
|||
}
|
||||
},
|
||||
mobileAppointment() {
|
||||
return this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
return (
|
||||
this.submittedOrder.serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE ||
|
||||
this.submittedOrder.serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
);
|
||||
},
|
||||
inShopAppointment() {
|
||||
return this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.IN_SHOP;
|
||||
return (
|
||||
this.submittedOrder.serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.IN_SHOP
|
||||
);
|
||||
},
|
||||
dropOffAppointment() {
|
||||
return this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF;
|
||||
return (
|
||||
this.submittedOrder.serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.DROP_OFF
|
||||
);
|
||||
},
|
||||
inShopAppointmentDuration() {
|
||||
const inshopDurationTime = getDisplayTextForDurationLength(
|
||||
|
|
@ -287,11 +328,13 @@ export default {
|
|||
},
|
||||
selectedVaps() {
|
||||
return this.submittedOrder.lineItems.vaps;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.carrierUrl) {
|
||||
this.$refs.siteFooter.updateButtonText(`Go back to ${this.carrierName}`);
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
`Go back to ${this.carrierName}`
|
||||
);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -304,57 +347,62 @@ export default {
|
|||
// Service Location
|
||||
const { serviceLocation } = useMainStore().order;
|
||||
const mobileReqs = !!(
|
||||
serviceLocation.address
|
||||
&& serviceLocation.city
|
||||
&& serviceLocation.state
|
||||
&& serviceLocation.zipCode
|
||||
serviceLocation.address &&
|
||||
serviceLocation.city &&
|
||||
serviceLocation.state &&
|
||||
serviceLocation.zipCode
|
||||
);
|
||||
|
||||
const providerLocation = serviceLocation.provider.address;
|
||||
const dropOffInShopReqs = !!(
|
||||
providerLocation.streetAddress
|
||||
&& providerLocation.city
|
||||
&& providerLocation.state
|
||||
&& providerLocation.zipCode
|
||||
providerLocation.streetAddress &&
|
||||
providerLocation.city &&
|
||||
providerLocation.state &&
|
||||
providerLocation.zipCode
|
||||
);
|
||||
|
||||
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
const isMobile =
|
||||
serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE ||
|
||||
serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
|
||||
const serviceLocationReqs =
|
||||
(isMobile && mobileReqs) || (!isMobile && dropOffInShopReqs);
|
||||
|
||||
// Insurance
|
||||
const isInsuranceSet = useMainStore().order.payment.isInsurance !== null;
|
||||
const isInsuranceSet =
|
||||
useMainStore().order.payment.isInsurance !== null;
|
||||
|
||||
// Schedule
|
||||
const { schedule } = useMainStore().order;
|
||||
const scheduleReqs = !!(
|
||||
schedule.date
|
||||
&& schedule.startTime
|
||||
&& schedule.endTime
|
||||
&& schedule.jobMaxMinutes
|
||||
&& schedule.jobMinMinutes
|
||||
schedule.date &&
|
||||
schedule.startTime &&
|
||||
schedule.endTime &&
|
||||
schedule.jobMaxMinutes &&
|
||||
schedule.jobMinMinutes
|
||||
);
|
||||
|
||||
// Contact Info
|
||||
const { contactInfo } = useMainStore().order;
|
||||
const contactInfoReqs = !!(
|
||||
contactInfo.firstName
|
||||
&& contactInfo.lastName
|
||||
&& contactInfo.servicePhone
|
||||
&& contactInfo.emailAddress
|
||||
contactInfo.firstName &&
|
||||
contactInfo.lastName &&
|
||||
contactInfo.servicePhone &&
|
||||
contactInfo.emailAddress
|
||||
);
|
||||
|
||||
// Payment
|
||||
const paymentMethodReqs = useMainStore().order.payment.isPayInAdvance === false;
|
||||
const paymentMethodReqs =
|
||||
useMainStore().order.payment.isPayInAdvance === false;
|
||||
|
||||
return (
|
||||
serviceLocationReqs
|
||||
&& isInsuranceSet
|
||||
&& scheduleReqs
|
||||
&& contactInfoReqs
|
||||
&& paymentMethodReqs
|
||||
serviceLocationReqs &&
|
||||
isInsuranceSet &&
|
||||
scheduleReqs &&
|
||||
contactInfoReqs &&
|
||||
paymentMethodReqs
|
||||
);
|
||||
},
|
||||
forwardButtonAction() {
|
||||
|
|
@ -365,11 +413,15 @@ export default {
|
|||
case AppointmentTypeStrings.MOBILE:
|
||||
case AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP:
|
||||
// eslint-disable-next-line max-len
|
||||
return `Between ${get12HourTimeMobileFormat(this.appointmentStartTime)} - ${get12HourTimeMobileFormat(this.appointmentEndTime)}`;
|
||||
return `Between ${get12HourTimeMobileFormat(
|
||||
this.appointmentStartTime
|
||||
)} - ${get12HourTimeMobileFormat(this.appointmentEndTime)}`;
|
||||
case AppointmentTypeStrings.DROP_OFF:
|
||||
return 'Drop off before 9:30 AM';
|
||||
case AppointmentTypeStrings.IN_SHOP:
|
||||
return `at ${get12HourTimeFormat(this.appointmentStartTime)}`;
|
||||
return `at ${get12HourTimeFormat(
|
||||
this.appointmentStartTime
|
||||
)}`;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -377,7 +429,11 @@ export default {
|
|||
processIfStatements,
|
||||
getBodyText2FromCms(cmsWidgetName) {
|
||||
const body2Text = this.getCmsContent(cmsWidgetName, 'BodyText2');
|
||||
return this.processIfStatements(body2Text, 'custom', this.getCustomValueFromString);
|
||||
return this.processIfStatements(
|
||||
body2Text,
|
||||
'custom',
|
||||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
|
|
@ -388,8 +444,8 @@ export default {
|
|||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export default {
|
|||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
questionsPageLayout
|
||||
questionsPageLayout,
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -48,8 +48,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -65,8 +65,8 @@ export default {
|
|||
selectedAnswers: {},
|
||||
currentGlassIndex: 0,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -78,11 +78,12 @@ export default {
|
|||
},
|
||||
pageData() {
|
||||
return useMainStore().pageData(issPageValues.PART_QUESTIONS);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// are there alreadyAnsweredQuestions?
|
||||
const alreadyAnsweredQuestions = useMainStore().damage.partQuestionAnswers;
|
||||
const alreadyAnsweredQuestions =
|
||||
useMainStore().damage.partQuestionAnswers;
|
||||
|
||||
this.questionsData = this.pageData.partsOrQuestions
|
||||
.filter((x) => x.partQuestions)
|
||||
|
|
@ -93,7 +94,11 @@ export default {
|
|||
// reset selectedAnswers for this glass
|
||||
this.selectedAnswers[glass.answerKey] = [];
|
||||
|
||||
const updatedGlass = this.setupInitialData(glass, index, alreadyAnsweredQuestions);
|
||||
const updatedGlass = this.setupInitialData(
|
||||
glass,
|
||||
index,
|
||||
alreadyAnsweredQuestions
|
||||
);
|
||||
|
||||
// Set up watch for each set of glass questions
|
||||
this.$watch(
|
||||
|
|
@ -111,19 +116,23 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
const partQuestionsFromPageData = useMainStore().pageData(issPageValues.PART_QUESTIONS);
|
||||
const partQuestionsFromPageData = useMainStore().pageData(
|
||||
issPageValues.PART_QUESTIONS
|
||||
);
|
||||
return (
|
||||
partQuestionsFromPageData
|
||||
&& Object.keys(partQuestionsFromPageData.partsOrQuestions).length > 0
|
||||
partQuestionsFromPageData &&
|
||||
Object.keys(partQuestionsFromPageData.partsOrQuestions).length >
|
||||
0
|
||||
);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
const questionAnswersArray = this.questionsData.map((glass) => ({
|
||||
glassLocation: glass.glassLocation,
|
||||
glassName: glass.glassName,
|
||||
result: (glass.answerData && glass.answerData.answerResult) || '',
|
||||
result:
|
||||
(glass.answerData && glass.answerData.answerResult) || '',
|
||||
answeredQuestions: glass.answerData?.answeredQuestions,
|
||||
isSuppressedPart: glass.isSuppressedPart
|
||||
isSuppressedPart: glass.isSuppressedPart,
|
||||
}));
|
||||
|
||||
// clear out answerData for future page loads; must occur prior to store save
|
||||
|
|
@ -143,7 +152,7 @@ export default {
|
|||
|
||||
// TODO KO delete for quote mvp
|
||||
this.navigateForward(glassPartsForStore, null);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@
|
|||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteHeader ref="siteHeader" cmsWidgetName="SiteHeaderWidget" />
|
||||
<vehicleBanner
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
|
|
@ -94,7 +92,7 @@ export default {
|
|||
cartDropdown,
|
||||
paymentMethodQuestion,
|
||||
alert,
|
||||
VehicleBanner
|
||||
VehicleBanner,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -107,20 +105,20 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'reviewDropdownData',
|
||||
promise: reviewDropdownPromise
|
||||
promise: reviewDropdownPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'wipers',
|
||||
promise: wipersPromise
|
||||
promise: wipersPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'rainDefense',
|
||||
promise: rainDefensePromise
|
||||
}
|
||||
promise: rainDefensePromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -130,12 +128,15 @@ export default {
|
|||
const unpricedVaps = [...resultMap.wipers, resultMap.rainDefense];
|
||||
|
||||
let hasBailedOut = false;
|
||||
const pricedVaps = await useMainStore().getPriceOrderItems(unpricedVaps)
|
||||
const pricedVaps = await useMainStore()
|
||||
.getPriceOrderItems(unpricedVaps)
|
||||
.catch((err) => {
|
||||
useMainStore().setBailout(bailoutMessage.pricingResponseError(
|
||||
unpricedVaps.map((li) => li.partNumber),
|
||||
{ code: err.code, message: err.message, data: err.data }
|
||||
));
|
||||
useMainStore().setBailout(
|
||||
bailoutMessage.pricingResponseError(
|
||||
unpricedVaps.map((li) => li.partNumber),
|
||||
{ code: err.code, message: err.message, data: err.data }
|
||||
)
|
||||
);
|
||||
hasBailedOut = true;
|
||||
next(`/?issPage=${issPageValues.BAILOUT_PAGE}`);
|
||||
});
|
||||
|
|
@ -144,7 +145,9 @@ export default {
|
|||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.updateFooterButtonText(vm.customCallToActionButtonCopy);
|
||||
vm.$refs.reviewDropdown.initializeComponent(resultMap.reviewDropdownData);
|
||||
vm.$refs.reviewDropdown.initializeComponent(
|
||||
resultMap.reviewDropdownData
|
||||
);
|
||||
vm.storeAvailableVaps(pricedVaps ?? []);
|
||||
});
|
||||
}
|
||||
|
|
@ -153,8 +156,8 @@ export default {
|
|||
return {
|
||||
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -171,106 +174,115 @@ export default {
|
|||
}
|
||||
},
|
||||
displayPayInAdvanceAlert() {
|
||||
return (
|
||||
this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT]
|
||||
);
|
||||
return this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT];
|
||||
},
|
||||
isPayInAdvanceDisabled() {
|
||||
return useMainStore().isUnverified;
|
||||
},
|
||||
paymentMethod() {
|
||||
return this.paymentMethodInternalModel;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
customCallToActionButtonCopy(newValue) {
|
||||
this.updateFooterButtonText(newValue);
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// Vehicle
|
||||
const { vehicle } = useMainStore().order;
|
||||
const vehicleReqs = !!(vehicle.year && vehicle.make && vehicle.model && vehicle.style);
|
||||
const vehicleReqs = !!(
|
||||
vehicle.year &&
|
||||
vehicle.make &&
|
||||
vehicle.model &&
|
||||
vehicle.style
|
||||
);
|
||||
|
||||
// Damage
|
||||
const { isRepair, numberOfChips, glassToReplace } = useMainStore().order.damage;
|
||||
const { isRepair, numberOfChips, glassToReplace } =
|
||||
useMainStore().order.damage;
|
||||
const damageReqs = !!(
|
||||
(isRepair && numberOfChips)
|
||||
|| (!isRepair && glassToReplace?.length)
|
||||
(isRepair && numberOfChips) ||
|
||||
(!isRepair && glassToReplace?.length)
|
||||
);
|
||||
|
||||
// Service Package
|
||||
const { lineItems } = useMainStore().order;
|
||||
const packageReqs = !!(
|
||||
(isRepair || lineItems.glassParts)
|
||||
&& lineItems.supportingItems
|
||||
(isRepair || lineItems.glassParts) &&
|
||||
lineItems.supportingItems
|
||||
);
|
||||
|
||||
// Service Location
|
||||
const { serviceLocation } = useMainStore().order;
|
||||
const mobileReqs = !!(
|
||||
serviceLocation.address
|
||||
&& serviceLocation.city
|
||||
&& serviceLocation.state
|
||||
&& serviceLocation.zipCode
|
||||
serviceLocation.address &&
|
||||
serviceLocation.city &&
|
||||
serviceLocation.state &&
|
||||
serviceLocation.zipCode
|
||||
);
|
||||
|
||||
const providerLocation = serviceLocation.provider.address;
|
||||
const dropOffInshopReqs = !!(
|
||||
providerLocation.streetAddress
|
||||
&& providerLocation.city
|
||||
&& providerLocation.state
|
||||
&& providerLocation.zipCode
|
||||
providerLocation.streetAddress &&
|
||||
providerLocation.city &&
|
||||
providerLocation.state &&
|
||||
providerLocation.zipCode
|
||||
);
|
||||
|
||||
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
const isMobile =
|
||||
serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE ||
|
||||
serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
const serviceLocationReqs =
|
||||
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
||||
|
||||
// Schedule
|
||||
const { date, startTime, endTime, jobMaxMinutes, jobMinMinutes } = useMainStore().order.schedule;
|
||||
const { date, startTime, endTime, jobMaxMinutes, jobMinMinutes } =
|
||||
useMainStore().order.schedule;
|
||||
const scheduleReqs = !!(
|
||||
date
|
||||
&& startTime
|
||||
&& endTime
|
||||
&& jobMaxMinutes
|
||||
&& jobMinMinutes
|
||||
date &&
|
||||
startTime &&
|
||||
endTime &&
|
||||
jobMaxMinutes &&
|
||||
jobMinMinutes
|
||||
);
|
||||
|
||||
// Customer
|
||||
const { firstName, lastName, emailAddress } = useMainStore().order.customer;
|
||||
const customerReqs = !!(
|
||||
firstName
|
||||
&& lastName
|
||||
&& emailAddress
|
||||
);
|
||||
const { firstName, lastName, emailAddress } =
|
||||
useMainStore().order.customer;
|
||||
const customerReqs = !!(firstName && lastName && emailAddress);
|
||||
|
||||
// Contact Info
|
||||
const { contactInfo } = useMainStore().order;
|
||||
const contactInfoReqs = !!(
|
||||
contactInfo.firstName
|
||||
&& contactInfo.lastName
|
||||
&& contactInfo.servicePhone
|
||||
&& contactInfo.emailAddress
|
||||
contactInfo.firstName &&
|
||||
contactInfo.lastName &&
|
||||
contactInfo.servicePhone &&
|
||||
contactInfo.emailAddress
|
||||
);
|
||||
|
||||
return (
|
||||
vehicleReqs
|
||||
&& damageReqs
|
||||
&& packageReqs
|
||||
&& serviceLocationReqs
|
||||
&& scheduleReqs
|
||||
&& customerReqs
|
||||
&& contactInfoReqs
|
||||
vehicleReqs &&
|
||||
damageReqs &&
|
||||
packageReqs &&
|
||||
serviceLocationReqs &&
|
||||
scheduleReqs &&
|
||||
customerReqs &&
|
||||
contactInfoReqs
|
||||
);
|
||||
},
|
||||
getPaymentMethodFromStore() {
|
||||
const { payInAdvanceType } = useMainStore().order.payment;
|
||||
const isPayInAdvance = useMainStore().order.payment.isPayInAdvance && !!payInAdvanceType;
|
||||
const isPayInAdvance =
|
||||
useMainStore().order.payment.isPayInAdvance &&
|
||||
!!payInAdvanceType;
|
||||
|
||||
return isPayInAdvance ? payInAdvanceType : paymentMethods.PAY_AT_TIME_OF_SERVICE;
|
||||
return isPayInAdvance
|
||||
? payInAdvanceType
|
||||
: paymentMethods.PAY_AT_TIME_OF_SERVICE;
|
||||
},
|
||||
updateFooterButtonText(newValue) {
|
||||
this.$refs.siteFooter.updateButtonText(newValue);
|
||||
|
|
@ -292,8 +304,8 @@ export default {
|
|||
},
|
||||
storeAvailableVaps(vaps) {
|
||||
useMainStore().order.availableVaps = vaps;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
<template>
|
||||
<Form>
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2 payment">
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<alert
|
||||
v-if="displayPayInAdvanceCreditCardAlert"
|
||||
name="payInAdvanceCreditCardErrorAlert"
|
||||
|
|
@ -51,7 +55,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="shouldBlockInteraction"
|
||||
class="ui-block"
|
||||
|
|
@ -65,22 +68,10 @@
|
|||
:target="isPaypal ? '_top' : 'card-frame'"
|
||||
method="POST"
|
||||
:action="checkoutUrl">
|
||||
<input
|
||||
type="hidden"
|
||||
name="paymentType"
|
||||
:value="paymentType" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgSessionId"
|
||||
:value="authToken" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgAuthToken"
|
||||
:value="authToken" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgSignaturePublic"
|
||||
:value="authSignature" />
|
||||
<input type="hidden" name="paymentType" :value="paymentType" />
|
||||
<input type="hidden" name="sgSessionId" :value="authToken" />
|
||||
<input type="hidden" name="sgAuthToken" :value="authToken" />
|
||||
<input type="hidden" name="sgSignaturePublic" :value="authSignature" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgSignatureStartDate"
|
||||
|
|
@ -93,34 +84,13 @@
|
|||
type="hidden"
|
||||
name="sge_commerce_indicator_isinternet"
|
||||
value="true" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sghopsource"
|
||||
value="Safelite.com" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgHtmlStyle"
|
||||
value="ResourceSafeliteHtml" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgErrorMessagesEmbedded"
|
||||
value="true" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgNoKeystrokeProcessing"
|
||||
value="false" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="maskCharacter"
|
||||
value="*" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="styleSheetCode"
|
||||
:value="dynamicCSSUrl" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="styleSheetCode2"
|
||||
:value="dynamicHopCSSUrl" />
|
||||
<input type="hidden" name="sghopsource" value="Safelite.com" />
|
||||
<input type="hidden" name="sgHtmlStyle" value="ResourceSafeliteHtml" />
|
||||
<input type="hidden" name="sgErrorMessagesEmbedded" value="true" />
|
||||
<input type="hidden" name="sgNoKeystrokeProcessing" value="false" />
|
||||
<input type="hidden" name="maskCharacter" value="*" />
|
||||
<input type="hidden" name="styleSheetCode" :value="dynamicCSSUrl" />
|
||||
<input type="hidden" name="styleSheetCode2" :value="dynamicHopCSSUrl" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgReceiptResponseURL"
|
||||
|
|
@ -133,102 +103,33 @@
|
|||
type="hidden"
|
||||
name="sgErrorResponseURL"
|
||||
:value="payInAdvanceResponseUrl" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgheaderline1"
|
||||
:value="getHeaderLine1" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgHeader1subtitle"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgheaderline2"
|
||||
:value="getHeaderLine2" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgheaderline3"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgheaderline4"
|
||||
value="" />
|
||||
<input type="hidden" name="sgheaderline1" :value="getHeaderLine1" />
|
||||
<input type="hidden" name="sgHeader1subtitle" value="" />
|
||||
<input type="hidden" name="sgheaderline2" :value="getHeaderLine2" />
|
||||
<input type="hidden" name="sgheaderline3" value="" />
|
||||
<input type="hidden" name="sgheaderline4" value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgheaderline5"
|
||||
value="*Required information" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_firstName"
|
||||
:value="firstName" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_firstNameShow"
|
||||
value="true" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sghopmiddleInitialShow"
|
||||
value="false" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_lastName"
|
||||
:value="lastName" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_lastNameShow"
|
||||
value="true" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_street1"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_street2"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_city"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_state"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_postalCode"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_postalCodeShow"
|
||||
value="true" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_postalCodeEnable"
|
||||
value="true" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgLabelPostalCode"
|
||||
value="Billing ZIP" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgtotalamount"
|
||||
:value="displayAmount" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="totalAmountDecimal"
|
||||
:value="totalAmount" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="lineItems"
|
||||
:value="payInAdvanceLineItems" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgdiscountstrikethruamount"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="callerDisplayText"
|
||||
value="" />
|
||||
<input type="hidden" name="billTo_firstName" :value="firstName" />
|
||||
<input type="hidden" name="billTo_firstNameShow" value="true" />
|
||||
<input type="hidden" name="sghopmiddleInitialShow" value="false" />
|
||||
<input type="hidden" name="billTo_lastName" :value="lastName" />
|
||||
<input type="hidden" name="billTo_lastNameShow" value="true" />
|
||||
<input type="hidden" name="billTo_street1" value="" />
|
||||
<input type="hidden" name="billTo_street2" value="" />
|
||||
<input type="hidden" name="billTo_city" value="" />
|
||||
<input type="hidden" name="billTo_state" value="" />
|
||||
<input type="hidden" name="billTo_postalCode" value="" />
|
||||
<input type="hidden" name="billTo_postalCodeShow" value="true" />
|
||||
<input type="hidden" name="billTo_postalCodeEnable" value="true" />
|
||||
<input type="hidden" name="sgLabelPostalCode" value="Billing ZIP" />
|
||||
<input type="hidden" name="sgtotalamount" :value="displayAmount" />
|
||||
<input type="hidden" name="totalAmountDecimal" :value="totalAmount" />
|
||||
<input type="hidden" name="lineItems" :value="payInAdvanceLineItems" />
|
||||
<input type="hidden" name="sgdiscountstrikethruamount" value="" />
|
||||
<input type="hidden" name="callerDisplayText" value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgtermsofusedisplaytext"
|
||||
|
|
@ -261,38 +162,14 @@
|
|||
type="hidden"
|
||||
name="sgErrorMessageTimeOut"
|
||||
value="For your security, this transaction has been timed out." />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgLabelCardNumber"
|
||||
value="" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgLabelAddressLine1"
|
||||
:value="address1" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgLabelAddressLine2"
|
||||
:value="address2" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgLabelCity"
|
||||
:value="city" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgLabelState"
|
||||
:value="state" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgCtu"
|
||||
:value="ctu" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgWorkOrder"
|
||||
:value="workOrderNumber" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgEmailAddress"
|
||||
:value="emailAddress" />
|
||||
<input type="hidden" name="sgLabelCardNumber" value="" />
|
||||
<input type="hidden" name="sgLabelAddressLine1" :value="address1" />
|
||||
<input type="hidden" name="sgLabelAddressLine2" :value="address2" />
|
||||
<input type="hidden" name="sgLabelCity" :value="city" />
|
||||
<input type="hidden" name="sgLabelState" :value="state" />
|
||||
<input type="hidden" name="sgCtu" :value="ctu" />
|
||||
<input type="hidden" name="sgWorkOrder" :value="workOrderNumber" />
|
||||
<input type="hidden" name="sgEmailAddress" :value="emailAddress" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="paypalInvoiceNumber"
|
||||
|
|
@ -313,30 +190,12 @@
|
|||
type="hidden"
|
||||
name="sgCCTimeoutURL"
|
||||
:value="payInAdvanceCancelUrl" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="sgTransactionType"
|
||||
value="authorization" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="amount"
|
||||
:value="totalAmount" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ctu"
|
||||
:value="ctu" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="orderNumber"
|
||||
:value="workOrderNumber" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="billTo_email"
|
||||
:value="emailAddress" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="useDecisionManager"
|
||||
value="True" />
|
||||
<input type="hidden" name="sgTransactionType" value="authorization" />
|
||||
<input type="hidden" name="amount" :value="totalAmount" />
|
||||
<input type="hidden" name="ctu" :value="ctu" />
|
||||
<input type="hidden" name="orderNumber" :value="workOrderNumber" />
|
||||
<input type="hidden" name="billTo_email" :value="emailAddress" />
|
||||
<input type="hidden" name="useDecisionManager" value="True" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="correlationId"
|
||||
|
|
@ -345,38 +204,17 @@
|
|||
type="hidden"
|
||||
name="sgErrorMessageCard_CVN"
|
||||
value="Please enter a valid CVV" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ship_to_address_line1"
|
||||
:value="address1" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ship_to_address_line2"
|
||||
:value="address2" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ship_to_address_city"
|
||||
:value="city" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ship_to_address_state"
|
||||
:value="state" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ship_to_address_country"
|
||||
value="US" />
|
||||
<input type="hidden" name="ship_to_address_line1" :value="address1" />
|
||||
<input type="hidden" name="ship_to_address_line2" :value="address2" />
|
||||
<input type="hidden" name="ship_to_address_city" :value="city" />
|
||||
<input type="hidden" name="ship_to_address_state" :value="state" />
|
||||
<input type="hidden" name="ship_to_address_country" value="US" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ship_to_address_postal_code"
|
||||
:value="zipCode" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="ship_to_phone"
|
||||
:value="phoneNumber" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="calling_application"
|
||||
value="ISSNextGen" />
|
||||
<input type="hidden" name="ship_to_phone" :value="phoneNumber" />
|
||||
<input type="hidden" name="calling_application" value="ISSNextGen" />
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
|
|
@ -395,11 +233,14 @@ import { useMainStore } from '@/store';
|
|||
import iframeResize from 'iframe-resizer/js/iframeResizer.js';
|
||||
import externalUrls from '@/router/router-constants/externalUrl-values.js';
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
import { hopPaymentMethods, paymentMethods } from '@/constants/payment-method-constants.js';
|
||||
import {
|
||||
hopPaymentMethods,
|
||||
paymentMethods,
|
||||
} from '@/constants/payment-method-constants.js';
|
||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
||||
import queryStrings from '@/constants/query-strings';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import cartDropdown from "@/iss-components/cart-dropdown/cart-dropdown.vue";
|
||||
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
|
||||
|
||||
export default {
|
||||
name: 'payment-page',
|
||||
|
|
@ -409,7 +250,7 @@ export default {
|
|||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
alert
|
||||
alert,
|
||||
},
|
||||
directives: {
|
||||
resize: {
|
||||
|
|
@ -420,26 +261,27 @@ export default {
|
|||
},
|
||||
unmounted(el) {
|
||||
el.iFrameResizer.removeListeners();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
const paymentSignaturePromise = await useMainStore().getPaymentSignature();
|
||||
const paymentSignaturePromise =
|
||||
await useMainStore().getPaymentSignature();
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'paymentSignature',
|
||||
promise: paymentSignaturePromise
|
||||
}
|
||||
promise: paymentSignaturePromise,
|
||||
},
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
|
|
@ -489,7 +331,7 @@ export default {
|
|||
totalAmount: this.getAmountDue(),
|
||||
displayAmount: this.getDisplayAmountDue(),
|
||||
payInAdvanceLineItems: '',
|
||||
shouldBlockInteraction: false
|
||||
shouldBlockInteraction: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -511,13 +353,19 @@ export default {
|
|||
},
|
||||
getHeaderLine1() {
|
||||
if (!this.isPaypal) {
|
||||
return this.getCmsContent('PayInAdvanceHeaderLine1', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
return this.getCmsContent(
|
||||
'PayInAdvanceHeaderLine1',
|
||||
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
||||
);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
getHeaderLine2() {
|
||||
if (!this.isPaypal) {
|
||||
return this.getCmsContent('PayInAdvanceHeaderLine2', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
return this.getCmsContent(
|
||||
'PayInAdvanceHeaderLine2',
|
||||
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
||||
);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
|
@ -532,70 +380,75 @@ export default {
|
|||
},
|
||||
displayPayInAdvanceAfterPayAlert() {
|
||||
return this.displayPayInAdvanceAlert(paymentMethods.AFTERPAY);
|
||||
}
|
||||
},
|
||||
},
|
||||
methods:
|
||||
{
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// Line Items
|
||||
const packageReqs = !!useMainStore().order.lineItems.supportingItems;
|
||||
const packageReqs =
|
||||
!!useMainStore().order.lineItems.supportingItems;
|
||||
|
||||
// Service Location
|
||||
const { serviceLocation } = useMainStore().order;
|
||||
const mobileReqs = !!(
|
||||
serviceLocation.address
|
||||
&& serviceLocation.city
|
||||
&& serviceLocation.state
|
||||
&& serviceLocation.zipCode
|
||||
serviceLocation.address &&
|
||||
serviceLocation.city &&
|
||||
serviceLocation.state &&
|
||||
serviceLocation.zipCode
|
||||
);
|
||||
|
||||
const providerLocation = serviceLocation.provider.address;
|
||||
const dropOffInshopReqs = !!(
|
||||
providerLocation.streetAddress
|
||||
&& providerLocation.city
|
||||
&& providerLocation.state
|
||||
&& providerLocation.zipCode
|
||||
providerLocation.streetAddress &&
|
||||
providerLocation.city &&
|
||||
providerLocation.state &&
|
||||
providerLocation.zipCode
|
||||
);
|
||||
|
||||
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
const isMobile =
|
||||
serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE ||
|
||||
serviceLocation.appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
|
||||
const serviceLocationReqs =
|
||||
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
||||
|
||||
// Insurance
|
||||
const isInsuranceSet = useMainStore().order.payment.isInsurance !== null;
|
||||
const isInsuranceSet =
|
||||
useMainStore().order.payment.isInsurance !== null;
|
||||
|
||||
// Schedule
|
||||
const { schedule } = useMainStore().order;
|
||||
const scheduleReqs = !!(
|
||||
schedule.date
|
||||
&& schedule.startTime
|
||||
&& schedule.endTime
|
||||
&& schedule.jobMaxMinutes
|
||||
&& schedule.jobMinMinutes
|
||||
schedule.date &&
|
||||
schedule.startTime &&
|
||||
schedule.endTime &&
|
||||
schedule.jobMaxMinutes &&
|
||||
schedule.jobMinMinutes
|
||||
);
|
||||
|
||||
// Contact Info
|
||||
const { contactInfo } = useMainStore().order;
|
||||
const contactInfoReqs = !!(
|
||||
contactInfo.firstName
|
||||
&& contactInfo.lastName
|
||||
&& contactInfo.servicePhone
|
||||
&& contactInfo.emailAddress
|
||||
contactInfo.firstName &&
|
||||
contactInfo.lastName &&
|
||||
contactInfo.servicePhone &&
|
||||
contactInfo.emailAddress
|
||||
);
|
||||
|
||||
const paymentMethodReqs =
|
||||
useMainStore().order.payment.isPayInAdvance !== null
|
||||
&& (useMainStore().order.payment.isPayInAdvance || !!useMainStore().order.payment.payInAdvanceType);
|
||||
useMainStore().order.payment.isPayInAdvance !== null &&
|
||||
(useMainStore().order.payment.isPayInAdvance ||
|
||||
!!useMainStore().order.payment.payInAdvanceType);
|
||||
|
||||
return (
|
||||
packageReqs
|
||||
&& serviceLocationReqs
|
||||
&& isInsuranceSet
|
||||
&& scheduleReqs
|
||||
&& contactInfoReqs
|
||||
&& paymentMethodReqs
|
||||
packageReqs &&
|
||||
serviceLocationReqs &&
|
||||
isInsuranceSet &&
|
||||
scheduleReqs &&
|
||||
contactInfoReqs &&
|
||||
paymentMethodReqs
|
||||
);
|
||||
},
|
||||
getWorkOrderNumber() {
|
||||
|
|
@ -616,19 +469,32 @@ export default {
|
|||
return undefined;
|
||||
},
|
||||
getAddress1() {
|
||||
return useMainStore().order.serviceLocation.address ?? useMainStore().order.serviceLocation.provider.address.streetAddress;
|
||||
return (
|
||||
useMainStore().order.serviceLocation.address ??
|
||||
useMainStore().order.serviceLocation.provider.address
|
||||
.streetAddress
|
||||
);
|
||||
},
|
||||
getAddress2() {
|
||||
return useMainStore().order.serviceLocation.address2;
|
||||
},
|
||||
getCity() {
|
||||
return useMainStore().order.serviceLocation.city ?? useMainStore().order.serviceLocation.provider.address.city;
|
||||
return (
|
||||
useMainStore().order.serviceLocation.city ??
|
||||
useMainStore().order.serviceLocation.provider.address.city
|
||||
);
|
||||
},
|
||||
getState() {
|
||||
return useMainStore().order.serviceLocation.state ?? useMainStore().order.serviceLocation.provider.address.state;
|
||||
return (
|
||||
useMainStore().order.serviceLocation.state ??
|
||||
useMainStore().order.serviceLocation.provider.address.state
|
||||
);
|
||||
},
|
||||
getZipCode() {
|
||||
return useMainStore().order.serviceLocation.zipCode ?? useMainStore().order.serviceLocation.provider.address.zipCode;
|
||||
return (
|
||||
useMainStore().order.serviceLocation.zipCode ??
|
||||
useMainStore().order.serviceLocation.provider.address.zipCode
|
||||
);
|
||||
},
|
||||
getPaymentType() {
|
||||
switch (useMainStore().order.payment.payInAdvanceType) {
|
||||
|
|
@ -644,13 +510,33 @@ export default {
|
|||
},
|
||||
getPayInAdvanceLineItems(cartItems) {
|
||||
const { glassParts } = useMainStore().order.lineItems;
|
||||
const lineItems = (glassParts === null)
|
||||
? [this.getPayInAdvanceFormattedLineItem('Labor', 0, 1), this.getPayInAdvanceFormattedLineItem('Repair supplies', 0, 1)]
|
||||
: [this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1)];
|
||||
const lineItems =
|
||||
glassParts === null
|
||||
? [
|
||||
this.getPayInAdvanceFormattedLineItem('Labor', 0, 1),
|
||||
this.getPayInAdvanceFormattedLineItem(
|
||||
'Repair supplies',
|
||||
0,
|
||||
1
|
||||
),
|
||||
]
|
||||
: [
|
||||
this.getPayInAdvanceFormattedLineItem(
|
||||
'Parts and labor',
|
||||
0,
|
||||
1
|
||||
),
|
||||
];
|
||||
|
||||
cartItems.forEach((item) => {
|
||||
if (item.name !== null && item.category !== 'promos') {
|
||||
lineItems.push(this.getPayInAdvanceFormattedLineItem(item.name, (item.salesTax + item.subTotal).toFixed(2), 1));
|
||||
lineItems.push(
|
||||
this.getPayInAdvanceFormattedLineItem(
|
||||
item.name,
|
||||
(item.salesTax + item.subTotal).toFixed(2),
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -661,9 +547,19 @@ export default {
|
|||
},
|
||||
getMockPiaLineItems() {
|
||||
let lineItems = [];
|
||||
lineItems = [this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1)];
|
||||
lineItems.push(this.getPayInAdvanceFormattedLineItem('New wiper blades', 75.22, 1));
|
||||
lineItems.push(this.getPayInAdvanceFormattedLineItem('Recycling', 37.60, 1));
|
||||
lineItems = [
|
||||
this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1),
|
||||
];
|
||||
lineItems.push(
|
||||
this.getPayInAdvanceFormattedLineItem(
|
||||
'New wiper blades',
|
||||
75.22,
|
||||
1
|
||||
)
|
||||
);
|
||||
lineItems.push(
|
||||
this.getPayInAdvanceFormattedLineItem('Recycling', 37.6, 1)
|
||||
);
|
||||
|
||||
this.payInAdvanceLineItems = lineItems.join('||');
|
||||
},
|
||||
|
|
@ -671,7 +567,9 @@ export default {
|
|||
return baseMixin.methods.getAmountDue(useMainStore().lineItems);
|
||||
},
|
||||
getDisplayAmountDue() {
|
||||
return baseMixin.methods.getDisplayAmountDue(useMainStore().lineItems);
|
||||
return baseMixin.methods.getDisplayAmountDue(
|
||||
useMainStore().lineItems
|
||||
);
|
||||
},
|
||||
fetchSignatureInfo(signatureInfo) {
|
||||
this.authToken = signatureInfo.token;
|
||||
|
|
@ -688,10 +586,21 @@ export default {
|
|||
if (iframe) {
|
||||
iframe.onload = () => {
|
||||
if (iframe.contentWindow) {
|
||||
if (this.paymentType === hopPaymentMethods.CREDIT_CARD) {
|
||||
iframe.contentWindow.postMessage('CreditCardChosen', '*');
|
||||
} else if (this.paymentType === hopPaymentMethods.AFTERPAY) {
|
||||
iframe.contentWindow.postMessage('afterpay', '*');
|
||||
if (
|
||||
this.paymentType ===
|
||||
hopPaymentMethods.CREDIT_CARD
|
||||
) {
|
||||
iframe.contentWindow.postMessage(
|
||||
'CreditCardChosen',
|
||||
'*'
|
||||
);
|
||||
} else if (
|
||||
this.paymentType === hopPaymentMethods.AFTERPAY
|
||||
) {
|
||||
iframe.contentWindow.postMessage(
|
||||
'afterpay',
|
||||
'*'
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -710,7 +619,8 @@ export default {
|
|||
},
|
||||
setIFrameListener() {
|
||||
window.addEventListener('message', (event) =>
|
||||
this.handleIFrameContentWindowMessage(event));
|
||||
this.handleIFrameContentWindowMessage(event)
|
||||
);
|
||||
},
|
||||
setUIBlock(val) {
|
||||
this.shouldBlockInteraction = val;
|
||||
|
|
@ -722,7 +632,8 @@ export default {
|
|||
},
|
||||
displayPayInAdvanceAlert(payMethod) {
|
||||
return (
|
||||
this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT] === payMethod
|
||||
this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT] ===
|
||||
payMethod
|
||||
);
|
||||
},
|
||||
paymentFailedPayLater() {
|
||||
|
|
@ -736,14 +647,17 @@ export default {
|
|||
window.location = this.payInAdvanceCancelUrl;
|
||||
},
|
||||
forwardButtonAction() {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||
}
|
||||
}
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.payment p{
|
||||
margin-bottom:0.75rem;
|
||||
.payment p {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.hop-iframe {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,16 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div
|
||||
class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid mt-0 px-5">
|
||||
<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="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
|
|
@ -79,7 +82,7 @@ export default {
|
|||
siteFooter,
|
||||
buttonQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -89,9 +92,10 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}];
|
||||
// use resultMap to populate layout content.
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
|
|
@ -108,10 +112,12 @@ export default {
|
|||
questionAnswersArray: [],
|
||||
schoolPropertyAnswer: '',
|
||||
parkingLotAnswer: '',
|
||||
hasValidCarId: this.mainStore.vehicle.carId && this.mainStore.vehicle.carId !== '0',
|
||||
hasValidCarId:
|
||||
this.mainStore.vehicle.carId &&
|
||||
this.mainStore.vehicle.carId !== '0',
|
||||
rules: {
|
||||
selectionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
selectionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -128,57 +134,66 @@ export default {
|
|||
return this.getCmsContent('ParkingLotQuestion', 'Answers');
|
||||
},
|
||||
educatorEndorsement() {
|
||||
return useMainStore().order.policy.endorsements?.includes(endorsementOptions.EDUCATOR) ?? false;
|
||||
return (
|
||||
useMainStore().order.policy.endorsements?.includes(
|
||||
endorsementOptions.EDUCATOR
|
||||
) ?? false
|
||||
);
|
||||
},
|
||||
parkingGuardEndorsement() {
|
||||
return useMainStore().order.policy.endorsements?.includes(endorsementOptions.PARKING_GUARD) ?? false;
|
||||
}
|
||||
return (
|
||||
useMainStore().order.policy.endorsements?.includes(
|
||||
endorsementOptions.PARKING_GUARD
|
||||
) ?? false
|
||||
);
|
||||
},
|
||||
},
|
||||
methods:
|
||||
{
|
||||
async forwardButtonAction() {
|
||||
// TO DO: remove hard coding and update data format once service returns endorsement questions
|
||||
if (this.educatorEndorsement) {
|
||||
this.questionAnswersArray.push({
|
||||
questionNum: 1,
|
||||
endorsementName: endorsementOptions.EDUCATOR,
|
||||
questionText: this.schoolPropertyQuestionText,
|
||||
selectedAnswer: this.schoolPropertyAnswer
|
||||
});
|
||||
}
|
||||
if (this.parkingGuardEndorsement) {
|
||||
this.questionAnswersArray.push({
|
||||
questionNum: 2,
|
||||
endorsementName: endorsementOptions.PARKING_GUARD,
|
||||
questionText: this.parkingLotQuestionText,
|
||||
selectedAnswer: this.parkingLotAnswer
|
||||
});
|
||||
}
|
||||
|
||||
// save answers to store as order.policy.endorsementQuestionAnswers
|
||||
useMainStore().saveEndorsementQuestionAnswers(this.questionAnswersArray);
|
||||
|
||||
return this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
if (!this.hasValidCarId) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_CAR_ID_NOT_FOUND,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
methods: {
|
||||
async forwardButtonAction() {
|
||||
// TO DO: remove hard coding and update data format once service returns endorsement questions
|
||||
if (this.educatorEndorsement) {
|
||||
this.questionAnswersArray.push({
|
||||
questionNum: 1,
|
||||
endorsementName: endorsementOptions.EDUCATOR,
|
||||
questionText: this.schoolPropertyQuestionText,
|
||||
selectedAnswer: this.schoolPropertyAnswer,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (this.parkingGuardEndorsement) {
|
||||
this.questionAnswersArray.push({
|
||||
questionNum: 2,
|
||||
endorsementName: endorsementOptions.PARKING_GUARD,
|
||||
questionText: this.parkingLotQuestionText,
|
||||
selectedAnswer: this.parkingLotAnswer,
|
||||
});
|
||||
}
|
||||
|
||||
// save answers to store as order.policy.endorsementQuestionAnswers
|
||||
useMainStore().saveEndorsementQuestionAnswers(
|
||||
this.questionAnswersArray
|
||||
);
|
||||
|
||||
return this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
if (!this.hasValidCarId) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_WITH_CAR_ID_NOT_FOUND,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
:deep .subheader-primary {
|
||||
margin-bottom: map-get($spacers, 2);
|
||||
}
|
||||
|
|
@ -211,5 +226,4 @@ export default {
|
|||
:deep div.question-text.d-flex {
|
||||
margin-top: map-get($spacers, 4);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,39 +4,39 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2 px-5">
|
||||
<div class="row mt-4 mb-3">
|
||||
<div class="col">
|
||||
<siteSubHeader
|
||||
id="sub-header"
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<addressQuestions
|
||||
id="address-questions-wrapper"
|
||||
ref="addressQuestions"
|
||||
v-model="customerQuestions.addressQuestions"
|
||||
includeStreetAddress2="true" />
|
||||
<textboxQuestion
|
||||
ref="policyHolderFirstName"
|
||||
v-model="customerQuestions.firstName"
|
||||
inputId="firstNameField"
|
||||
cmsWidgetName="PolicyholderFirstNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.firstName" />
|
||||
<textboxQuestion
|
||||
ref="policyHolderLastName"
|
||||
v-model="customerQuestions.lastName"
|
||||
class="mt-4"
|
||||
inputId="lastNameField"
|
||||
cmsWidgetName="PolicyholderLastNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.lastName" />
|
||||
</div>
|
||||
</div>
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
id="sub-header"
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<addressQuestions
|
||||
id="address-questions-wrapper"
|
||||
ref="addressQuestions"
|
||||
v-model="customerQuestions.addressQuestions"
|
||||
includeStreetAddress2="true" />
|
||||
<textboxQuestion
|
||||
ref="policyHolderFirstName"
|
||||
v-model="customerQuestions.firstName"
|
||||
inputId="firstNameField"
|
||||
cmsWidgetName="PolicyholderFirstNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.firstName" />
|
||||
<textboxQuestion
|
||||
ref="policyHolderLastName"
|
||||
v-model="customerQuestions.lastName"
|
||||
class="mt-4"
|
||||
inputId="lastNameField"
|
||||
cmsWidgetName="PolicyholderLastNameQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.lastName" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
|
|
@ -74,7 +74,7 @@ export default {
|
|||
addressQuestions,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -85,8 +85,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
|
|
@ -106,8 +106,8 @@ export default {
|
|||
vehiclesFound: [],
|
||||
rules: {
|
||||
firstName: globalRules.POLICYHOLDER_FIRST_NAME_REQUIRED,
|
||||
lastName: globalRules.POLICYHOLDER_LAST_NAME_REQUIRED
|
||||
}
|
||||
lastName: globalRules.POLICYHOLDER_LAST_NAME_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -116,10 +116,9 @@ export default {
|
|||
},
|
||||
vehiclesCount() {
|
||||
return this.vehiclesFound.length;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods:
|
||||
{
|
||||
methods: {
|
||||
async forwardButtonAction() {
|
||||
this.mainStore.updatePolicyHolderDetails(this.customerQuestions);
|
||||
return this.navigateForward();
|
||||
|
|
@ -144,19 +143,20 @@ export default {
|
|||
|
||||
getPolicyHolderDetailsFromStore() {
|
||||
return {
|
||||
addressQuestions:
|
||||
{
|
||||
streetAddress: this.mainStore.order.customer.address.streetAddress,
|
||||
streetAddress2: this.mainStore.order.customer.address.streetAddress2,
|
||||
addressQuestions: {
|
||||
streetAddress:
|
||||
this.mainStore.order.customer.address.streetAddress,
|
||||
streetAddress2:
|
||||
this.mainStore.order.customer.address.streetAddress2,
|
||||
city: this.mainStore.order.customer.address.city,
|
||||
state: this.mainStore.order.customer.address.state,
|
||||
zipCode: this.mainStore.order.customer.address.zipCode
|
||||
zipCode: this.mainStore.order.customer.address.zipCode,
|
||||
},
|
||||
firstName: this.mainStore.order.customer.firstName,
|
||||
lastName: this.mainStore.order.customer.lastName
|
||||
lastName: this.mainStore.order.customer.lastName,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -164,14 +164,14 @@ export default {
|
|||
#sub-header p {
|
||||
font-size: 16px;
|
||||
line-height: 26px;
|
||||
color: #4D5151;
|
||||
color: #4d5151;
|
||||
}
|
||||
|
||||
#address-questions-wrapper {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
#address-questions-wrapper .alert.heading {
|
||||
#address-questions-wrapper .alert.heading {
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,35 +4,32 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader
|
||||
class="mb-2 header"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2 px-5">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<vehicleBanner
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
class="mt-2 mb-4" />
|
||||
<policyVehiclesQuestion
|
||||
v-model="selectedVehicleVin"
|
||||
class="px-4"
|
||||
cmsWidgetName="PolicyVehiclesQuestion"
|
||||
:vehicles="VehiclesForQuestions"
|
||||
:validationRules="rules.optionRequired" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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" />
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -55,9 +52,10 @@ import globalRules from '@/constants/global-rules.js';
|
|||
import { useMainStore } from '@/store/index.js';
|
||||
import bailoutMessage from '@/constants/bailoutMessage';
|
||||
import {
|
||||
deductibleForSelectedVehicle, endorsementsForSelectedVehicle,
|
||||
deductibleForSelectedVehicle,
|
||||
endorsementsForSelectedVehicle,
|
||||
noCoverageForSelectedVehicle,
|
||||
repairWaivedForSelectedVehicle
|
||||
repairWaivedForSelectedVehicle,
|
||||
} from '@/helpers/policy-vehicle-helper';
|
||||
|
||||
export default {
|
||||
|
|
@ -68,11 +66,13 @@ export default {
|
|||
vehicleBanner,
|
||||
policyVehiclesQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = await fetchCmsContentForPage(to.query.issPage);
|
||||
const cmsContentPromise = await fetchCmsContentForPage(
|
||||
to.query.issPage
|
||||
);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(cmsContentPromise);
|
||||
});
|
||||
|
|
@ -90,26 +90,27 @@ export default {
|
|||
displayGeneric: true,
|
||||
policyVinFound: true,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
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}`
|
||||
};
|
||||
}) ?? [];
|
||||
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() {
|
||||
|
|
@ -125,9 +126,11 @@ export default {
|
|||
return repairWaivedForSelectedVehicle(this.selectedPolicyVehicle);
|
||||
},
|
||||
selectedVehicle() {
|
||||
const vehicle = this.mainStore.lookupVehicleByVin(this.selectedVehicleVin);
|
||||
const vehicle = this.mainStore.lookupVehicleByVin(
|
||||
this.selectedVehicleVin
|
||||
);
|
||||
return vehicle;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
async selectedVehicleVin(value) {
|
||||
|
|
@ -151,10 +154,12 @@ export default {
|
|||
// save selected vehicle to the store
|
||||
this.mainStore.updateVehicle(vehicle.data);
|
||||
this.displayGeneric = false;
|
||||
this.selectedPolicyVehicle = this.policyVehicles.find((p) => p.vin === value);
|
||||
this.selectedPolicyVehicle = this.policyVehicles.find(
|
||||
(p) => p.vin === value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
if (this.mainStore.order.vehicle.vin) {
|
||||
|
|
@ -163,116 +168,141 @@ export default {
|
|||
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);
|
||||
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));
|
||||
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.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, {
|
||||
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
|
||||
});
|
||||
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
|
||||
};
|
||||
}
|
||||
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>
|
||||
.header{
|
||||
.header {
|
||||
margin-bottom: 0rem !important;
|
||||
}
|
||||
:deep(.form-test-error){
|
||||
:deep(.form-test-error) {
|
||||
text-align: left;
|
||||
margin-top: 0rem !important;
|
||||
line-height: 1.50rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
<!-- †est comment -->
|
||||
|
|
|
|||
|
|
@ -1,26 +1,32 @@
|
|||
<template>
|
||||
<Form
|
||||
ref="theForm"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteSubHeader
|
||||
id="sub-header"
|
||||
cmsWidgetName="SiteSubHeader"
|
||||
class="mb-5 mt-4" />
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="selectedProvider"
|
||||
questionText="Select an option:"
|
||||
:answers="prefAnswers"
|
||||
groupName="prefQuestions"
|
||||
buttonTypeString="providerPrefRadio"
|
||||
:validationRules="rules.optionRequired"
|
||||
isRequired
|
||||
class="mx-5" />
|
||||
<div class="px-5">
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
id="sub-header"
|
||||
cmsWidgetName="SiteSubHeader"
|
||||
class="mb-5 mt-4" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="selectedProvider"
|
||||
questionText="Select an option:"
|
||||
:answers="prefAnswers"
|
||||
groupName="prefQuestions"
|
||||
buttonTypeString="providerPrefRadio"
|
||||
:validationRules="rules.optionRequired"
|
||||
isRequired />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
|
|
@ -30,28 +36,29 @@
|
|||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
<recalModal ref="recalModal" cmsWidgetName="RecalModal" />
|
||||
<steeringModal
|
||||
ref="StateSteeringModal"
|
||||
cmsWidgetName="StateSteeringModal" />
|
||||
<shopPreferenceModal
|
||||
ref="ShopPreferenceDrawer"
|
||||
cmsWidgetName="ShopPreferenceDrawer"
|
||||
:showSteeringLink="showSteeringLink"
|
||||
@openSteering="openStateSteeringModal" />
|
||||
<tpaRecalModal
|
||||
ref="TPARecalModal"
|
||||
cmsWidgetName="TPARecalModal"
|
||||
:ackError="ackError"
|
||||
@buttonClick="navigateWithTPAAck" />
|
||||
</div>
|
||||
<recalModal
|
||||
ref="recalModal"
|
||||
cmsWidgetName="RecalModal" />
|
||||
<steeringModal
|
||||
ref="StateSteeringModal"
|
||||
cmsWidgetName="StateSteeringModal" />
|
||||
<shopPreferenceModal
|
||||
ref="ShopPreferenceDrawer"
|
||||
cmsWidgetName="ShopPreferenceDrawer"
|
||||
:showSteeringLink="showSteeringLink"
|
||||
@openSteering="openStateSteeringModal" />
|
||||
<tpaRecalModal
|
||||
ref="TPARecalModal"
|
||||
cmsWidgetName="TPARecalModal"
|
||||
:ackError="ackError"
|
||||
@buttonClick="navigateWithTPAAck" />
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
import { fetchCmsContentForPage, setupModalLinks } from '@/helpers/cms-content-helper';
|
||||
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';
|
||||
|
|
@ -69,7 +76,7 @@ import shopPreferenceModal from '@/layouts/provider-preference/shop-preference-m
|
|||
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 bailoutMessage from '@/constants/bailoutMessage';
|
||||
|
||||
const options = { SAFELITE: 'SafeliteOption', TPA: 'TPAOption' };
|
||||
|
||||
|
|
@ -86,7 +93,7 @@ export default {
|
|||
recalModal,
|
||||
steeringModal,
|
||||
shopPreferenceModal,
|
||||
tpaRecalModal
|
||||
tpaRecalModal,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -95,8 +102,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
|
|
@ -114,8 +121,8 @@ export default {
|
|||
showSteeringLink: false,
|
||||
tpaAcknowledgement: false,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -125,39 +132,58 @@ export default {
|
|||
prefAnswers() {
|
||||
const cmsAnswersContent = [
|
||||
{
|
||||
cmsWidgetName: options.SAFELITE
|
||||
cmsWidgetName: options.SAFELITE,
|
||||
},
|
||||
{
|
||||
cmsWidgetName: options.TPA
|
||||
}
|
||||
cmsWidgetName: options.TPA,
|
||||
},
|
||||
];
|
||||
// if cms content has not yet loaded, skip
|
||||
if (!this.getCmsContent(cmsAnswersContent[0].cmsWidgetName, 'HeaderText')
|
||||
|| this.getCmsContent(cmsAnswersContent[0].cmsWidgetName, 'HeaderText') === '') {
|
||||
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)
|
||||
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;
|
||||
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>");
|
||||
return headerText?.replace(
|
||||
'{custom:SafeliteLogo}',
|
||||
"<span class='safeliteLogo'></span>"
|
||||
);
|
||||
},
|
||||
getSubheaderTextFromCms(cmsWidgetName) {
|
||||
return this.getCmsContent(cmsWidgetName, 'SubheaderText');
|
||||
|
|
@ -174,9 +200,11 @@ export default {
|
|||
navigateWithTPAAck() {
|
||||
this.mainStore.saveProviderPreferenceData({
|
||||
selectedProvider: this.selectedProvider,
|
||||
tpaAcknowledgement: this.tpaAcknowledgement
|
||||
tpaAcknowledgement: this.tpaAcknowledgement,
|
||||
});
|
||||
this.navigateForward(this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED);
|
||||
this.navigateForward(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED
|
||||
);
|
||||
},
|
||||
forwardButtonAction() {
|
||||
if (this.selectedProvider) {
|
||||
|
|
@ -184,7 +212,9 @@ export default {
|
|||
switch (this.selectedProvider) {
|
||||
case options.SAFELITE:
|
||||
this.mainStore.updateIsSafeliteProvider(true);
|
||||
scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE;
|
||||
scenario =
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_WITH_SAFELITE;
|
||||
break;
|
||||
case options.TPA:
|
||||
this.mainStore.updateIsSafeliteProvider(false);
|
||||
|
|
@ -194,10 +224,16 @@ export default {
|
|||
this.$refs.siteFooter.removeLoader();
|
||||
return;
|
||||
}
|
||||
scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED;
|
||||
scenario =
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_WITH_TPA_ENABLED;
|
||||
} else {
|
||||
this.mainStore.setBailout(bailoutMessage.TPANotEnabled());
|
||||
scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED;
|
||||
this.mainStore.setBailout(
|
||||
bailoutMessage.TPANotEnabled()
|
||||
);
|
||||
scenario =
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_WITH_TPA_DISABLED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -205,14 +241,14 @@ export default {
|
|||
this.navigateForward(scenario);
|
||||
this.mainStore.saveProviderPreferenceData({
|
||||
selectedProvider: this.selectedProvider,
|
||||
tpaAcknowledgement: this.tpaAcknowledgement
|
||||
tpaAcknowledgement: this.tpaAcknowledgement,
|
||||
});
|
||||
}
|
||||
},
|
||||
openStateSteeringModal() {
|
||||
this.$refs.StateSteeringModal.openModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -4,57 +4,73 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteSubHeader
|
||||
cmsWidgetName="ScheduleSubHeaderWidget"
|
||||
subTextClasses="text-center small sub-text"
|
||||
class="mt-4" />
|
||||
<template v-if="ChangeShopLink.length">
|
||||
<textBlock
|
||||
cmsWidgetName="ChangeShopLink"
|
||||
justifyText="center"
|
||||
class="mb-3 text-link-small"
|
||||
:marginTopSizeOverride="1" />
|
||||
</template>
|
||||
<div class="main-content-container">
|
||||
<locationAlerts
|
||||
ref="locationAlerts"
|
||||
cmsWidgetPrefix="LocationAlert-" />
|
||||
<datePicker
|
||||
ref="datePicker"
|
||||
v-model="selectedDate"
|
||||
customComponentId="dateQuestion"
|
||||
selectableDatesSetting="custom"
|
||||
class="text-link-small"
|
||||
:customSelectableDatesCallback="getAvailableDatesMethod"
|
||||
validationRules="date-required"
|
||||
@dateClicked="openInshopTimeSlotsModal" />
|
||||
<timeSlotModalQuestion
|
||||
ref="timeSlotModalQuestion"
|
||||
v-model="selectedTimeSlotInfo"
|
||||
customComponentId="timeSlotModalQuestion"
|
||||
cmsWidgetName="TimeSlotModalQuestion"
|
||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||
:selectedDate="selectedDate"
|
||||
:appointmentType="appointmentType"
|
||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||
:estimatedServiceMinutesMinimum="selectableDatesData.estimatedServiceMinutesMinimum"
|
||||
:estimatedServiceMinutesMaximum="selectableDatesData.estimatedServiceMinutesMaximum"
|
||||
validationRules="time-slot-selection-required"
|
||||
@timeSlotModalClosed="timeSlotModalClosed" />
|
||||
<siteFooter
|
||||
ref="navbar"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="ScheduleSubHeaderWidget"
|
||||
subTextClasses="text-center small sub-text"
|
||||
class="mt-4" />
|
||||
<template v-if="ChangeShopLink.length">
|
||||
<textBlock
|
||||
cmsWidgetName="ChangeShopLink"
|
||||
justifyText="center"
|
||||
class="mb-3 text-link-small"
|
||||
:marginTopSizeOverride="1" />
|
||||
</template>
|
||||
<div class="main-content-container">
|
||||
<locationAlerts
|
||||
ref="locationAlerts"
|
||||
cmsWidgetPrefix="LocationAlert-" />
|
||||
<datePicker
|
||||
ref="datePicker"
|
||||
v-model="selectedDate"
|
||||
customComponentId="dateQuestion"
|
||||
selectableDatesSetting="custom"
|
||||
class="text-link-small"
|
||||
:customSelectableDatesCallback="
|
||||
getAvailableDatesMethod
|
||||
"
|
||||
validationRules="date-required"
|
||||
@dateClicked="openInshopTimeSlotsModal" />
|
||||
<timeSlotModalQuestion
|
||||
ref="timeSlotModalQuestion"
|
||||
v-model="selectedTimeSlotInfo"
|
||||
customComponentId="timeSlotModalQuestion"
|
||||
cmsWidgetName="TimeSlotModalQuestion"
|
||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||
:selectedDate="selectedDate"
|
||||
:appointmentType="appointmentType"
|
||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||
:estimatedServiceMinutesMinimum="
|
||||
selectableDatesData.estimatedServiceMinutesMinimum
|
||||
"
|
||||
:estimatedServiceMinutesMaximum="
|
||||
selectableDatesData.estimatedServiceMinutesMaximum
|
||||
"
|
||||
validationRules="time-slot-selection-required"
|
||||
@timeSlotModalClosed="timeSlotModalClosed" />
|
||||
<siteFooter
|
||||
ref="navbar"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
|
|
@ -74,10 +90,17 @@ import {
|
|||
AppointmentTypeStrings,
|
||||
GET_MOBILE_TIME_SLOTS,
|
||||
GET_SHOP_TIME_SLOTS,
|
||||
PREMIUM_FEE_PART_TYPE
|
||||
PREMIUM_FEE_PART_TYPE,
|
||||
} from '@/constants/schedule-constants.js';
|
||||
import { fetchCmsContentForPage, splitCopyOnCMSPlaceHolder } from '@/helpers/cms-content-helper';
|
||||
import { calcDaysBetweenDates, convertDateStringToDate, sumDateString } from '@/helpers/date-helper';
|
||||
import {
|
||||
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';
|
||||
|
|
@ -103,7 +126,10 @@ const getAvailableDates = async (
|
|||
appointmentType,
|
||||
providerNumber
|
||||
) => {
|
||||
const apiEndDateLimit = sumDateString(startDateString, TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||
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 = [];
|
||||
|
|
@ -117,7 +143,10 @@ const getAvailableDates = async (
|
|||
|
||||
if (i > 1) {
|
||||
apiStartDate = sumDateString(apiEndDate, 1);
|
||||
apiEndDate = sumDateString(apiStartDate, TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||
apiEndDate = sumDateString(
|
||||
apiStartDate,
|
||||
TIME_SLOTS_CALL_DAYS_LIMIT
|
||||
);
|
||||
|
||||
if (i === apiCallsCount) {
|
||||
apiEndDate = endDateString;
|
||||
|
|
@ -126,14 +155,17 @@ const getAvailableDates = async (
|
|||
apiEndDate = apiEndDateLimit;
|
||||
}
|
||||
|
||||
if (appointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||
if (
|
||||
appointmentType === AppointmentTypeStrings.MOBILE ||
|
||||
appointmentType ===
|
||||
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
) {
|
||||
storeActionConfig = {
|
||||
storeAction: GET_MOBILE_TIME_SLOTS,
|
||||
payload: {
|
||||
startDate: apiStartDate,
|
||||
endDate: apiEndDate
|
||||
}
|
||||
endDate: apiEndDate,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
storeActionConfig = {
|
||||
|
|
@ -142,15 +174,16 @@ const getAvailableDates = async (
|
|||
startDate: apiStartDate,
|
||||
endDate: apiEndDate,
|
||||
shopAppointmentType: appointmentType,
|
||||
providerNumber
|
||||
}
|
||||
providerNumber,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (apiStartDate < apiEndDate) storeActionConfigs.push(storeActionConfig);
|
||||
if (apiStartDate < apiEndDate)
|
||||
storeActionConfigs.push(storeActionConfig);
|
||||
}
|
||||
|
||||
const timeSlotsResponsesData = {
|
||||
days: []
|
||||
days: [],
|
||||
};
|
||||
|
||||
function compareDayStrings(a, b) {
|
||||
|
|
@ -160,26 +193,33 @@ const getAvailableDates = async (
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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
|
||||
];
|
||||
}));
|
||||
timeSlotsResponsesData.estimatedServiceMinutesMinimum =
|
||||
timeSlotsResponse.data.estimatedServiceMinutesMinimum;
|
||||
timeSlotsResponsesData.estimatedServiceMinutesMaximum =
|
||||
timeSlotsResponse.data.estimatedServiceMinutesMaximum;
|
||||
timeSlotsResponsesData.days = [
|
||||
...timeSlotsResponsesData.days,
|
||||
...timeSlotsResponse.data.days,
|
||||
];
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return makeParallelCalls().then(() => {
|
||||
|
|
@ -200,7 +240,7 @@ export default {
|
|||
siteFooter,
|
||||
textBlock,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -212,12 +252,13 @@ export default {
|
|||
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
const datePickerInitialDataPromise = await datePicker.methods.loadInitialData({
|
||||
selectableDatesSetting: 'custom',
|
||||
initialViewRowsToShow: 5,
|
||||
customSelectableDatesCallback: getAvailableDates,
|
||||
preSelectedDate
|
||||
});
|
||||
const datePickerInitialDataPromise =
|
||||
await datePicker.methods.loadInitialData({
|
||||
selectableDatesSetting: 'custom',
|
||||
initialViewRowsToShow: 5,
|
||||
customSelectableDatesCallback: getAvailableDates,
|
||||
preSelectedDate,
|
||||
});
|
||||
|
||||
const premiumFeePromise = useMainStore().getMobilePremiumFee();
|
||||
|
||||
|
|
@ -237,29 +278,34 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'alertReasons',
|
||||
promise: alertReasonsPromise
|
||||
promise: alertReasonsPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'datePickerInitialData',
|
||||
promise: datePickerInitialDataPromise
|
||||
promise: datePickerInitialDataPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'premiumFeeWithPrice',
|
||||
promise: premiumFeeWithPricePromise
|
||||
}
|
||||
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.datePicker.initializeComponent(
|
||||
resultMap.datePickerInitialData
|
||||
);
|
||||
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
||||
vm.setData(resultMap.datePickerInitialData.initialShopTimeSlotsResponse, resultMap.premiumFeeWithPrice);
|
||||
vm.setData(
|
||||
resultMap.datePickerInitialData.initialShopTimeSlotsResponse,
|
||||
resultMap.premiumFeeWithPrice
|
||||
);
|
||||
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
||||
});
|
||||
},
|
||||
|
|
@ -272,7 +318,7 @@ export default {
|
|||
selectedDate: this.getSelectedDate(),
|
||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||
selectableDatesData: [],
|
||||
mobilePremiumAppointmentFee: null
|
||||
mobilePremiumAppointmentFee: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -290,11 +336,13 @@ export default {
|
|||
return null;
|
||||
}
|
||||
|
||||
return this.selectableDatesData.days?.find((selectableDate) => selectableDate.date === this.selectedDate);
|
||||
return this.selectableDatesData.days?.find(
|
||||
(selectableDate) => selectableDate.date === this.selectedDate
|
||||
);
|
||||
},
|
||||
supportingItems() {
|
||||
return useMainStore().lineItems.supportingItems;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedDate(newValue, oldValue) {
|
||||
|
|
@ -307,31 +355,34 @@ export default {
|
|||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null
|
||||
jobMinMinutes: null,
|
||||
},
|
||||
isPremiumAppointment: null
|
||||
isPremiumAppointment: 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 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);
|
||||
useMainStore().order.damage.isRepair ||
|
||||
(useMainStore().order.lineItems?.glassParts != null &&
|
||||
useMainStore().order.lineItems.glassParts.length > 0);
|
||||
|
||||
return serviceLocationPreReqs && supportingItems && damageInfo;
|
||||
},
|
||||
|
|
@ -349,7 +400,8 @@ export default {
|
|||
this.mainStore.order.serviceLocation.provider.providerNumber
|
||||
);
|
||||
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
||||
this.selectableDatesData.days = this.selectableDatesData.days.concat(newShopTimeSlots.days);
|
||||
this.selectableDatesData.days =
|
||||
this.selectableDatesData.days.concat(newShopTimeSlots.days);
|
||||
return newShopTimeSlots;
|
||||
},
|
||||
getAvailableDates,
|
||||
|
|
@ -364,12 +416,16 @@ export default {
|
|||
},
|
||||
getSelectedTimeSlotInfo() {
|
||||
const isPremiumAppointment =
|
||||
!!(this.supportingItems?.filter((lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE) ?? [])
|
||||
.length > 0;
|
||||
!!(
|
||||
this.supportingItems?.filter(
|
||||
(lineItem) =>
|
||||
lineItem.partType === PREMIUM_FEE_PART_TYPE
|
||||
) ?? []
|
||||
).length > 0;
|
||||
|
||||
const selectedTimeSlotInfo = {
|
||||
timeSlot: this.mainStore.order.schedule,
|
||||
isPremiumAppointment
|
||||
isPremiumAppointment,
|
||||
};
|
||||
|
||||
return selectedTimeSlotInfo;
|
||||
|
|
@ -385,12 +441,16 @@ export default {
|
|||
if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) {
|
||||
navbarButtonText = 'Continue';
|
||||
} else {
|
||||
navbarButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(timeSlotInfo.timeSlot.date)}`;
|
||||
navbarButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(
|
||||
timeSlotInfo.timeSlot.date
|
||||
)}`;
|
||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(timeSlotInfo.timeSlot.startTime)}`;
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.startTime
|
||||
)}`;
|
||||
} else if (
|
||||
this.appointmentType === AppointmentTypeStrings.MOBILE
|
||||
&& !timeSlotInfo.isPremiumAppointment
|
||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||
!timeSlotInfo.isPremiumAppointment
|
||||
) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.startTime,
|
||||
|
|
@ -406,9 +466,15 @@ export default {
|
|||
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' });
|
||||
return dateObject.toLocaleDateString('en-us', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
});
|
||||
},
|
||||
getDisplayTextForMilitaryTime(militaryTimeInput, shouldTrimMinutesIfEmpty = false) {
|
||||
getDisplayTextForMilitaryTime(
|
||||
militaryTimeInput,
|
||||
shouldTrimMinutesIfEmpty = false
|
||||
) {
|
||||
// Expected input: "HH:MM"
|
||||
let hours = parseInt(militaryTimeInput.split(':')[0], 10);
|
||||
const minutes = militaryTimeInput.split(':')[1];
|
||||
|
|
@ -426,9 +492,12 @@ export default {
|
|||
forwardButtonAction() {
|
||||
this.mainStore.saveSchedule(this.selectedTimeSlotInfo.timeSlot);
|
||||
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||
}
|
||||
}
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -444,7 +513,8 @@ $page-side-padding: 1.5rem;
|
|||
}
|
||||
|
||||
:deep(.text-link-small) {
|
||||
a, .btn-link {
|
||||
a,
|
||||
.btn-link {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@
|
|||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-5" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" class="mt-5" />
|
||||
<div class="main-content-container">
|
||||
<serviceZipModalQuestion
|
||||
ref="serviceZipCodeQuestion"
|
||||
|
|
@ -86,9 +84,12 @@
|
|||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid || displayNoShopsAlert"
|
||||
:isForwardActionDisabled="
|
||||
!meta.valid || displayNoShopsAlert
|
||||
"
|
||||
@backClicked="navigateBack(this, navigateBackScenario)"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
>>>>>>> develop
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
|
|
@ -101,7 +102,11 @@ 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';
|
||||
import {
|
||||
getPricedMobileFeePart,
|
||||
getServiceabilityDetails,
|
||||
getZipCodeData,
|
||||
} from '@/helpers/service-location-helper';
|
||||
|
||||
// Import Component
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
|
|
@ -119,11 +124,11 @@ import serviceZipModalQuestion from '@/layouts/service-location/service-zip-moda
|
|||
// DEFINE VALIDATION RULES
|
||||
defineRule('mobile-location-required', (value) => {
|
||||
if (
|
||||
value.addressQuestions.streetAddress === ''
|
||||
|| value.addressQuestions.city === ''
|
||||
|| value.addressQuestions.state === ''
|
||||
|| value.addressQuestions.zipCode === ''
|
||||
|| value.isVehicleProtected == null
|
||||
value.addressQuestions.streetAddress === '' ||
|
||||
value.addressQuestions.city === '' ||
|
||||
value.addressQuestions.state === '' ||
|
||||
value.addressQuestions.zipCode === '' ||
|
||||
value.isVehicleProtected == null
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
|
|
@ -143,42 +148,46 @@ export default {
|
|||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
serviceZipModalQuestion,
|
||||
shopQuestion
|
||||
shopQuestion,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
const serviceZipCode = useMainStore().order.serviceLocation.zipCode || useMainStore().order.customer.address.zipCode;
|
||||
const serviceZipCode =
|
||||
useMainStore().order.serviceLocation.zipCode ||
|
||||
useMainStore().order.customer.address.zipCode;
|
||||
const zipCodeData = getZipCodeData(serviceZipCode);
|
||||
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
|
||||
const shopQuestionInitialDataPromise = shopQuestion.methods.loadInitialData(serviceZipCode);
|
||||
const serviceabilityDetailsPromise =
|
||||
getServiceabilityDetails(serviceZipCode);
|
||||
const shopQuestionInitialDataPromise =
|
||||
shopQuestion.methods.loadInitialData(serviceZipCode);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'mobileFeePart',
|
||||
promise: mobileFeePartPromise
|
||||
promise: mobileFeePartPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'serviceabilityDetails',
|
||||
promise: serviceabilityDetailsPromise
|
||||
promise: serviceabilityDetailsPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'shopQuestionInitialData',
|
||||
promise: shopQuestionInitialDataPromise
|
||||
promise: shopQuestionInitialDataPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'zipCodeData',
|
||||
promise: zipCodeData
|
||||
}
|
||||
promise: zipCodeData,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -190,7 +199,9 @@ export default {
|
|||
resultMap.mobileFeePart,
|
||||
resultMap.shopQuestionInitialData?.mobileProviderNumber
|
||||
);
|
||||
vm.$refs.shopQuestion.initializeComponent(resultMap.shopQuestionInitialData);
|
||||
vm.$refs.shopQuestion.initializeComponent(
|
||||
resultMap.shopQuestionInitialData
|
||||
);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
|
|
@ -214,12 +225,15 @@ export default {
|
|||
mobileFeePart: null,
|
||||
mobileProviderNumber: null,
|
||||
zipContainsMilitaryBase: false,
|
||||
zipCodeCtu: null
|
||||
zipCodeCtu: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent('ServiceTypeQuestionWidget', 'QuestionText');
|
||||
return this.getCmsContent(
|
||||
'ServiceTypeQuestionWidget',
|
||||
'QuestionText'
|
||||
);
|
||||
},
|
||||
answersFromCms() {
|
||||
return this.getCmsContent('ServiceTypeQuestionWidget', 'Answers');
|
||||
|
|
@ -228,7 +242,7 @@ export default {
|
|||
get() {
|
||||
return {
|
||||
state: this.state,
|
||||
zipCode: this.zipCode
|
||||
zipCode: this.zipCode,
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
|
|
@ -243,7 +257,7 @@ export default {
|
|||
|
||||
// eslint-disable-next-line vue/valid-next-tick
|
||||
this.$nextTick();
|
||||
}
|
||||
},
|
||||
},
|
||||
mobileLocationQuestions: {
|
||||
get() {
|
||||
|
|
@ -253,9 +267,9 @@ export default {
|
|||
streetAddress2: this.streetAddress2,
|
||||
city: this.city,
|
||||
state: this.state,
|
||||
zipCode: this.zipCode
|
||||
zipCode: this.zipCode,
|
||||
},
|
||||
isVehicleProtected: this.isVehicleProtected
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
|
|
@ -267,46 +281,62 @@ export default {
|
|||
this.isVehicleProtected = newValue.isVehicleProtected;
|
||||
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
if (!(this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)) {
|
||||
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 &&
|
||||
this.isRecalibrationServiceableMobile
|
||||
);
|
||||
}
|
||||
return this.isGlassServiceableMobile;
|
||||
},
|
||||
isServiceableInshop() {
|
||||
if (this.isRecalibrationServiceableInshop !== null) {
|
||||
return this.isGlassServiceableInshop && this.isRecalibrationServiceableInshop;
|
||||
return (
|
||||
this.isGlassServiceableInshop &&
|
||||
this.isRecalibrationServiceableInshop
|
||||
);
|
||||
}
|
||||
|
||||
return this.isGlassServiceableInshop;
|
||||
},
|
||||
isShopQuestionDisplayed() {
|
||||
return (
|
||||
this.selectedAppointmentType === 'Inshop'
|
||||
|| this.selectedAppointmentType === 'Dropoff'
|
||||
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;
|
||||
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
|
||||
this.isServiceableInshop &&
|
||||
this.isGlassServiceableMobile &&
|
||||
this.isRecalibrationServiceableMobile === false
|
||||
);
|
||||
},
|
||||
displayMilitaryZipAlert() {
|
||||
|
|
@ -320,9 +350,9 @@ export default {
|
|||
},
|
||||
displayServiceableInshopOnly() {
|
||||
return (
|
||||
!this.displayRecalibrationWarning
|
||||
&& this.isServiceableInshop
|
||||
&& !this.isServiceableMobile
|
||||
!this.displayRecalibrationWarning &&
|
||||
this.isServiceableInshop &&
|
||||
!this.isServiceableMobile
|
||||
);
|
||||
},
|
||||
displayServiceableMobileOnly() {
|
||||
|
|
@ -333,13 +363,13 @@ export default {
|
|||
return isNoComp || isITAC
|
||||
? this.navigationScenarios.CLICKED_BACK_CANNOT_REACH_TPA_FLOW
|
||||
: this.navigationScenarios.CLICKED_BACK_CAN_REACH_TPA_FLOW;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return (
|
||||
useMainStore().lineItems.supportingItems !== null
|
||||
&& useMainStore().order.serviceLocation.zipCode !== null
|
||||
useMainStore().lineItems.supportingItems !== null &&
|
||||
useMainStore().order.serviceLocation.zipCode !== null
|
||||
);
|
||||
},
|
||||
async reloadShopData(zipCode) {
|
||||
|
|
@ -360,8 +390,8 @@ export default {
|
|||
city: null,
|
||||
state: null,
|
||||
zipCode: null,
|
||||
zipCodeCtu: null
|
||||
}
|
||||
zipCodeCtu: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -374,17 +404,18 @@ export default {
|
|||
zipCodeCtu: this.zipCodeCtu,
|
||||
appointmentType: this.selectedAppointmentType,
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
provider
|
||||
provider,
|
||||
});
|
||||
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
openModalAction(modalName) {
|
||||
this.$refs[modalName].openModal();
|
||||
},
|
||||
resetDependentState() {
|
||||
|
||||
},
|
||||
resetDependentState() {},
|
||||
getServiceAddressFromStore() {
|
||||
return useMainStore().order.serviceLocation.address;
|
||||
},
|
||||
|
|
@ -395,10 +426,16 @@ export default {
|
|||
return useMainStore().order.serviceLocation.city;
|
||||
},
|
||||
getServiceStateFromStore() {
|
||||
return useMainStore().order.serviceLocation.state || useMainStore().order.customer.address.state;
|
||||
return (
|
||||
useMainStore().order.serviceLocation.state ||
|
||||
useMainStore().order.customer.address.state
|
||||
);
|
||||
},
|
||||
getServiceZipCodeFromStore() {
|
||||
return useMainStore().order.serviceLocation.zipCode || useMainStore().order.customer.address.zipCode;
|
||||
return (
|
||||
useMainStore().order.serviceLocation.zipCode ||
|
||||
useMainStore().order.customer.address.zipCode
|
||||
);
|
||||
},
|
||||
getIsVehicleProtectedFromStore() {
|
||||
return useMainStore().order.serviceLocation.isVehicleProtected;
|
||||
|
|
@ -409,7 +446,12 @@ export default {
|
|||
getSelectedProvider() {
|
||||
return useMainStore().order.serviceLocation.provider;
|
||||
},
|
||||
setData(zipCodeData, serviceabilityDetails, mobileFeePart, mobileProviderNumber) {
|
||||
setData(
|
||||
zipCodeData,
|
||||
serviceabilityDetails,
|
||||
mobileFeePart,
|
||||
mobileProviderNumber
|
||||
) {
|
||||
if (zipCodeData) {
|
||||
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
|
||||
this.zipCodeCtu = zipCodeData.zipCodeCtu;
|
||||
|
|
@ -446,12 +488,16 @@ export default {
|
|||
this.isVehicleProtected = null;
|
||||
},
|
||||
setServiceabilityDetails(serviceabilityDetails) {
|
||||
this.isGlassServiceableInshop = serviceabilityDetails.isGlassServiceableInshop;
|
||||
this.isRecalibrationServiceableInshop = serviceabilityDetails.isRecalibrationServiceableInshop;
|
||||
this.isGlassServiceableMobile = serviceabilityDetails.isGlassServiceableMobile;
|
||||
this.isRecalibrationServiceableMobile = serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||
}
|
||||
}
|
||||
this.isGlassServiceableInshop =
|
||||
serviceabilityDetails.isGlassServiceableInshop;
|
||||
this.isRecalibrationServiceableInshop =
|
||||
serviceabilityDetails.isRecalibrationServiceableInshop;
|
||||
this.isGlassServiceableMobile =
|
||||
serviceabilityDetails.isGlassServiceableMobile;
|
||||
this.isRecalibrationServiceableMobile =
|
||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -475,21 +521,21 @@ $page-side-padding: 1.5rem;
|
|||
&:first-of-type {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
&:not(:nth-of-type(1)){
|
||||
line-height: 1.250rem;
|
||||
&:not(:nth-of-type(1)) {
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
.choose-option{
|
||||
.button-question >div {
|
||||
.choose-option {
|
||||
.button-question > div {
|
||||
&:first-of-type {
|
||||
margin-bottom: 0.95rem;
|
||||
line-height: 1.500rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-question{
|
||||
.row.form-test-error{
|
||||
line-height:1.500rem;
|
||||
.button-question {
|
||||
.row.form-test-error {
|
||||
line-height: 1.5rem;
|
||||
padding-left: 0rem !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -500,7 +546,6 @@ $page-side-padding: 1.5rem;
|
|||
span {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,14 +4,18 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
justification="left"
|
||||
issContainingPage="service-packages" />
|
||||
<div class="mx-5">
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
justification="left"
|
||||
issContainingPage="service-packages" />
|
||||
<servicePackageQuestion
|
||||
ref="servicePackage"
|
||||
cmsWidgetName="ServicePackage"
|
||||
|
|
@ -31,22 +35,18 @@
|
|||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
<loadingModal ref="loadingModal" :textSlides="loadingText" />
|
||||
<contentGroupModal
|
||||
ref="RainDefenseModal"
|
||||
cmsWidgetName="RainDefenseModal" />
|
||||
<contentGroupModal
|
||||
ref="FrontWiperModal"
|
||||
cmsWidgetName="FrontWiperModal" />
|
||||
<contentGroupModal
|
||||
ref="RearWiperModal"
|
||||
cmsWidgetName="RearWiperModal" />
|
||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
</div>
|
||||
<loadingModal
|
||||
ref="loadingModal"
|
||||
:textSlides="loadingText" />
|
||||
<contentGroupModal
|
||||
ref="RainDefenseModal"
|
||||
cmsWidgetName="RainDefenseModal" />
|
||||
<contentGroupModal
|
||||
ref="FrontWiperModal"
|
||||
cmsWidgetName="FrontWiperModal" />
|
||||
<contentGroupModal
|
||||
ref="RearWiperModal"
|
||||
cmsWidgetName="RearWiperModal" />
|
||||
<contentGroupModal
|
||||
ref="RecalModal"
|
||||
cmsWidgetName="RecalModal" />
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ export default {
|
|||
Form,
|
||||
servicePackageQuestion,
|
||||
loadingModal,
|
||||
contentGroupModal
|
||||
contentGroupModal,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -94,20 +94,20 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'wipers',
|
||||
promise: wipersPromise
|
||||
promise: wipersPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'rainDefense',
|
||||
promise: rainDefensePromise
|
||||
promise: rainDefensePromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'supportingItems',
|
||||
promise: supportingItemsPromise
|
||||
}
|
||||
promise: supportingItemsPromise,
|
||||
},
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
|
|
@ -118,11 +118,12 @@ export default {
|
|||
resultMap.rainDefense,
|
||||
...resultMap.supportingItems,
|
||||
...resultMap.wipers,
|
||||
...clonedGlassParts
|
||||
...clonedGlassParts,
|
||||
];
|
||||
|
||||
let hasBailedOut = false;
|
||||
const pricingResults = await store.getPriceOrderItems(availableLineItems)
|
||||
const pricingResults = await store
|
||||
.getPriceOrderItems(availableLineItems)
|
||||
.catch((err) => {
|
||||
useMainStore().setBailout(
|
||||
bailoutMessage.pricingResponseError(
|
||||
|
|
@ -155,17 +156,17 @@ export default {
|
|||
'Looking for dates',
|
||||
'Searching for times',
|
||||
'Nearly there',
|
||||
'Finishing up'
|
||||
'Finishing up',
|
||||
],
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
optionRequired: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
PriceDisclaimerText() {
|
||||
return this.getCmsContent('PriceDisclaimerWidget', 'Text');
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openModalAction(modalName) {
|
||||
|
|
@ -173,11 +174,11 @@ export default {
|
|||
},
|
||||
arePagePrerequisitesValid() {
|
||||
return (
|
||||
store.order.serviceLocation.zipCode
|
||||
&& store.order.serviceLocation.zipCodeCtu
|
||||
&& (store.order.damage.isRepair
|
||||
|| (store.order.lineItems?.glassParts != null
|
||||
&& store.order.lineItems.glassParts.length > 0))
|
||||
store.order.serviceLocation.zipCode &&
|
||||
store.order.serviceLocation.zipCodeCtu &&
|
||||
(store.order.damage.isRepair ||
|
||||
(store.order.lineItems?.glassParts != null &&
|
||||
store.order.lineItems.glassParts.length > 0))
|
||||
);
|
||||
},
|
||||
vapsItemsSelectedAction(vapsItemsSelected) {
|
||||
|
|
@ -187,10 +188,12 @@ export default {
|
|||
const parts = {
|
||||
glassParts: this.pricedGlassParts,
|
||||
supportingItems: this.supportingItems,
|
||||
vaps: this.selectedVaps
|
||||
vaps: this.selectedVaps,
|
||||
};
|
||||
if (!allGlassPartsAndItemsHavePrices(parts)) {
|
||||
window.console.error('One or more items have no price assigned!');
|
||||
window.console.error(
|
||||
'One or more items have no price assigned!'
|
||||
);
|
||||
}
|
||||
if (this.pricedGlassParts.length > 0) {
|
||||
store.updateGlassParts(this.pricedGlassParts);
|
||||
|
|
@ -198,15 +201,18 @@ export default {
|
|||
store.updateSupportingItems(this.supportingItems);
|
||||
store.updateVaps(this.selectedVaps);
|
||||
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||
}
|
||||
}
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.subheader-secondary {
|
||||
margin-top: .5rem;
|
||||
margin-top: 0.5rem;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +220,7 @@ export default {
|
|||
margin: 1.3rem 0 1.5rem 0;
|
||||
|
||||
a {
|
||||
color: #4D5151;
|
||||
color: #4d5151;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid px-5 pb-2 confirmation">
|
||||
<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="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
ref="vehicleBanner"
|
||||
class="mb-4"
|
||||
|
|
@ -17,7 +21,9 @@
|
|||
:displayGenericVehicleImage="false" />
|
||||
<div class="text-center text-color--black pb-2 fs-5">
|
||||
<img :src="tpaConfirmationImage" />
|
||||
<span class="ms-2" v-html="tpaConfirmationHeaderText"></span>
|
||||
<span
|
||||
class="ms-2"
|
||||
v-html="tpaConfirmationHeaderText"></span>
|
||||
</div>
|
||||
<div class="text-center text-color--black mb-3 fw-bold">
|
||||
<span v-html="tpaConfirmationSubheaderText"></span>
|
||||
|
|
@ -36,8 +42,7 @@
|
|||
:customText="contactCarrierText"
|
||||
class="contact-carrier-text small"
|
||||
@click="setBailoutInfo()" />
|
||||
<div
|
||||
ref="confirmationOrderDetailsSection">
|
||||
<div ref="confirmationOrderDetailsSection">
|
||||
<textBlock
|
||||
ref="tpaConfirmationOrderDetailsTitle"
|
||||
:customText="orderDetailsTitle"
|
||||
|
|
@ -75,12 +80,19 @@ import textBlock from '@/digital-components/text-block/text-block.vue';
|
|||
import deductibleBox from '@/layouts/tpa-submit/deductible-box/deductible-box.vue';
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage, processIfStatements } from '@/helpers/cms-content-helper';
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
processIfStatements,
|
||||
} from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import { toTitleCase, toDisplayPhoneNumber, formatAmountInDollars } from '@/helpers/text-helper.js';
|
||||
import {
|
||||
toTitleCase,
|
||||
toDisplayPhoneNumber,
|
||||
formatAmountInDollars,
|
||||
} from '@/helpers/text-helper.js';
|
||||
import bailoutMessage from '@/constants/bailoutMessage';
|
||||
|
||||
const VERIFYING_COVERAGE = 'Verifying coverage';
|
||||
|
|
@ -94,7 +106,7 @@ export default {
|
|||
textBlock,
|
||||
deductibleBox,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -105,12 +117,12 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'accountInfo',
|
||||
promise: accountInfoPromise
|
||||
}
|
||||
promise: accountInfoPromise,
|
||||
},
|
||||
];
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -130,40 +142,67 @@ export default {
|
|||
return this.getCmsContent('TPAConfirmationContent', 'Image');
|
||||
},
|
||||
tpaConfirmationSubheaderText() {
|
||||
return this.getCmsContent('TPAConfirmationContent', 'SubheaderText')
|
||||
?.replaceAll('{custom:glassShop}', this.preferredShopName);
|
||||
return this.getCmsContent(
|
||||
'TPAConfirmationContent',
|
||||
'SubheaderText'
|
||||
)?.replaceAll('{custom:glassShop}', this.preferredShopName);
|
||||
},
|
||||
tpaConfirmationBodyOne() {
|
||||
return this.getCmsContent('TPAConfirmationContent', 'BodyText')
|
||||
?.replaceAll('{custom:phoneNumber}', this.preferredShopPhoneNumber)
|
||||
?.replaceAll(
|
||||
'{custom:phoneNumber}',
|
||||
this.preferredShopPhoneNumber
|
||||
)
|
||||
?.replaceAll('{custom:glassShop}', this.preferredShopName);
|
||||
},
|
||||
tpaConfirmationBodyTwo() {
|
||||
return this.getCmsContent('TPAConfirmationContent', 'BodyText2');
|
||||
},
|
||||
contactCarrierText() {
|
||||
const contactCarrierText = this.getCmsContent('ContactCarrierContent', 'Text')
|
||||
?.replaceAll('{custom:carrierPhoneNumber}', this.carrierPhoneNumber);
|
||||
return this.processIfStatements(contactCarrierText, 'custom', this.getCustomValueFromString);
|
||||
const contactCarrierText = this.getCmsContent(
|
||||
'ContactCarrierContent',
|
||||
'Text'
|
||||
)?.replaceAll(
|
||||
'{custom:carrierPhoneNumber}',
|
||||
this.carrierPhoneNumber
|
||||
);
|
||||
return this.processIfStatements(
|
||||
contactCarrierText,
|
||||
'custom',
|
||||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
orderDetailsTitle() {
|
||||
return this.getCmsContent('OrderDetailsContent', 'HeaderText');
|
||||
},
|
||||
orderDetailsBody() {
|
||||
const orderDetailsBodyText = this.getCmsContent('OrderDetailsContent', 'BodyText');
|
||||
return this.processIfStatements(orderDetailsBodyText, 'custom', this.getCustomValueFromString);
|
||||
const orderDetailsBodyText = this.getCmsContent(
|
||||
'OrderDetailsContent',
|
||||
'BodyText'
|
||||
);
|
||||
return this.processIfStatements(
|
||||
orderDetailsBodyText,
|
||||
'custom',
|
||||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
deductibleBoxValue() {
|
||||
return this.isVerified ? this.formatAmountInDollars(this.currentDeductible) : VERIFYING_COVERAGE;
|
||||
return this.isVerified
|
||||
? this.formatAmountInDollars(this.currentDeductible)
|
||||
: VERIFYING_COVERAGE;
|
||||
},
|
||||
currentDeductible() {
|
||||
return useMainStore().order.currentDeductible;
|
||||
},
|
||||
preferredShopName() {
|
||||
return toTitleCase(useMainStore().order.serviceLocation.provider.companyName);
|
||||
return toTitleCase(
|
||||
useMainStore().order.serviceLocation.provider.companyName
|
||||
);
|
||||
},
|
||||
preferredShopPhoneNumber() {
|
||||
return this.toDisplayPhoneNumber(useMainStore().order.serviceLocation.provider.phoneNumber);
|
||||
return this.toDisplayPhoneNumber(
|
||||
useMainStore().order.serviceLocation.provider.phoneNumber
|
||||
);
|
||||
},
|
||||
isVerified() {
|
||||
return useMainStore().order.payment.insuranceCoverage.isVerified;
|
||||
|
|
@ -175,44 +214,46 @@ export default {
|
|||
return this.mainStore.issConfig.successReturnURL;
|
||||
},
|
||||
carrierPhoneNumber() {
|
||||
return this.toDisplayPhoneNumber(useMainStore().order.carrierPhoneNumber);
|
||||
}
|
||||
return this.toDisplayPhoneNumber(
|
||||
useMainStore().order.carrierPhoneNumber
|
||||
);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.carrierUrl) {
|
||||
this.$refs.siteFooter.updateButtonText(`Go back to ${this.carrierName}`);
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
`Go back to ${this.carrierName}`
|
||||
);
|
||||
}
|
||||
},
|
||||
methods:
|
||||
{
|
||||
async forwardButtonAction() {
|
||||
this.$router.navigateToExternalUrl(this.carrierUrl);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case 'deductibleAboveZero':
|
||||
return this.isVerified && this.currentDeductible !== 0;
|
||||
case 'zeroDeductible':
|
||||
return this.isVerified && this.currentDeductible === 0;
|
||||
case 'verifyingCoverage':
|
||||
return !this.isVerified;
|
||||
case 'coverageVerified':
|
||||
return this.isVerified;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
setBailoutInfo() {
|
||||
this.mainStore.setBailout(bailoutMessage.RequestCallback);
|
||||
},
|
||||
toDisplayPhoneNumber,
|
||||
formatAmountInDollars,
|
||||
processIfStatements
|
||||
}
|
||||
methods: {
|
||||
async forwardButtonAction() {
|
||||
this.$router.navigateToExternalUrl(this.carrierUrl);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case 'deductibleAboveZero':
|
||||
return this.isVerified && this.currentDeductible !== 0;
|
||||
case 'zeroDeductible':
|
||||
return this.isVerified && this.currentDeductible === 0;
|
||||
case 'verifyingCoverage':
|
||||
return !this.isVerified;
|
||||
case 'coverageVerified':
|
||||
return this.isVerified;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
setBailoutInfo() {
|
||||
this.mainStore.setBailout(bailoutMessage.RequestCallback);
|
||||
},
|
||||
toDisplayPhoneNumber,
|
||||
formatAmountInDollars,
|
||||
processIfStatements,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.text-color--black {
|
||||
color: $black;
|
||||
}
|
||||
|
|
@ -233,5 +274,4 @@ export default {
|
|||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,112 +1,120 @@
|
|||
<template>
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
:cmsWidgetName="widget.siteHeader" />
|
||||
<Form
|
||||
id="searchProvidersForm"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="mx-5">
|
||||
<label
|
||||
id="tpaSearchQuestionLabel"
|
||||
for="tpaSearchQuestionField"
|
||||
class="text-center fs-5 mt-5 mb-0 text-black w-100">
|
||||
{{ tpaSearchQuestionLabel }}
|
||||
</label>
|
||||
<label
|
||||
id="searchInstructions"
|
||||
for="tpaSearchQuestionField"
|
||||
class="text-center small darker-gray w-100 mb-4">
|
||||
{{ searchInstructionsText }}
|
||||
</label>
|
||||
<div class="mb-5">
|
||||
<textboxQuestion
|
||||
id="tpaSearchQuestionField"
|
||||
v-model="zipCode"
|
||||
inputId="tpaSearchQuestionFieldInput"
|
||||
:cmsWidgetName="widget.tpaSearchQuestion"
|
||||
:includeSearchIcon="true"
|
||||
:displayQuestionText="false"
|
||||
isRequired
|
||||
:isDisabled="reloadingProviders"
|
||||
:validationRules="rules.zipCode"
|
||||
@clickEvent="searchClick" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
<googleMap
|
||||
id="map"
|
||||
class="mb-4"
|
||||
:addresses="providerAddresses"
|
||||
:zipCode="mapZipCode" />
|
||||
<Form
|
||||
id="providerSelectionForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="mx-5">
|
||||
<dropdownQuestion
|
||||
id="searchRadiusFilter"
|
||||
v-model="filter"
|
||||
:cmsWidgetName="widget.filterByQuestion"
|
||||
inputId="searchRadiusFilterInput"
|
||||
:options="filterOptions"
|
||||
disableAutoFill
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<Form
|
||||
id="searchProvidersForm"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<label
|
||||
id="tpaSearchQuestionLabel"
|
||||
for="tpaSearchQuestionField"
|
||||
class="text-center fs-5 mt-5 mb-0 text-black w-100">
|
||||
{{ tpaSearchQuestionLabel }}
|
||||
</label>
|
||||
<label
|
||||
id="searchInstructions"
|
||||
for="tpaSearchQuestionField"
|
||||
class="text-center small darker-gray w-100 mb-4">
|
||||
{{ searchInstructionsText }}
|
||||
</label>
|
||||
<div class="mb-5">
|
||||
<textboxQuestion
|
||||
id="tpaSearchQuestionField"
|
||||
v-model="zipCode"
|
||||
inputId="tpaSearchQuestionFieldInput"
|
||||
:cmsWidgetName="widget.tpaSearchQuestion"
|
||||
:includeSearchIcon="true"
|
||||
:displayQuestionText="false"
|
||||
isRequired
|
||||
:isDisabled="reloadingProviders"
|
||||
:validationRules="rules.filter" />
|
||||
<loader
|
||||
v-if="reloadingProviders"
|
||||
id="providersLoader"
|
||||
loaderPosition="center"
|
||||
loaderColor="blue"
|
||||
:width="2"
|
||||
:height="2"
|
||||
class="my-4" />
|
||||
<div v-else>
|
||||
<div class="my-4">
|
||||
<buttonQuestion
|
||||
id="selectProviderQuestion"
|
||||
v-model="selectedProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:answers="providerButtonData"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
isRequired
|
||||
:validationRules="rules.provider"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<alert
|
||||
v-if="providers?.length === 0 ?? true"
|
||||
id="alertNoNetworkProviders"
|
||||
:cmsWidgetName="widget.noNetworkShopsAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false"
|
||||
:manualHeadline="noNetworkShopsAlertHeaderText" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<textLink
|
||||
id="preferredShopNotListedLink"
|
||||
linkType="navigation"
|
||||
href="javascript:void(0)"
|
||||
:text="shopNotListedModalLink"
|
||||
@clickEvent="doNotSeeMyShopLinkClick" />
|
||||
</div>
|
||||
</div>
|
||||
:validationRules="rules.zipCode"
|
||||
@clickEvent="searchClick" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
:cmsWidgetName="widget.siteFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</Form>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid fade-on-route-transition">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<googleMap
|
||||
id="map"
|
||||
class="mb-4"
|
||||
:addresses="providerAddresses"
|
||||
:zipCode="mapZipCode" />
|
||||
<Form
|
||||
id="providerSelectionForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<dropdownQuestion
|
||||
id="searchRadiusFilter"
|
||||
v-model="filter"
|
||||
:cmsWidgetName="widget.filterByQuestion"
|
||||
inputId="searchRadiusFilterInput"
|
||||
:options="filterOptions"
|
||||
disableAutoFill
|
||||
:isDisabled="reloadingProviders"
|
||||
:validationRules="rules.filter" />
|
||||
<loader
|
||||
v-if="reloadingProviders"
|
||||
id="providersLoader"
|
||||
loaderPosition="center"
|
||||
loaderColor="blue"
|
||||
:width="2"
|
||||
:height="2"
|
||||
class="my-4" />
|
||||
<div v-else>
|
||||
<div class="my-4">
|
||||
<buttonQuestion
|
||||
id="selectProviderQuestion"
|
||||
v-model="selectedProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:answers="providerButtonData"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
isRequired
|
||||
:validationRules="rules.provider"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<alert
|
||||
v-if="providers?.length === 0 ?? true"
|
||||
id="alertNoNetworkProviders"
|
||||
:cmsWidgetName="widget.noNetworkShopsAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false"
|
||||
:manualHeadline="
|
||||
noNetworkShopsAlertHeaderText
|
||||
" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<textLink
|
||||
id="preferredShopNotListedLink"
|
||||
linkType="navigation"
|
||||
href="javascript:void(0)"
|
||||
:text="shopNotListedModalLink"
|
||||
@clickEvent="doNotSeeMyShopLinkClick" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
:cmsWidgetName="widget.siteFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -138,7 +146,7 @@ const radiusFilterPairs = [
|
|||
{ radius: 15, filter: '15 miles' },
|
||||
{ radius: 25, filter: '25 miles' },
|
||||
{ radius: 50, filter: '50 miles' },
|
||||
{ radius: 100, filter: '100 miles' }
|
||||
{ radius: 100, filter: '100 miles' },
|
||||
];
|
||||
|
||||
function convertRadiusFilterToInteger(filter) {
|
||||
|
|
@ -194,11 +202,12 @@ export default {
|
|||
googleMap,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const { zipCode, filter, providers, providerNumber } = await getInitialSearchData();
|
||||
const { zipCode, filter, providers, providerNumber } =
|
||||
await getInitialSearchData();
|
||||
const cmsContent = await fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
next(async (vm) => {
|
||||
|
|
@ -216,7 +225,7 @@ export default {
|
|||
selectedProviderNumber: '',
|
||||
reloadingProviders: false,
|
||||
additionalButtonData: {
|
||||
displayAvailabilityIndicators: false
|
||||
displayAvailabilityIndicators: false,
|
||||
},
|
||||
widget: {
|
||||
siteHeader: 'SiteHeaderWidget',
|
||||
|
|
@ -225,22 +234,23 @@ export default {
|
|||
filterByQuestion: 'FilterByQuestion',
|
||||
noNetworkShopsAlert: 'NoNetworkShopsAlertWidget',
|
||||
shopNotListedLink: 'ShopNotListedLink',
|
||||
siteFooter: 'SiteFooterWidget'
|
||||
siteFooter: 'SiteFooterWidget',
|
||||
},
|
||||
rules: {
|
||||
zipCode: `${globalRules.ZIP_CODE_REQUIRED}|${globalRules.ZIP_CODE_SEARCH_FORMAT}`,
|
||||
filter: globalRules.OPTION_REQUIRED, // TODO do we even need this?
|
||||
provider: globalRules.OPTION_REQUIRED
|
||||
provider: globalRules.OPTION_REQUIRED,
|
||||
},
|
||||
shopListButton: shallowRef(shopListButton)
|
||||
shopListButton: shallowRef(shopListButton),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
filterOptions() {
|
||||
const filterByAnswers = this.getCmsContent(
|
||||
this.widget.filterByQuestion,
|
||||
widgetFields.INPUT_QUESTION_WIDGET.ANSWERS
|
||||
) ?? [];
|
||||
const filterByAnswers =
|
||||
this.getCmsContent(
|
||||
this.widget.filterByQuestion,
|
||||
widgetFields.INPUT_QUESTION_WIDGET.ANSWERS
|
||||
) ?? [];
|
||||
const filterByAnswersObj = {};
|
||||
[...filterByAnswers].forEach((answer) => {
|
||||
filterByAnswersObj[answer.Name] = answer.Name;
|
||||
|
|
@ -275,14 +285,26 @@ export default {
|
|||
)?.replaceAll('{custom:radiusInMiles}', this.radiusInMiles);
|
||||
},
|
||||
providerAddresses() {
|
||||
return this.providers?.map((provider) => this.getProviderAddress(provider)) ?? [];
|
||||
return (
|
||||
this.providers?.map((provider) =>
|
||||
this.getProviderAddress(provider)
|
||||
) ?? []
|
||||
);
|
||||
},
|
||||
providerButtonData() {
|
||||
return this.providers?.map((provider) => this.getShopButtonDataFromProvider(provider)) ?? [];
|
||||
return (
|
||||
this.providers?.map((provider) =>
|
||||
this.getShopButtonDataFromProvider(provider)
|
||||
) ?? []
|
||||
);
|
||||
},
|
||||
selectedProviderIsSafeliteShop() {
|
||||
return this.providers?.find((p) => p.providerNumber === this.selectedProviderNumber)?.isSafeliteShop ?? false;
|
||||
}
|
||||
return (
|
||||
this.providers?.find(
|
||||
(p) => p.providerNumber === this.selectedProviderNumber
|
||||
)?.isSafeliteShop ?? false
|
||||
);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
async filter() {
|
||||
|
|
@ -295,13 +317,16 @@ export default {
|
|||
},
|
||||
providers(newProviders) {
|
||||
if (this.dataLoaded) {
|
||||
this.selectedProviderNumber = newProviders?.length === 1 ?? false
|
||||
? newProviders[0]?.providerNumber ?? ''
|
||||
: '';
|
||||
this.selectedProviderNumber =
|
||||
newProviders?.length === 1 ?? false
|
||||
? newProviders[0]?.providerNumber ?? ''
|
||||
: '';
|
||||
}
|
||||
},
|
||||
selectedProviderNumber(newNumber) {
|
||||
const provider = this.providers?.find((p) => p.providerNumber === newNumber);
|
||||
const provider = this.providers?.find(
|
||||
(p) => p.providerNumber === newNumber
|
||||
);
|
||||
if (provider && this.dataLoaded) {
|
||||
useMainStore().updateServiceLocation({
|
||||
searchFilter: this.filter,
|
||||
|
|
@ -313,14 +338,14 @@ export default {
|
|||
city: provider.address?.city,
|
||||
state: provider.address?.state,
|
||||
zipCode: provider.address?.zipCode,
|
||||
zipCodeCtu: provider.address?.zipCodeCtu
|
||||
zipCodeCtu: provider.address?.zipCodeCtu,
|
||||
},
|
||||
companyName: provider?.companyName,
|
||||
phoneNumber: provider?.phoneNumber
|
||||
}
|
||||
phoneNumber: provider?.phoneNumber,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (!this.dataLoaded) {
|
||||
|
|
@ -355,12 +380,16 @@ export default {
|
|||
}
|
||||
|
||||
const addressLine1 = toTitleCase(provider?.address?.streetAddress);
|
||||
const joinString = addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : '';
|
||||
const joinString =
|
||||
addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : '';
|
||||
return [addressLine1, addressLine2].join(joinString);
|
||||
},
|
||||
async getProviderButtonData() {
|
||||
this.reloadingProviders = true;
|
||||
const getTpaProvidersResult = await useMainStore().getTpaProviders(this.zipCode, this.radiusInMiles);
|
||||
const getTpaProvidersResult = await useMainStore().getTpaProviders(
|
||||
this.zipCode,
|
||||
this.radiusInMiles
|
||||
);
|
||||
this.reloadingProviders = false;
|
||||
return getTpaProvidersResult?.data?.shopProviders ?? [];
|
||||
},
|
||||
|
|
@ -381,7 +410,8 @@ export default {
|
|||
}
|
||||
const scenario = this.selectedProviderIsSafeliteShop
|
||||
? this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP
|
||||
: this.navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP;
|
||||
: this.navigationScenarios
|
||||
.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP;
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
|
|
@ -394,25 +424,27 @@ export default {
|
|||
},
|
||||
getShopButtonDataFromProvider(provider) {
|
||||
const cellNumber = toDisplayPhoneNumber(provider?.phoneNumber);
|
||||
const distance = provider?.distanceInMiles !== null && !Number.isNaN(parseFloat(provider?.distanceInMiles))
|
||||
? +provider.distanceInMiles.toFixed(1)
|
||||
: null;
|
||||
const distance =
|
||||
provider?.distanceInMiles !== null &&
|
||||
!Number.isNaN(parseFloat(provider?.distanceInMiles))
|
||||
? +provider.distanceInMiles.toFixed(1)
|
||||
: null;
|
||||
|
||||
return {
|
||||
buttonLabel: provider?.companyName ?? '',
|
||||
buttonLabelSubCopy: distance === null
|
||||
? ''
|
||||
: `${distance} mi`,
|
||||
buttonBodyCopy: `${this.getProviderAddress(provider)}<br>${cellNumber ?? ''}`,
|
||||
value: provider?.providerNumber ?? ''
|
||||
buttonLabelSubCopy: distance === null ? '' : `${distance} mi`,
|
||||
buttonBodyCopy: `${this.getProviderAddress(provider)}<br>${
|
||||
cellNumber ?? ''
|
||||
}`,
|
||||
value: provider?.providerNumber ?? '',
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.darker-gray {
|
||||
color: map-get($colors, "darker-gray");
|
||||
color: map-get($colors, 'darker-gray');
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,17 +5,22 @@
|
|||
class="tpa-submit"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader
|
||||
ref="siteHeader"
|
||||
:cmsWidgetName="widget.siteHeader" />
|
||||
<div class="px-5">
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
ref="vehicleBanner"
|
||||
:cmsWidgetName="widget.vehicleBanner"
|
||||
:displayGenericVehicleImage="false"
|
||||
class="mt-5" /> <!-- TODO fix styling -->
|
||||
class="mt-5" />
|
||||
<!-- TODO fix styling -->
|
||||
<textBlock
|
||||
ref="subHeaderTitle"
|
||||
:customText="subHeaderTitle"
|
||||
|
|
@ -51,9 +56,7 @@
|
|||
<div
|
||||
v-for="(section, index) in sections"
|
||||
:key="section.title">
|
||||
<hr
|
||||
v-if="index !== 0"
|
||||
class="my-3" />
|
||||
<hr v-if="index !== 0" class="my-3" />
|
||||
<reviewBlock
|
||||
:id="'review-block-' + index"
|
||||
:customHeaderText="section.title"
|
||||
|
|
@ -109,13 +112,25 @@ import contactDetailsDrawer from '@/layouts/tpa-submit/contact-details-drawer/co
|
|||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage, processIfStatements, getStringWithCustomValues } from '@/helpers/cms-content-helper.js';
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
processIfStatements,
|
||||
getStringWithCustomValues,
|
||||
} from '@/helpers/cms-content-helper.js';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import { toTitleCase, toDisplayPhoneNumber, formatAddress, formatAmountInDollars } from '@/helpers/text-helper.js';
|
||||
import { getDamageDisplayContent, getLocationAnswer } from '@/helpers/damage-review-content-generator.js';
|
||||
import {
|
||||
toTitleCase,
|
||||
toDisplayPhoneNumber,
|
||||
formatAddress,
|
||||
formatAmountInDollars,
|
||||
} from '@/helpers/text-helper.js';
|
||||
import {
|
||||
getDamageDisplayContent,
|
||||
getLocationAnswer,
|
||||
} from '@/helpers/damage-review-content-generator.js';
|
||||
import damageLocationsSelected from '@/constants/damage-locations-selected.js';
|
||||
|
||||
const VERIFYING_COVERAGE = 'Verifying coverage';
|
||||
|
|
@ -132,7 +147,7 @@ export default {
|
|||
siteFooter,
|
||||
contactDetailsDrawer,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -155,41 +170,66 @@ export default {
|
|||
vehicle: 'VehicleSubTitle',
|
||||
damage: 'DamageSubTitle',
|
||||
shop: 'PreferredShopSubTitle',
|
||||
contactInfo: 'ContactDetailsSubTitle'
|
||||
contactInfo: 'ContactDetailsSubTitle',
|
||||
},
|
||||
damageLocations: 'DamageLocationsWidget',
|
||||
orderDetails: 'OrderDetailsContent',
|
||||
footer: 'SiteFooterWidget'
|
||||
footer: 'SiteFooterWidget',
|
||||
},
|
||||
companyName,
|
||||
customValueMap: {
|
||||
glassShop: companyName
|
||||
}
|
||||
glassShop: companyName,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
subHeaderTitle() {
|
||||
return this.getCmsContent(this.widget.siteSubHeader, widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
|
||||
return this.getCmsContent(
|
||||
this.widget.siteSubHeader,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT
|
||||
);
|
||||
},
|
||||
subHeaderBodyOne() {
|
||||
return this.getCmsContent(this.widget.siteSubHeader, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT);
|
||||
return this.getCmsContent(
|
||||
this.widget.siteSubHeader,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||
);
|
||||
},
|
||||
subHeaderBodyTwo() {
|
||||
const cmsContent = this.getCmsContent(this.widget.siteSubHeader, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
|
||||
const cmsContent = this.getCmsContent(
|
||||
this.widget.siteSubHeader,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2
|
||||
);
|
||||
return getStringWithCustomValues(cmsContent, this.customValueMap);
|
||||
},
|
||||
serviceSummaryText() {
|
||||
return this.getCmsContent(this.widget.serviceSummary, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
return this.getCmsContent(
|
||||
this.widget.serviceSummary,
|
||||
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
||||
);
|
||||
},
|
||||
orderDetailsTitle() {
|
||||
return this.getCmsContent(this.widget.orderDetails, widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
|
||||
return this.getCmsContent(
|
||||
this.widget.orderDetails,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT
|
||||
);
|
||||
},
|
||||
orderDetailsBody() {
|
||||
const orderDetailsBodyText = this.getCmsContent(this.widget.orderDetails, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT);
|
||||
return processIfStatements(orderDetailsBodyText, 'custom', this.getCustomValueFromString);
|
||||
const orderDetailsBodyText = this.getCmsContent(
|
||||
this.widget.orderDetails,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||
);
|
||||
return processIfStatements(
|
||||
orderDetailsBodyText,
|
||||
'custom',
|
||||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
forwardButtonText() {
|
||||
return this.getCmsContent(this.widget.footer, widgetFields.FOOTER_WIDGET.FORWARD_BUTTON_TEXT);
|
||||
return this.getCmsContent(
|
||||
this.widget.footer,
|
||||
widgetFields.FOOTER_WIDGET.FORWARD_BUTTON_TEXT
|
||||
);
|
||||
},
|
||||
isVerified() {
|
||||
return useMainStore().order.payment.insuranceCoverage.isVerified;
|
||||
|
|
@ -198,7 +238,9 @@ export default {
|
|||
return useMainStore().order.currentDeductible;
|
||||
},
|
||||
deductibleBoxValue() {
|
||||
return this.isVerified ? formatAmountInDollars(this.currentDeductible) : VERIFYING_COVERAGE;
|
||||
return this.isVerified
|
||||
? formatAmountInDollars(this.currentDeductible)
|
||||
: VERIFYING_COVERAGE;
|
||||
},
|
||||
getVehicleLines() {
|
||||
const { year, make, model } = useMainStore().order.vehicle;
|
||||
|
|
@ -208,15 +250,27 @@ export default {
|
|||
return [line];
|
||||
},
|
||||
locationAnswers() {
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(this.widget.damageLocations);
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(
|
||||
this.widget.damageLocations
|
||||
);
|
||||
},
|
||||
driverSideDamageAnswers() {
|
||||
const answerContent = getLocationAnswer(damageLocationsSelected.DRIVER, this.locationAnswers);
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(answerContent?.SubWidgetName);
|
||||
const answerContent = getLocationAnswer(
|
||||
damageLocationsSelected.DRIVER,
|
||||
this.locationAnswers
|
||||
);
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(
|
||||
answerContent?.SubWidgetName
|
||||
);
|
||||
},
|
||||
passengerSideDamageAnswers() {
|
||||
const answerContent = getLocationAnswer(damageLocationsSelected.PASSENGER, this.locationAnswers);
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(answerContent?.SubWidgetName);
|
||||
const answerContent = getLocationAnswer(
|
||||
damageLocationsSelected.PASSENGER,
|
||||
this.locationAnswers
|
||||
);
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(
|
||||
answerContent?.SubWidgetName
|
||||
);
|
||||
},
|
||||
getDamageLines() {
|
||||
const { glassToReplace, isRepair } = useMainStore().order.damage;
|
||||
|
|
@ -229,76 +283,108 @@ export default {
|
|||
);
|
||||
},
|
||||
getPreferredShopLines() {
|
||||
const { phoneNumber, address } = useMainStore().order.serviceLocation.provider;
|
||||
const { phoneNumber, address } =
|
||||
useMainStore().order.serviceLocation.provider;
|
||||
const { streetAddress, city, state, zipCode } = address;
|
||||
const displayAddress = formatAddress(streetAddress, null, city, state, zipCode);
|
||||
const displayAddress = formatAddress(
|
||||
streetAddress,
|
||||
null,
|
||||
city,
|
||||
state,
|
||||
zipCode
|
||||
);
|
||||
const displayPhoneNumber = toDisplayPhoneNumber(phoneNumber);
|
||||
return [toTitleCase(this.companyName ?? ''), displayAddress, displayPhoneNumber];
|
||||
return [
|
||||
toTitleCase(this.companyName ?? ''),
|
||||
displayAddress,
|
||||
displayPhoneNumber,
|
||||
];
|
||||
},
|
||||
getContactInfoLines() {
|
||||
const { firstName, lastName, emailAddress, servicePhone } = useMainStore().contactInfo;
|
||||
const { firstName, lastName, emailAddress, servicePhone } =
|
||||
useMainStore().contactInfo;
|
||||
return [
|
||||
`${firstName} ${lastName}`,
|
||||
emailAddress ?? '',
|
||||
toDisplayPhoneNumber(servicePhone)
|
||||
toDisplayPhoneNumber(servicePhone),
|
||||
];
|
||||
}
|
||||
},
|
||||
},
|
||||
methods:
|
||||
{
|
||||
setSections() {
|
||||
const vehicleScenario = useMainStore().isPolicyVehicle
|
||||
? this.navigationScenarios.EDIT_POLICY_VEHICLE
|
||||
: this.navigationScenarios.EDIT_VEHICLE;
|
||||
this.sections = [
|
||||
this.getSection(this.widget.subheader.vehicle, this.getVehicleLines, () => this.navigate(vehicleScenario)),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(this.widget.subheader.damage, this.getDamageLines, () => this.navigate(this.navigationScenarios.EDIT_DAMAGE)),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(this.widget.subheader.shop, this.getPreferredShopLines, () => this.navigate(this.navigationScenarios.EDIT_PREFERRED_SHOP)),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(this.widget.subheader.contactInfo, this.getContactInfoLines, this.openContactDetailsModal)
|
||||
];
|
||||
},
|
||||
getSection(widgetName, lines, onClick) {
|
||||
return {
|
||||
title: this.getCmsContent(widgetName, widgetFields.TEXT_BLOCK_WIDGET.TEXT),
|
||||
lines,
|
||||
onClickEdit: onClick
|
||||
};
|
||||
},
|
||||
forwardButtonAction() {
|
||||
this.navigate(this.navigationScenarios.CLICKED_FORWARD);
|
||||
},
|
||||
navigate(scenario) {
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case 'deductibleAboveZero':
|
||||
return this.isVerified && this.currentDeductible !== 0;
|
||||
case 'zeroDeductible':
|
||||
return this.isVerified && this.currentDeductible === 0;
|
||||
case 'verifyingCoverage':
|
||||
return !this.isVerified;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
openContactDetailsModal() {
|
||||
this.$refs.contactDetailsDrawer.openModal();
|
||||
methods: {
|
||||
setSections() {
|
||||
const vehicleScenario = useMainStore().isPolicyVehicle
|
||||
? this.navigationScenarios.EDIT_POLICY_VEHICLE
|
||||
: this.navigationScenarios.EDIT_VEHICLE;
|
||||
this.sections = [
|
||||
this.getSection(
|
||||
this.widget.subheader.vehicle,
|
||||
this.getVehicleLines,
|
||||
() => this.navigate(vehicleScenario)
|
||||
),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(
|
||||
this.widget.subheader.damage,
|
||||
this.getDamageLines,
|
||||
() => this.navigate(this.navigationScenarios.EDIT_DAMAGE)
|
||||
),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(
|
||||
this.widget.subheader.shop,
|
||||
this.getPreferredShopLines,
|
||||
() =>
|
||||
this.navigate(
|
||||
this.navigationScenarios.EDIT_PREFERRED_SHOP
|
||||
)
|
||||
),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(
|
||||
this.widget.subheader.contactInfo,
|
||||
this.getContactInfoLines,
|
||||
this.openContactDetailsModal
|
||||
),
|
||||
];
|
||||
},
|
||||
getSection(widgetName, lines, onClick) {
|
||||
return {
|
||||
title: this.getCmsContent(
|
||||
widgetName,
|
||||
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
||||
),
|
||||
lines,
|
||||
onClickEdit: onClick,
|
||||
};
|
||||
},
|
||||
forwardButtonAction() {
|
||||
this.navigate(this.navigationScenarios.CLICKED_FORWARD);
|
||||
},
|
||||
navigate(scenario) {
|
||||
this.$router.navigate(scenario, this.$route);
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case 'deductibleAboveZero':
|
||||
return this.isVerified && this.currentDeductible !== 0;
|
||||
case 'zeroDeductible':
|
||||
return this.isVerified && this.currentDeductible === 0;
|
||||
case 'verifyingCoverage':
|
||||
return !this.isVerified;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
openContactDetailsModal() {
|
||||
this.$refs.contactDetailsDrawer.openModal();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.tpa-submit__title--line-height {
|
||||
line-height: map-get($spacers, 6);
|
||||
}
|
||||
|
||||
.text-color--darker-gray {
|
||||
color: $darker-gray
|
||||
color: $darker-gray;
|
||||
}
|
||||
|
||||
.text-color--black {
|
||||
|
|
@ -307,7 +393,6 @@ export default {
|
|||
|
||||
hr {
|
||||
opacity: 1;
|
||||
color: $gray-350
|
||||
color: $gray-350;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,66 +4,94 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row mt-2 px-3">
|
||||
<div class="col">
|
||||
<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" />
|
||||
<damageLocationQuestion
|
||||
ref="damageLocation"
|
||||
v-model="selectedDamageLocations"
|
||||
cmsWidgetName="DamageLocationQuestion"
|
||||
groupName="DamageLocationQuestion" />
|
||||
<windshieldOptions
|
||||
ref="windshieldOptions"
|
||||
v-model="selectedWindshieldOptions"
|
||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-3" />
|
||||
<alert
|
||||
v-if="hasRepairReplaceConflict"
|
||||
class="my-5"
|
||||
cmsWidgetName="HasReplacementConflict"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<sideDoorOptions
|
||||
v-show="!hasRepairReplaceConflict"
|
||||
ref="sideDoorOptions"
|
||||
v-model="sideDoorOptionsData"
|
||||
cmsWidgetName="SideDoorSideQuestion"
|
||||
groupName="SideDoorSideQuestion"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-1" />
|
||||
<replaceOptionsQuestion
|
||||
ref="backGlassOptions"
|
||||
v-model="selectedRearReplaceOptions"
|
||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||
groupName="BackGlassReplaceOptionsQuestion"
|
||||
validationRules="replace-options-required" />
|
||||
<site-footer
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="container-fluid fade-on-route-transition replace-options-question">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 px-0 px-md-2">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</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>
|
||||
|
|
@ -95,7 +123,10 @@ import damageLocationsSelected from '@/constants/damage-locations-selected.js';
|
|||
import { useMainStore } from '@/store';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule('replace-options-required', required(errorMessages.REPLACE_OPTIONS_REQUIRED));
|
||||
defineRule(
|
||||
'replace-options-required',
|
||||
required(errorMessages.REPLACE_OPTIONS_REQUIRED)
|
||||
);
|
||||
|
||||
export default {
|
||||
name: 'vehicle-damage',
|
||||
|
|
@ -111,7 +142,7 @@ export default {
|
|||
replaceOptionsQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
alert
|
||||
alert,
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -119,18 +150,20 @@ export default {
|
|||
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const damageOptionsPromise = store.getDamageOptions(store.order.vehicle.carId);
|
||||
const damageOptionsPromise = store.getDamageOptions(
|
||||
store.order.vehicle.carId
|
||||
);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'damageOptions',
|
||||
promise: damageOptionsPromise
|
||||
}
|
||||
promise: damageOptionsPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -138,13 +171,23 @@ export default {
|
|||
// 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.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
|
||||
);
|
||||
vm.$refs.windshieldOptions.initializeComponent(resultMap.damageOptions.windshieldOptions.availableReplacementOptions);
|
||||
vm.$refs.backGlassOptions.initializeComponent(resultMap.damageOptions.backGlassOptions.availableReplacementOptions);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
|
|
@ -157,77 +200,101 @@ export default {
|
|||
selectedDamageLocations: this.getDamageLocationsFromStore(),
|
||||
sideDoorOptionsData: {
|
||||
selectedDoorSides: this.getDoorSidesFromStore(),
|
||||
selectedDriverSideReplaceOptions: this.getDriverSideReplaceOptionsFromStore(),
|
||||
selectedPassengerSideReplaceOptions: this.getPassengerSideReplaceOptionsFromStore()
|
||||
selectedDriverSideReplaceOptions:
|
||||
this.getDriverSideReplaceOptionsFromStore(),
|
||||
selectedPassengerSideReplaceOptions:
|
||||
this.getPassengerSideReplaceOptionsFromStore(),
|
||||
},
|
||||
selectedWindshieldOptions: this.getWindshieldOptionsFromStore(),
|
||||
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore()
|
||||
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isWindshieldDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD);
|
||||
return this.selectedDamageLocations.some(
|
||||
(selectedDamages) =>
|
||||
selectedDamages.toUpperCase() ===
|
||||
damageLocationsCms.WINDSHIELD
|
||||
);
|
||||
},
|
||||
isSideDoorDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR);
|
||||
return this.selectedDamageLocations.some(
|
||||
(selectedDamages) =>
|
||||
selectedDamages.toUpperCase() ===
|
||||
damageLocationsCms.SIDEDOOR
|
||||
);
|
||||
},
|
||||
isRearWindowDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW);
|
||||
return this.selectedDamageLocations.some(
|
||||
(selectedDamages) =>
|
||||
selectedDamages.toUpperCase() ===
|
||||
damageLocationsCms.REARWINDOW
|
||||
);
|
||||
},
|
||||
isWindshieldRepair() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation
|
||||
&& this.selectedWindshieldOptions.selectedWindshieldDamageType
|
||||
=== damageLocationsSelected.REPAIR
|
||||
this.isWindshieldDamageLocation &&
|
||||
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
||||
damageLocationsSelected.REPAIR
|
||||
);
|
||||
},
|
||||
isDriverSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
|
||||
return this
|
||||
.sideDoorOptionsData.selectedDoorSides
|
||||
.some((selectedDriverSide) => selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE);
|
||||
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);
|
||||
return this.sideDoorOptionsData.selectedDoorSides.some(
|
||||
(selectedPassengerSide) =>
|
||||
selectedPassengerSide.toUpperCase() ===
|
||||
damageLocationsCms.PASSENGERSIDE
|
||||
);
|
||||
},
|
||||
hasRepairReplaceConflict() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation
|
||||
&& this.selectedDamageLocations.length > 1
|
||||
&& this.isWindshieldRepair
|
||||
this.isWindshieldDamageLocation &&
|
||||
this.selectedDamageLocations.length > 1 &&
|
||||
this.isWindshieldRepair
|
||||
);
|
||||
},
|
||||
hasSplitSingleConflict() {
|
||||
if (
|
||||
!this.selectedDamageLocations?.includes('Windshield')
|
||||
|| this.selectedWindshieldOptions.selectedWindshieldDamageType
|
||||
=== damageLocationsSelected.REPAIR
|
||||
|| !this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
|
||||
) return false;
|
||||
!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()
|
||||
)))
|
||||
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];
|
||||
}
|
||||
return this.$route.params[
|
||||
this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
|
|
@ -240,22 +307,32 @@ export default {
|
|||
const glassSelections = [];
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.WINDSHIELD)
|
||||
|| this.mainStore.order.damage.isRepair
|
||||
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
|
||||
))
|
||||
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)
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.REAR
|
||||
)
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.REARWINDOW);
|
||||
}
|
||||
|
|
@ -266,43 +343,62 @@ export default {
|
|||
const windShieldOptions = {
|
||||
selectedWindshieldDamageType: '',
|
||||
selectedWindshieldChipCount: null,
|
||||
selectedWindshieldReplaceOptions: []
|
||||
selectedWindshieldReplaceOptions: [],
|
||||
};
|
||||
|
||||
if (this.mainStore.order.damage.isRepair === undefined) return windshieldOptions;
|
||||
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;
|
||||
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
|
||||
))
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation ===
|
||||
damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.SINGLE
|
||||
)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType = damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(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
|
||||
))
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation ===
|
||||
damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.DRIVER
|
||||
)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType = damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(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
|
||||
))
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation ===
|
||||
damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName ===
|
||||
damageLocationsSelected.PASSENGER
|
||||
)
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType = damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(damageLocationsSelected.PASSENGER);
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.PASSENGER
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -311,13 +407,20 @@ export default {
|
|||
getDoorSidesFromStore() {
|
||||
const doorSides = [];
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.DRIVER)
|
||||
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)
|
||||
this.mainStore.order.damage.glassToReplace?.some(
|
||||
(glass) =>
|
||||
glass.glassLocation ===
|
||||
damageLocationsSelected.PASSENGER
|
||||
)
|
||||
) {
|
||||
doorSides.push(damageLocationsSelected.PASSENGERSIDE);
|
||||
}
|
||||
|
|
@ -347,8 +450,11 @@ export default {
|
|||
return passengerSideReplaceOptions;
|
||||
},
|
||||
getRearReplaceOptionsFromStore() {
|
||||
const rearReplaceOptions = this.mainStore.order.damage
|
||||
.glassToReplace?.filter((glass) => glass.glassLocation === damageLocationsSelected.REAR)[0]?.glassName;
|
||||
const rearReplaceOptions =
|
||||
this.mainStore.order.damage.glassToReplace?.filter(
|
||||
(glass) =>
|
||||
glass.glassLocation === damageLocationsSelected.REAR
|
||||
)[0]?.glassName;
|
||||
|
||||
return rearReplaceOptions;
|
||||
},
|
||||
|
|
@ -360,7 +466,8 @@ export default {
|
|||
);
|
||||
|
||||
if (this.isWindshieldRepair) {
|
||||
const supportingItems = await useMainStore().getSupportingItems();
|
||||
const supportingItems =
|
||||
await useMainStore().getSupportingItems();
|
||||
useMainStore().updateSupportingItems(supportingItems.data);
|
||||
}
|
||||
|
||||
|
|
@ -372,16 +479,22 @@ export default {
|
|||
} else if (this.mainStore.order.vehicle.vin) {
|
||||
// If vin already exists, navigate directly to vin-lookup
|
||||
|
||||
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
|
||||
const partsOrQuestionsResponse =
|
||||
await this.getPartsOrQuestions();
|
||||
if (partsOrQuestionsResponse.error) {
|
||||
// To Do: Need requirement on what to do here
|
||||
window.console.error('Error on retrieving PartsOrQuestions');
|
||||
window.console.error(
|
||||
'Error on retrieving PartsOrQuestions'
|
||||
);
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||
await this.navigateForward(partsOrQuestionsResponse.data.partsOrQuestions, this);
|
||||
await this.navigateForward(
|
||||
partsOrQuestionsResponse.data.partsOrQuestions,
|
||||
this
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
|
||||
|
|
@ -394,42 +507,48 @@ export default {
|
|||
selectedGlassToReplace() {
|
||||
const selectedGlassToReplace = [];
|
||||
if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) {
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach((wsItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.WINDSHIELD,
|
||||
glassName: wsItem
|
||||
});
|
||||
});
|
||||
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
|
||||
});
|
||||
});
|
||||
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
|
||||
});
|
||||
});
|
||||
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach(
|
||||
(passengerItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.PASSENGER,
|
||||
glassName: passengerItem,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isRearWindowDamageLocation) {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.REAR,
|
||||
glassName: this.selectedRearReplaceOptions
|
||||
glassName: this.selectedRearReplaceOptions,
|
||||
});
|
||||
}
|
||||
|
||||
return selectedGlassToReplace;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,32 @@
|
|||
<template>
|
||||
<Form
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<VehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<SiteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-5 mb-2" />
|
||||
<VinLookupMethods
|
||||
ref="VinLookupMethods"
|
||||
v-model="selectedVinLookupMethod"
|
||||
cmsWidgetName="VINLookupMethod"
|
||||
groupName="VinLookupMethods" />
|
||||
<SiteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
class="mt-5"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<div class="select-car-form rounded">
|
||||
<VehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<SiteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-5 mb-2" />
|
||||
<VinLookupMethods
|
||||
ref="VinLookupMethods"
|
||||
v-model="selectedVinLookupMethod"
|
||||
cmsWidgetName="VINLookupMethod"
|
||||
groupName="VinLookupMethods" />
|
||||
<SiteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
class="mt-5"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -61,7 +57,7 @@ export default {
|
|||
SiteHeader,
|
||||
SiteSubHeader,
|
||||
VehicleBanner,
|
||||
VinLookupMethods
|
||||
VinLookupMethods,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -71,8 +67,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -84,13 +80,13 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
selectedVinLookupMethod: null
|
||||
selectedVinLookupMethod: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedVinLookupMethod === null;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisiteValid() {
|
||||
|
|
@ -99,19 +95,28 @@ export default {
|
|||
forwardButtonAction() {
|
||||
switch (this.selectedVinLookupMethod) {
|
||||
case vinLookupMethodSelections.MANUALVIN:
|
||||
this.$router.navigate(this.navigationScenarios.SELECTED_MANUAL_VIN, this.$route);
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_MANUAL_VIN,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
case vinLookupMethodSelections.LICENSEPLATE:
|
||||
this.$router.navigate(this.navigationScenarios.SELECTED_LICENSE_PLATE, this.$route);
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_LICENSE_PLATE,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
case vinLookupMethodSelections.HOMEADDRESS:
|
||||
this.$router.navigate(this.navigationScenarios.SELECTED_HOME_ADDRESS, this.$route);
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_HOME_ADDRESS,
|
||||
this.$route
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
resetDependentState() {}
|
||||
}
|
||||
resetDependentState() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,60 +1,55 @@
|
|||
<template>
|
||||
<Form
|
||||
ref="theForm"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
ref="vehicleBanner"
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<div class="prevent-squish my-5">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<alert
|
||||
id="vehicle-parts-alert"
|
||||
class="rounded border-0 shadow-sm"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertWidget"
|
||||
:isDismissible="false" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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
|
||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
|
||||
:glassLocation="item.glassLocation"
|
||||
:glassName="item.glassName"
|
||||
:colorAnswers="item.colorAnswers"
|
||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
@backClicked="navigateBackByVehicleQuestions"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
ref="vehicleBanner"
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<alert
|
||||
id="vehicle-parts-alert"
|
||||
class="mt-3 mb-3"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertWidget"
|
||||
: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
|
||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||
v-model="
|
||||
selectedGlassParts[
|
||||
item.glassLocation + '-' + item.glassName
|
||||
]
|
||||
"
|
||||
:glassLocation="item.glassLocation"
|
||||
:glassName="item.glassName"
|
||||
:colorAnswers="item.colorAnswers"
|
||||
:alreadyPopulatedPartsData="
|
||||
alreadyPopulatedPartsData
|
||||
" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
@backClicked="navigateBackByVehicleQuestions"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -89,7 +84,7 @@ export default {
|
|||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
siteFooter,
|
||||
alert
|
||||
alert,
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -99,8 +94,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
|
|
@ -109,27 +104,36 @@ export default {
|
|||
|
||||
// Glass Part Question dynamic component
|
||||
Object.keys(vm.$refs)
|
||||
.filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined)
|
||||
.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
|
||||
}));
|
||||
ColorQuestionWidget:
|
||||
resultMap.cmsContent.ColorQuestionWidget,
|
||||
FeatureQuestionWidget:
|
||||
resultMap.cmsContent.FeatureQuestionWidget,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedGlassParts: {},
|
||||
alertWidgetData: Object,
|
||||
alreadyPopulatedPartsData: []
|
||||
alreadyPopulatedPartsData: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedGlassPartNumbers?.length !== this.PartsFromApi.partsOrQuestions?.length;
|
||||
return (
|
||||
this.selectedGlassPartNumbers?.length !==
|
||||
this.PartsFromApi.partsOrQuestions?.length
|
||||
);
|
||||
},
|
||||
selectedGlassPartNumbers() {
|
||||
// Compile all selected parts from the page.
|
||||
// Compile all selected parts from the page.
|
||||
const numberArray = [];
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const glassPart of Object.values(this.selectedGlassParts)) {
|
||||
|
|
@ -152,13 +156,15 @@ export default {
|
|||
FeatureAnswers: [
|
||||
{
|
||||
FeatureAnswerText:
|
||||
p.description === '' ? p.color : p.description,
|
||||
PartNumber: p.partNumber
|
||||
}
|
||||
]
|
||||
p.description === ''
|
||||
? p.color
|
||||
: p.description,
|
||||
PartNumber: p.partNumber,
|
||||
},
|
||||
],
|
||||
});
|
||||
return arr;
|
||||
}, [])
|
||||
}, []),
|
||||
}));
|
||||
|
||||
return mappedData;
|
||||
|
|
@ -170,18 +176,20 @@ export default {
|
|||
|
||||
RefPrefix() {
|
||||
return 'partQuestion';
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.LoadInitialPartsData();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// Check if isRepair is populated and if the pageData we need is here (Parts data)
|
||||
// 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
|
||||
useMainStore().damage.isRepair != null &&
|
||||
useMainStore().pageData(issPageValues.VEHICLE_PARTS) &&
|
||||
Object.keys(
|
||||
useMainStore().pageData(issPageValues.VEHICLE_PARTS)
|
||||
).length !== 0
|
||||
);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
|
|
@ -189,18 +197,25 @@ export default {
|
|||
|
||||
// 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)) {
|
||||
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];
|
||||
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]
|
||||
parts: [currentPart],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -208,7 +223,9 @@ export default {
|
|||
// 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');
|
||||
throw new Error(
|
||||
'Could not match any parts to the selected parts'
|
||||
);
|
||||
}
|
||||
|
||||
this.navigateForward(matchedParts, null);
|
||||
|
|
@ -216,23 +233,26 @@ export default {
|
|||
|
||||
LoadInitialPartsData() {
|
||||
const partsData = this.PartsFromApi;
|
||||
this.alreadyPopulatedPartsData = this.mainStore.lineItems.glassParts === null
|
||||
? []
|
||||
: this.mainStore.lineItems.glassParts;
|
||||
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.
|
||||
// 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;
|
||||
this.selectedGlassParts[
|
||||
`${g.glassLocation}-${g.glassName}`
|
||||
] = p;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -1,77 +1,75 @@
|
|||
<template>
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles position-relative">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="siteSubHeader"
|
||||
justification="center"
|
||||
darkGraySubText />
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@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" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="siteSubHeader"
|
||||
justification="center"
|
||||
darkGraySubText />
|
||||
|
||||
<vehicleQuestion
|
||||
ref="vehicleYearQuestion"
|
||||
v-model="selectedYear"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleYearQuestion"
|
||||
:updateValues="updateYearValues"
|
||||
validationRules="year-required"
|
||||
inputId="yearQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleMakeQuestion"
|
||||
v-model="selectedMake"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleMakeQuestion"
|
||||
:updateValues="updateMakeValues"
|
||||
validationRules="make-required"
|
||||
inputId="makeQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleModelQuestion"
|
||||
v-model="selectedModel"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleModelQuestion"
|
||||
:updateValues="updateModelValues"
|
||||
validationRules="model-required"
|
||||
inputId="modelQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleStyleQuestion"
|
||||
v-model="selectedStyle"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleStyleQuestion"
|
||||
:updateValues="updateStyleValues"
|
||||
validationRules="style-required"
|
||||
inputId="styleQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleYearQuestion"
|
||||
v-model="selectedYear"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleYearQuestion"
|
||||
:updateValues="updateYearValues"
|
||||
validationRules="year-required"
|
||||
inputId="yearQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleMakeQuestion"
|
||||
v-model="selectedMake"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleMakeQuestion"
|
||||
:updateValues="updateMakeValues"
|
||||
validationRules="make-required"
|
||||
inputId="makeQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleModelQuestion"
|
||||
v-model="selectedModel"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleModelQuestion"
|
||||
:updateValues="updateModelValues"
|
||||
validationRules="model-required"
|
||||
inputId="modelQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleStyleQuestion"
|
||||
v-model="selectedStyle"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleStyleQuestion"
|
||||
:updateValues="updateStyleValues"
|
||||
validationRules="style-required"
|
||||
inputId="styleQuestionField" />
|
||||
|
||||
<vehicleBanner
|
||||
ref="banner"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
class="mt-5 mb-3" />
|
||||
<vehicleBanner
|
||||
ref="banner"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
class="mt-5 mb-3" />
|
||||
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -106,7 +104,7 @@ export default {
|
|||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleQuestion
|
||||
vehicleQuestion,
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
|
||||
|
|
@ -118,8 +116,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -131,7 +129,7 @@ export default {
|
|||
},
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
validationRules: String
|
||||
validationRules: String,
|
||||
},
|
||||
data() {
|
||||
const { year, make, model, style } = useMainStore().order.vehicle;
|
||||
|
|
@ -139,13 +137,13 @@ export default {
|
|||
selectedYear: year,
|
||||
selectedMake: make,
|
||||
selectedModel: model,
|
||||
selectedStyle: style
|
||||
selectedStyle: style,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
displayGeneric() {
|
||||
return !this.selectedStyle;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
|
@ -173,7 +171,7 @@ export default {
|
|||
selectedStyle(value) {
|
||||
this.mainStore.updateVehicleStyle(value);
|
||||
this.mainStore.setVehicle();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.vehicleYearQuestion.getNewValues();
|
||||
|
|
@ -198,7 +196,10 @@ export default {
|
|||
navigateForward() {
|
||||
this.mainStore.setVehicle().then(() => {
|
||||
if (this.mainStore.isBailout) {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, this.$route);
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
this.$route
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -219,22 +220,22 @@ export default {
|
|||
},
|
||||
async updateStyleValues() {
|
||||
return this.mainStore.getVehicleStyles();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.select-car-form {
|
||||
margin-left: .75rem;
|
||||
margin-right: .75rem;
|
||||
}
|
||||
.siteSubHeader {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.select-car-form {
|
||||
margin-left: 0.75rem;
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
.siteSubHeader {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.subheader-secondary {
|
||||
margin-top: .5rem;
|
||||
padding: 0px;
|
||||
}
|
||||
.subheader-secondary {
|
||||
margin-top: 0.5rem;
|
||||
padding: 0px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,38 +4,36 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="!carIdIsValid" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<vinLookupAlerts
|
||||
class="mt-5"
|
||||
:activeAlertType="activeVehicleLookupAlertType" />
|
||||
<vinQuestion
|
||||
v-model="vin"
|
||||
:mask="vinMask"
|
||||
:isDisabled="vinPopulatedOnPageLoad"
|
||||
textPosition="left" />
|
||||
<vinLocationInformation />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
class="mt-5"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="!carIdIsValid" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<vinLookupAlerts
|
||||
class="mt-5"
|
||||
:activeAlertType="activeVehicleLookupAlertType" />
|
||||
<vinQuestion
|
||||
v-model="vin"
|
||||
:mask="vinMask"
|
||||
:isDisabled="vinPopulatedOnPageLoad"
|
||||
textPosition="left" />
|
||||
<vinLocationInformation />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
class="mt-5"
|
||||
@backClicked="navigateBack"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -77,12 +75,12 @@ export default {
|
|||
vehicleBanner,
|
||||
vinLocationInformation,
|
||||
vinLookupAlerts,
|
||||
vinQuestion
|
||||
vinQuestion,
|
||||
},
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
provide() {
|
||||
return {
|
||||
vehicleFromLookup: computed(() => this.vehicleFromLookup)
|
||||
vehicleFromLookup: computed(() => this.vehicleFromLookup),
|
||||
};
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -92,8 +90,8 @@ export default {
|
|||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
|
@ -110,20 +108,24 @@ export default {
|
|||
data() {
|
||||
const vin = this.getVinFromStore();
|
||||
return {
|
||||
activeVehicleLookupAlertType: vin?.length > 0 && !this.hasValidCarId() ? vehicleLookupAlertTypes.NOT_FOUND : null,
|
||||
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()
|
||||
vinPopulatedOnPageLoad: vin?.length > 0 && this.hasValidCarId(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isCarIdDifferentFromTheStore() {
|
||||
return (
|
||||
this.vehicleFromLookup !== null && this.hasValidCarId()
|
||||
&& this.vehicleFromLookup.carId !== this.mainStore.vehicle.carId
|
||||
this.vehicleFromLookup !== null &&
|
||||
this.hasValidCarId() &&
|
||||
this.vehicleFromLookup.carId !== this.mainStore.vehicle.carId
|
||||
);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
|
|
@ -131,15 +133,15 @@ export default {
|
|||
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());
|
||||
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.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}`;
|
||||
|
|
@ -148,15 +150,17 @@ export default {
|
|||
},
|
||||
carIdIsValid() {
|
||||
return this.hasValidCarId();
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
vin() {
|
||||
this.resetActiveAlert();
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
this.needToLookupVehicle = true;
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
}
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('SiteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisiteValid() {
|
||||
|
|
@ -166,7 +170,10 @@ export default {
|
|||
return this.mainStore.vehicle.vin;
|
||||
},
|
||||
hasValidCarId() {
|
||||
return this.mainStore.vehicle.carId && this.mainStore.vehicle.carId !== '0';
|
||||
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() {
|
||||
|
|
@ -175,11 +182,16 @@ export default {
|
|||
this.$refs.siteFooter.enableForwardAction();
|
||||
|
||||
if (this.needToLookupVehicle) {
|
||||
const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);
|
||||
const vehicleLookupResponse = await this.lookupVehicleByVin(
|
||||
this.vin
|
||||
);
|
||||
|
||||
if (vehicleLookupResponse.error) {
|
||||
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
|
||||
this.mainStore.setBailout(bailoutMessage.vehicleNotFound(this.vin));
|
||||
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
|
||||
|
|
@ -192,21 +204,30 @@ export default {
|
|||
this.mainStore.resetBailout();
|
||||
|
||||
// Add vin bcs the response from the service doesn't contain vin
|
||||
this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, { vin: this.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.activeVehicleLookupAlertType =
|
||||
vehicleLookupAlertTypes.TWO_IDENTICAL_YMM_MATCHED;
|
||||
this.forwardButtonCarStyle = this.vehicleFromLookup.style;
|
||||
} else {
|
||||
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_MATCHED;
|
||||
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.updateButtonText(
|
||||
`Continue with ${vehicleYearMakeModelStyle}`
|
||||
);
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
|
||||
this.needToLookupVehicle = false;
|
||||
|
|
@ -216,11 +237,17 @@ export default {
|
|||
|
||||
let isSelectedGlassAvailableForVehicle = true;
|
||||
if (this.isCarIdDifferentFromTheStore) {
|
||||
isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(this.vehicleFromLookup.carId);
|
||||
isSelectedGlassAvailableForVehicle =
|
||||
await isGlassAvailableForCarId(
|
||||
this.vehicleFromLookup.carId
|
||||
);
|
||||
}
|
||||
|
||||
// navigate back to vehicle-damage
|
||||
if (this.isCarIdDifferentFromTheStore && !isSelectedGlassAvailableForVehicle) {
|
||||
if (
|
||||
this.isCarIdDifferentFromTheStore &&
|
||||
!isSelectedGlassAvailableForVehicle
|
||||
) {
|
||||
this.mainStore.updateVehicle(this.vehicleFromLookup);
|
||||
this.mainStore.resetDamageState();
|
||||
this.$router.navigate(
|
||||
|
|
@ -256,7 +283,10 @@ export default {
|
|||
}
|
||||
|
||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||
await this.navigateForward(partsOrQuestionsResponse.data.partsOrQuestions, this);
|
||||
await this.navigateForward(
|
||||
partsOrQuestionsResponse.data.partsOrQuestions,
|
||||
this
|
||||
);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
|
@ -266,8 +296,8 @@ export default {
|
|||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status
|
||||
}
|
||||
status: responseError.status,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
@ -277,7 +307,7 @@ export default {
|
|||
resetVehicleFromLookup() {
|
||||
this.vehicleFromLookup = null;
|
||||
},
|
||||
resetDependentState() {}
|
||||
}
|
||||
resetDependentState() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -4,172 +4,142 @@
|
|||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles welcome">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-4" />
|
||||
<div class="container-fluid px-5">
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="policyNumber"
|
||||
v-model="welcomePageModel.policyNumber"
|
||||
inputId="policyNumberField"
|
||||
cmsWidgetName="PolicyNumberQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:isDisabled="isPolicyHolderDisabled"
|
||||
:validationRules="rules.policyNumber" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="row mt-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="policyZip"
|
||||
v-model="welcomePageModel.policyZipCode"
|
||||
inputId="policyZipCode"
|
||||
cmsWidgetName="PolicyZipQuestion"
|
||||
isRequired
|
||||
mask="#####"
|
||||
:isDisabled="isPolicyZipDisabled"
|
||||
:validationRules="rules.policyZip" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="dateOfLoss"
|
||||
v-model="welcomePageModel.dateOfLoss"
|
||||
type="date"
|
||||
cmsWidgetName="DateOfLossQuestion"
|
||||
inputId="dateOfLossField"
|
||||
isRequired
|
||||
:isDisabled="isDateOfLossDisabled"
|
||||
disableAutoFill
|
||||
:max="new Date().toJSON().slice(0, 10)"
|
||||
:min="'1972-12-01'"
|
||||
:validationRules="rules.lossDate" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-4">
|
||||
<div class="col px-0">
|
||||
<textBlock
|
||||
cmsWidgetName="DamageDateEstimateWidget"
|
||||
typeStyle="small"
|
||||
class="mt-2" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<dropdownQuestion
|
||||
id="welcomeDropdown"
|
||||
ref="damageCause"
|
||||
v-model="welcomePageModel.damageCause"
|
||||
cmsWidgetName="DamageCauseQuestion"
|
||||
inputId="damageCauseQuestionField"
|
||||
:options="DamageCauseOptions"
|
||||
disableAutoFill
|
||||
:validationRules="rules.damageOption"
|
||||
placeHolderText="Select an option" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="phoneNumber"
|
||||
v-model="welcomePageModel.phoneNumber"
|
||||
inputId="phoneNumberField"
|
||||
cmsWidgetName="PhoneNumberQuestion"
|
||||
:validationRules="rules.phoneNumber"
|
||||
isRequired
|
||||
:mask="phoneMask"
|
||||
disableAutoFill />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="email"
|
||||
v-model="welcomePageModel.email"
|
||||
inputId="emailField"
|
||||
cmsWidgetName="EmailAddressQuestion"
|
||||
:validationRules="rules.email"
|
||||
isRequired
|
||||
disableAutoFill />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
v-if="displayDamageCityQuestion"
|
||||
ref="damageCity"
|
||||
v-model="welcomePageModel.damageCity"
|
||||
class="mt-4"
|
||||
inputId="damageCityField"
|
||||
cmsWidgetName="DamageCityQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.lossCity" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<dropdownQuestion
|
||||
v-if="displayDamageStateQuestion"
|
||||
id="welcomeDropdown"
|
||||
ref="state"
|
||||
v-model="welcomePageModel.damageState"
|
||||
class="mt-4"
|
||||
cmsWidgetName="DamageStateQuestion"
|
||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||
:options="getStates"
|
||||
:validationRules="rules.lossState"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
placeHolderText="Select an option" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<buttonQuestion
|
||||
v-if="displayGlassOnlyQuestion"
|
||||
ref="glassOnlyDamage"
|
||||
v-model="welcomePageModel.isDamageGlassOnly"
|
||||
class="px-0 mt-4"
|
||||
cmsWidgetName="GlassOnlyQuestion"
|
||||
inputId="isDamageGlassOnly"
|
||||
:answers="DamageGlassOnlyOptions"
|
||||
:questionText="DamageGlassOnlyQuestion"
|
||||
groupName="glassOnlyDamageOption"
|
||||
buttonTypeString="listButtonHorizontal"
|
||||
:validationRules="rules.damageOption"
|
||||
isRequired
|
||||
isSmallQuestionLabelText
|
||||
disableAutoFill />
|
||||
</div>
|
||||
<div
|
||||
id="welcomeFooter"
|
||||
class="row position-sticky top-100">
|
||||
<div class="col">
|
||||
<alert
|
||||
v-if="displayInvalidZipAlert"
|
||||
ref="alertInvalidZip"
|
||||
class="my-4"
|
||||
cmsWidgetName="AlertInvalidZipWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-3"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
<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 cmsWidgetName="SiteHeaderWidget" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-4" />
|
||||
<textboxQuestion
|
||||
ref="policyNumber"
|
||||
v-model="welcomePageModel.policyNumber"
|
||||
inputId="policyNumberField"
|
||||
cmsWidgetName="PolicyNumberQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:isDisabled="isPolicyHolderDisabled"
|
||||
:validationRules="rules.policyNumber"
|
||||
class="mb-3" />
|
||||
<textboxQuestion
|
||||
ref="policyZip"
|
||||
v-model="welcomePageModel.policyZipCode"
|
||||
inputId="policyZipCode"
|
||||
cmsWidgetName="PolicyZipQuestion"
|
||||
isRequired
|
||||
mask="#####"
|
||||
:isDisabled="isPolicyZipDisabled"
|
||||
:validationRules="rules.policyZip"
|
||||
class="mb-3" />
|
||||
<textboxQuestion
|
||||
ref="dateOfLoss"
|
||||
v-model="welcomePageModel.dateOfLoss"
|
||||
type="date"
|
||||
cmsWidgetName="DateOfLossQuestion"
|
||||
inputId="dateOfLossField"
|
||||
isRequired
|
||||
:isDisabled="isDateOfLossDisabled"
|
||||
disableAutoFill
|
||||
:max="new Date().toJSON().slice(0, 10)"
|
||||
:min="'1972-12-01'"
|
||||
:validationRules="rules.lossDate"
|
||||
class="mb-3" />
|
||||
<textBlock
|
||||
cmsWidgetName="DamageDateEstimateWidget"
|
||||
typeStyle="small"
|
||||
class="mb-3" />
|
||||
<dropdownQuestion
|
||||
id="welcomeDropdown"
|
||||
ref="damageCause"
|
||||
v-model="welcomePageModel.damageCause"
|
||||
cmsWidgetName="DamageCauseQuestion"
|
||||
inputId="damageCauseQuestionField"
|
||||
:options="DamageCauseOptions"
|
||||
disableAutoFill
|
||||
:validationRules="rules.damageOption"
|
||||
placeHolderText="Select an option"
|
||||
class="mb-3" />
|
||||
<textboxQuestion
|
||||
ref="phoneNumber"
|
||||
v-model="welcomePageModel.phoneNumber"
|
||||
inputId="phoneNumberField"
|
||||
cmsWidgetName="PhoneNumberQuestion"
|
||||
:validationRules="rules.phoneNumber"
|
||||
isRequired
|
||||
:mask="phoneMask"
|
||||
disableAutoFill
|
||||
class="mb-3" />
|
||||
<textboxQuestion
|
||||
ref="email"
|
||||
v-model="welcomePageModel.email"
|
||||
inputId="emailField"
|
||||
cmsWidgetName="EmailAddressQuestion"
|
||||
:validationRules="rules.email"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
class="mb-3" />
|
||||
<textboxQuestion
|
||||
v-if="displayDamageCityQuestion"
|
||||
ref="damageCity"
|
||||
v-model="welcomePageModel.damageCity"
|
||||
class="mb-3"
|
||||
inputId="damageCityField"
|
||||
cmsWidgetName="DamageCityQuestion"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
:validationRules="rules.lossCity" />
|
||||
<dropdownQuestion
|
||||
v-if="displayDamageStateQuestion"
|
||||
id="welcomeDropdown"
|
||||
ref="state"
|
||||
v-model="welcomePageModel.damageState"
|
||||
class="mb-3"
|
||||
cmsWidgetName="DamageStateQuestion"
|
||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||
:options="getStates"
|
||||
:validationRules="rules.lossState"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
placeHolderText="Select an option" />
|
||||
<buttonQuestion
|
||||
v-if="displayGlassOnlyQuestion"
|
||||
ref="glassOnlyDamage"
|
||||
v-model="welcomePageModel.isDamageGlassOnly"
|
||||
class="px-0 mt-4"
|
||||
cmsWidgetName="GlassOnlyQuestion"
|
||||
inputId="isDamageGlassOnly"
|
||||
:answers="DamageGlassOnlyOptions"
|
||||
:questionText="DamageGlassOnlyQuestion"
|
||||
groupName="glassOnlyDamageOption"
|
||||
buttonTypeString="listButtonHorizontal"
|
||||
:validationRules="rules.damageOption"
|
||||
isRequired
|
||||
isSmallQuestionLabelText
|
||||
disableAutoFill />
|
||||
<div id="welcomeFooter" class="row">
|
||||
<alert
|
||||
v-if="displayInvalidZipAlert"
|
||||
ref="alertInvalidZip"
|
||||
class="my-4"
|
||||
cmsWidgetName="AlertInvalidZipWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-3"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@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 />
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -185,9 +155,14 @@ import textboxQuestion from '@/digital-components/textbox-question/textbox-quest
|
|||
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 {
|
||||
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';
|
||||
|
|
@ -201,13 +176,17 @@ import globalMethods from '@/global-methods';
|
|||
import { endpoints } from '@/constants/endpoints';
|
||||
|
||||
// define validation rules
|
||||
defineRule('damage-option-required', required(errorMessages.DAMAGE_OPTION_REQUIRED));
|
||||
defineRule(
|
||||
'damage-option-required',
|
||||
required(errorMessages.DAMAGE_OPTION_REQUIRED)
|
||||
);
|
||||
|
||||
export default {
|
||||
name: 'welcome-page',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
footerImage,
|
||||
alert,
|
||||
buttonQuestion,
|
||||
textboxQuestion,
|
||||
|
|
@ -215,24 +194,25 @@ export default {
|
|||
siteFooter,
|
||||
textBlock,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
const cmsGlobalSiteHeaderContentPromise = fetchGlobalCmsContent('iss-siteheader');
|
||||
const cmsGlobalSiteHeaderContentPromise =
|
||||
fetchGlobalCmsContent('iss-siteheader');
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'globalSiteHeaderCmsContent',
|
||||
promise: cmsGlobalSiteHeaderContentPromise
|
||||
}
|
||||
promise: cmsGlobalSiteHeaderContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
|
|
@ -264,13 +244,16 @@ export default {
|
|||
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}`
|
||||
}
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
DamageCauseOptions() {
|
||||
const damageCauseAnswers = this.getCmsContent('DamageCauseQuestion', 'Answers');
|
||||
const damageCauseAnswers = this.getCmsContent(
|
||||
'DamageCauseQuestion',
|
||||
'Answers'
|
||||
);
|
||||
const damageCauseAnswersObj = {};
|
||||
if (damageCauseAnswers) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
|
@ -317,16 +300,18 @@ export default {
|
|||
},
|
||||
phoneMask() {
|
||||
return MaskaFormattedMasks.PHONE_NUMBER;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async forwardButtonAction() {
|
||||
await this.mainStore.validateZip({ zip: this.welcomePageModel.policyZipCode })
|
||||
await this.mainStore
|
||||
.validateZip({ zip: this.welcomePageModel.policyZipCode })
|
||||
.then(async (zipInfo) => {
|
||||
if (zipInfo?.data?.isValid === true) {
|
||||
this.mainStore.updatePolicyData(this.welcomePageModel);
|
||||
|
||||
this.mainStore.order.serviceLocation.zipCodeCtu = zipInfo.data.zipCodeCtu?.toString();
|
||||
this.mainStore.order.serviceLocation.zipCodeCtu =
|
||||
zipInfo.data.zipCodeCtu?.toString();
|
||||
|
||||
const billToInfo = await this.getBillToInfo(
|
||||
this.mainStore.issConfig.parentAccountNumber,
|
||||
|
|
@ -334,16 +319,31 @@ export default {
|
|||
);
|
||||
|
||||
if (billToInfo !== null) {
|
||||
this.mainStore.issConfig.billToAccountNumber = billToInfo.billToAccountNumber;
|
||||
this.mainStore.issConfig.itacCashBillToNumber = billToInfo.itacCashBillToNumber;
|
||||
this.mainStore.issConfig.itacFnrBillToNumber = billToInfo.itacFnrBillToNumber;
|
||||
this.mainStore.issConfig.billToAccountNumber =
|
||||
billToInfo.billToAccountNumber;
|
||||
this.mainStore.issConfig.itacCashBillToNumber =
|
||||
billToInfo.itacCashBillToNumber;
|
||||
this.mainStore.issConfig.itacFnrBillToNumber =
|
||||
billToInfo.itacFnrBillToNumber;
|
||||
}
|
||||
|
||||
await this.mainStore.getDuplicateReferrals()
|
||||
.then(() => {}, () => {})
|
||||
await this.mainStore
|
||||
.getDuplicateReferrals()
|
||||
.then(
|
||||
() => {},
|
||||
() => {}
|
||||
)
|
||||
.finally(async () => {
|
||||
if (this.isCoverageEnabled && !this.maxCoverageLookupAttemptsReached) {
|
||||
await this.mainStore.getCoveragePolicyInfo()?.then(() => {}, () => {});
|
||||
if (
|
||||
this.isCoverageEnabled &&
|
||||
!this.maxCoverageLookupAttemptsReached
|
||||
) {
|
||||
await this.mainStore
|
||||
.getCoveragePolicyInfo()
|
||||
?.then(
|
||||
() => {},
|
||||
() => {}
|
||||
);
|
||||
} else {
|
||||
this.mainStore.order.policy.policyLookupSuccessful = false;
|
||||
}
|
||||
|
|
@ -355,7 +355,6 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
async getBillToInfo(parentAccountNumber, providerNumber) {
|
||||
try {
|
||||
const payload = {
|
||||
|
|
@ -363,25 +362,29 @@ export default {
|
|||
providerNumber: providerNumber.toString(),
|
||||
billToSelectionCriteria: {
|
||||
typeOfClaim: 'GLASS ONLY',
|
||||
lineOfBusiness: 'PERSONAL'
|
||||
}
|
||||
lineOfBusiness: 'PERSONAL',
|
||||
},
|
||||
};
|
||||
|
||||
const response = await globalMethods.callHttpClient({
|
||||
method: endpoints.GetBillToInfo.method,
|
||||
endpoint: endpoints.GetBillToInfo.url,
|
||||
payload
|
||||
payload,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
console.error(`Error Status Code: ${err.data?.status}: ${err.data?.title}`);
|
||||
console.error(
|
||||
`Error Status Code: ${err.data?.status}: ${err.data?.title}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
navigateForward() {
|
||||
if (this.mainStore.applicationUser.duplicateOrders?.length > 0 ?? false) {
|
||||
if (
|
||||
this.mainStore.applicationUser.duplicateOrders?.length > 0 ??
|
||||
false
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
|
||||
this.$route,
|
||||
|
|
@ -392,7 +395,8 @@ export default {
|
|||
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.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
|
|
@ -400,7 +404,8 @@ export default {
|
|||
} else {
|
||||
// navigate to vehicle-selection page (manual entry)
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.navigationScenarios
|
||||
.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
|
||||
|
|
@ -424,19 +429,26 @@ export default {
|
|||
damageCause: this.mainStore.order.policy.damageCause,
|
||||
damageState: this.mainStore.order.policy.damageState,
|
||||
damageCity: this.mainStore.order.policy.damageCity,
|
||||
isDamageGlassOnly: this.mainStore.order.policy.isDamageGlassOnly,
|
||||
isDamageGlassOnly:
|
||||
this.mainStore.order.policy.isDamageGlassOnly,
|
||||
phoneNumber: this.mainStore.order.customer.phoneNumber,
|
||||
email: this.mainStore.order.customer.emailAddress,
|
||||
isPolicyNumberDisabled: this.mainStore.order.policy.isPolicyNumberDisabled
|
||||
isPolicyNumberDisabled:
|
||||
this.mainStore.order.policy.isPolicyNumberDisabled,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.page-container-grouped-styles.welcome {
|
||||
height: auto;
|
||||
<style lang="scss" scoped>
|
||||
form {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,35 +1,61 @@
|
|||
// Common/Global Styles
|
||||
// Use this file for global styles that don't or won't have their own stylesheet
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
font-size: 16px;
|
||||
background-color: #fff;
|
||||
color: #4D5151;
|
||||
|
||||
color: #4d5151;
|
||||
.container-fluid {
|
||||
max-width: 576px; //Remove once desktop app is complete
|
||||
|
||||
&.container-shadow {
|
||||
box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.15); //Use instead of Bootstrap's helper
|
||||
}
|
||||
|
||||
&.make-tall {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.prevent-squish {
|
||||
overflow-x: unset;
|
||||
}
|
||||
&.page-container-grouped-styles {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
// Set max-width on columns to prevent overly-wide
|
||||
// components on extra wide screens.
|
||||
.col-md-6 {
|
||||
max-width: 472px;
|
||||
@include media-breakpoint-up(xl) {
|
||||
max-width: 708px;
|
||||
}
|
||||
.col {
|
||||
max-width: 236px;
|
||||
&.one-list-card-width {
|
||||
max-width: 472px;
|
||||
@include media-breakpoint-up(xl) {
|
||||
max-width: 66.6666666%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.shop-question {
|
||||
.col {
|
||||
max-width: 472px;
|
||||
@include media-breakpoint-up(xl) {
|
||||
max-width: 66.6666666%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.col-xl-4 {
|
||||
max-width: 472px;
|
||||
.col {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
//END set max-width on columns
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.container,
|
||||
.container-fluid {
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sub-container {
|
||||
|
|
@ -38,7 +64,6 @@ body {
|
|||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,50 +75,12 @@ body {
|
|||
height: 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pac-container {
|
||||
z-index: 10000 !important;
|
||||
}
|
||||
|
||||
.page-container-grouped-styles {
|
||||
@extend .container-fluid, .shadow, .p-0, .position-relative, .make-tall;
|
||||
}
|
||||
|
||||
//Footer modal backdrop adjustments for positioning
|
||||
.modal-backdrop {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
max-width: 576px;
|
||||
|
||||
&.show {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll page when modal isn't open
|
||||
.fade-on-route-transition {
|
||||
height: calc(100% - 10px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
// Prevent scroll when modal is open
|
||||
&.modal-open {
|
||||
div.page-container-grouped-styles {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fade-on-route-transition {
|
||||
}
|
||||
.modal-open {
|
||||
.container-fluid {
|
||||
&.fade-on-route-transition {
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-text {
|
||||
display: inline;
|
||||
color: $blue;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,13 +180,12 @@ $spacers: (
|
|||
//Line Height
|
||||
|
||||
|
||||
//Grid breakpoints
|
||||
//Bootstrap Grid Breakpoints - Use these breakpoints only
|
||||
$grid-breakpoints: (
|
||||
xs: 0,
|
||||
sm: 576px,
|
||||
md: 838px,
|
||||
lg: 1074px,
|
||||
xl: 1416px,
|
||||
md: 768px,
|
||||
xl: 1200px,
|
||||
xxl: 1440px,
|
||||
);
|
||||
|
||||
//Shadow
|
||||
|
|
|
|||
|
|
@ -1,33 +1,38 @@
|
|||
<template>
|
||||
<a
|
||||
v-if="linkType === 'navigation'"
|
||||
class="navigation-link"
|
||||
:href="href"
|
||||
@click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
v-if="linkType === 'navigation'"
|
||||
class="navigation-link"
|
||||
:href="href"
|
||||
@click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="linkType === 'footer'"
|
||||
class="footer-link"
|
||||
:href="href"
|
||||
target="_blank"
|
||||
@click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
v-else-if="linkType === 'footer'"
|
||||
class="footer-link"
|
||||
:href="href"
|
||||
target="_blank"
|
||||
@click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="linkType === 'textSmall'"
|
||||
class="small"
|
||||
:href="href"
|
||||
@click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
v-else-if="linkType === 'textSmall'"
|
||||
class="small"
|
||||
:href="href"
|
||||
@click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
</a>
|
||||
<a v-else-if="linkType === 'text'" :href="href" @click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="linkType === 'text'"
|
||||
:href="href"
|
||||
@click="handleClick">
|
||||
{{ text }}<slot name="after-text"></slot>
|
||||
</a>
|
||||
</template>
|
||||
v-else-if="linkType === 'newWindowLink'"
|
||||
class="new-window-link"
|
||||
:href="href"
|
||||
target="_blank"
|
||||
@click="handleClick"
|
||||
>{{ text }}<slot name="after-text"></slot
|
||||
></a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
|
@ -36,8 +41,8 @@ export default {
|
|||
linkType: String,
|
||||
text: String,
|
||||
href: {
|
||||
type: String
|
||||
}
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
emits: ['click-event'],
|
||||
methods: {
|
||||
|
|
@ -49,13 +54,13 @@ export default {
|
|||
true
|
||||
);
|
||||
this.$emit('click-event');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a {
|
||||
a {
|
||||
color: $blue;
|
||||
text-underline-offset: 5px;
|
||||
line-height: 2;
|
||||
|
|
@ -63,31 +68,32 @@ export default {
|
|||
font-weight: 500;
|
||||
max-width: fit-content;
|
||||
&:hover {
|
||||
color: $blue-700;
|
||||
color: $blue-700;
|
||||
}
|
||||
&.small {
|
||||
line-height: 24px;
|
||||
&:hover {
|
||||
color: $blue-700;
|
||||
}
|
||||
line-height: 24px;
|
||||
&:hover {
|
||||
color: $blue-700;
|
||||
}
|
||||
}
|
||||
&.navigation-link {
|
||||
color: $black;
|
||||
line-height: 26px;
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
&.navigation-link,
|
||||
&.new-window-link {
|
||||
color: $black;
|
||||
line-height: 26px;
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
&.footer-link {
|
||||
color: $gray-600;
|
||||
text-decoration: none;
|
||||
line-height: 20px;
|
||||
padding: 0 0 2px 0;
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
&:hover {
|
||||
color: $gray-600;
|
||||
text-decoration: none;
|
||||
line-height: 20px;
|
||||
padding: 0 0 2px 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
&:hover {
|
||||
padding: 0 0 2px 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue