WIP update grid on each page.
This commit is contained in:
parent
68e0929c7d
commit
7906d0d13d
12 changed files with 1015 additions and 1004 deletions
|
|
@ -1,27 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<Form
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" autocomplete="off">
|
||||||
@submit="onSubmit"
|
|
||||||
@invalid-submit="onInvalidSubmit"
|
<div class="container-fluid">
|
||||||
ref="theForm"
|
<div class="row">
|
||||||
v-slot="{ meta }"
|
<div class="col">
|
||||||
autocomplete="off">
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||||
<div class="page-container-grouped-styles">
|
</div>
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
</div>
|
||||||
<vehicleBanner
|
<div class="row">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
ref="vehicleBanner"
|
<div class="col-md-8 col-lg-6">
|
||||||
:displayGenericVehicleImage="false" />
|
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
<vehicleBanner
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
ref="vehicleBanner"
|
||||||
<alert
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
||||||
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
||||||
|
|
||||||
|
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
||||||
|
|
||||||
|
<alert
|
||||||
ref="alertVinNotFound"
|
ref="alertVinNotFound"
|
||||||
v-if="displayVinNotFoundAlert"
|
v-if="displayVinNotFoundAlert"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="AlertVinNotFoundWidget"
|
cmsWidgetName="AlertVinNotFoundWidget"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
<alert
|
|
||||||
|
<alert
|
||||||
ref="alertMatchedDifferentVehicle"
|
ref="alertMatchedDifferentVehicle"
|
||||||
v-if="displayMatchedDifferentVehicleAlert"
|
v-if="displayMatchedDifferentVehicleAlert"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
|
|
@ -29,14 +36,16 @@
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
alertClass="alert-warning"
|
alertClass="alert-warning"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
<alert
|
|
||||||
|
<alert
|
||||||
ref="alertInvalidZip"
|
ref="alertInvalidZip"
|
||||||
v-if="displayInvalidZipAlert"
|
v-if="displayInvalidZipAlert"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
<alert
|
|
||||||
|
<alert
|
||||||
ref="alertNonServiceableZip"
|
ref="alertNonServiceableZip"
|
||||||
v-if="displayNonServiceableZipAlert"
|
v-if="displayNonServiceableZipAlert"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
|
|
@ -44,18 +53,22 @@
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
<alert
|
|
||||||
|
<alert
|
||||||
ref="alertVinLookupsByHomeAddressNotAllowed"
|
ref="alertVinLookupsByHomeAddressNotAllowed"
|
||||||
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
<transition name="fade" mode="out-in">
|
|
||||||
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
|
<transition name="fade" mode="out-in">
|
||||||
<div class="row mt-4 mb-1">
|
|
||||||
<div class="col">
|
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
|
||||||
<textboxQuestion
|
|
||||||
|
<div class="row mt-4 mb-1">
|
||||||
|
<div class="col">
|
||||||
|
<textboxQuestion
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
v-model="serviceZipCode"
|
v-model="serviceZipCode"
|
||||||
ref="serviceZip"
|
ref="serviceZip"
|
||||||
|
|
@ -63,17 +76,21 @@
|
||||||
aria-haspopup=""
|
aria-haspopup=""
|
||||||
mask="#####"
|
mask="#####"
|
||||||
validationRules="service-zip-required|service-zip-format" />
|
validationRules="service-zip-required|service-zip-format" />
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</transition>
|
||||||
</transition>
|
<navbar
|
||||||
<navbar
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isDisabled="!meta.valid"
|
:isDisabled="!meta.valid"
|
||||||
@ForwardClicked="forwardButtonAction"
|
@ForwardClicked="forwardButtonAction"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
:isForwardActionDisabled="!meta.valid" />
|
:isForwardActionDisabled="!meta.valid" />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -227,12 +244,12 @@ export default {
|
||||||
{
|
{
|
||||||
resultKey: "serviceZipValidationResponse",
|
resultKey: "serviceZipValidationResponse",
|
||||||
promise: this.serviceZipCode
|
promise: this.serviceZipCode
|
||||||
? this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
? this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
||||||
zip: this.serviceZipCode,
|
zip: this.serviceZipCode,
|
||||||
})
|
})
|
||||||
: this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
: this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
||||||
zip: this.customerQuestions.addressQuestions.zipCode,
|
zip: this.customerQuestions.addressQuestions.zipCode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -317,9 +334,9 @@ export default {
|
||||||
{
|
{
|
||||||
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||||
vehicleInfo:
|
vehicleInfo:
|
||||||
Object.keys(vehicleInfoToCommit).length === 0
|
Object.keys(vehicleInfoToCommit).length === 0
|
||||||
? this.$store.getters.vehicle
|
? this.$store.getters.vehicle
|
||||||
: vehicleInfoToCommit,
|
: vehicleInfoToCommit,
|
||||||
customerInfo: {
|
customerInfo: {
|
||||||
firstName: this.customerQuestions.firstName,
|
firstName: this.customerQuestions.firstName,
|
||||||
lastName: this.customerQuestions.lastName,
|
lastName: this.customerQuestions.lastName,
|
||||||
|
|
@ -389,8 +406,8 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
AlertNonServiceableZipHeader() {
|
AlertNonServiceableZipHeader() {
|
||||||
const zipCode = this.serviceZipCode
|
const zipCode = this.serviceZipCode
|
||||||
? this.serviceZipCode
|
? this.serviceZipCode
|
||||||
: this.customerQuestions.addressQuestions.zipCode;
|
: this.customerQuestions.addressQuestions.zipCode;
|
||||||
const text = this.getCmsContent(
|
const text = this.getCmsContent(
|
||||||
"AlertNonServiceableZipWidget",
|
"AlertNonServiceableZipWidget",
|
||||||
"HeadlineText"
|
"HeadlineText"
|
||||||
|
|
@ -411,9 +428,9 @@ export default {
|
||||||
const vinYmmExpected = `${this.$store.getters.vehicle.year} ${this.$store.getters.vehicle.make} ${this.$store.getters.vehicle.model}`;
|
const vinYmmExpected = `${this.$store.getters.vehicle.year} ${this.$store.getters.vehicle.make} ${this.$store.getters.vehicle.model}`;
|
||||||
|
|
||||||
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
|
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
|
||||||
.replaceAll("{custom:glassText}", getDamageString())
|
.replaceAll("{custom:glassText}", getDamageString())
|
||||||
.replaceAll("{custom:vinYmmFound}", vinYmmFound)
|
.replaceAll("{custom:vinYmmFound}", vinYmmFound)
|
||||||
.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
|
.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
||||||
|
|
@ -7,64 +7,62 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="my-5" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="my-5" />
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="FirstNameWidget"
|
cmsWidgetName="FirstNameWidget"
|
||||||
v-model="firstName"
|
v-model="firstName"
|
||||||
ref="firstName"
|
ref="firstName"
|
||||||
customInputId="firstName"
|
customInputId="firstName"
|
||||||
validationRules="first-name-required" />
|
validationRules="first-name-required" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="LastNameWidget"
|
cmsWidgetName="LastNameWidget"
|
||||||
v-model="lastName"
|
v-model="lastName"
|
||||||
ref="lastName"
|
ref="lastName"
|
||||||
customInputId="lastName"
|
customInputId="lastName"
|
||||||
validationRules="last-name-required" />
|
validationRules="last-name-required" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="emailQuestionWidget"
|
cmsWidgetName="emailQuestionWidget"
|
||||||
v-model="emailAddress"
|
v-model="emailAddress"
|
||||||
inputId="email"
|
inputId="email"
|
||||||
validationRules="email-address-required|email-address-format" />
|
validationRules="email-address-required|email-address-format" />
|
||||||
|
|
||||||
<phoneNumberQuestion
|
<phoneNumberQuestion
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="PhoneNumberQuestionWidget"
|
cmsWidgetName="PhoneNumberQuestionWidget"
|
||||||
v-model="phoneNumber"
|
v-model="phoneNumber"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="phone-number-required" />
|
validationRules="phone-number-required" />
|
||||||
|
|
||||||
<checkboxQuestion
|
<checkboxQuestion
|
||||||
class="mb-5"
|
class="mb-5"
|
||||||
cmsWidgetName="TextMeQuestionWidget"
|
cmsWidgetName="TextMeQuestionWidget"
|
||||||
v-model="isSmsOptIn" />
|
v-model="isSmsOptIn" />
|
||||||
|
|
||||||
<textareaQuestion
|
<textareaQuestion
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
v-model="techNotes"
|
v-model="techNotes"
|
||||||
cmsWidgetName="TextAreaContentWidget"
|
cmsWidgetName="TextAreaContentWidget"
|
||||||
maxLength="250" />
|
maxLength="250" />
|
||||||
|
|
||||||
<textBlock cmsWidgetName="DisclaimerCopyWidget" typeStyle="caption" />
|
<textBlock cmsWidgetName="DisclaimerCopyWidget" typeStyle="caption" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,81 +8,79 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
|
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
|
||||||
<funnelSubHeader class="pb-4" cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader class="pb-4" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div v-if="!skipVin">
|
<div v-if="!skipVin">
|
||||||
<div class="vinlookupquestion" v-html="this.VinLookupQuestionText"></div>
|
<div class="vinlookupquestion" v-html="this.VinLookupQuestionText"></div>
|
||||||
<buttonQuestion
|
<buttonQuestion
|
||||||
cmsWidgetName="VinLookupMethod"
|
cmsWidgetName="VinLookupMethod"
|
||||||
:answers="answersFromCms"
|
:answers="answersFromCms"
|
||||||
groupName="vinLookupMethodOption"
|
groupName="vinLookupMethodOption"
|
||||||
buttonTypeString="listButton"
|
buttonTypeString="listButton"
|
||||||
v-model="selectedVinLookupMethod"
|
v-model="selectedVinLookupMethod"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="option-required"
|
validationRules="option-required"
|
||||||
:logDisplayedValuesEvent="true" />
|
:logDisplayedValuesEvent="true" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<alert
|
<alert
|
||||||
class="my-4"
|
class="my-4"
|
||||||
:cmsWidgetName="alertInfo"
|
:cmsWidgetName="alertInfo"
|
||||||
alertClass="alert-info"
|
alertClass="alert-info"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
v-model="serviceZipCode"
|
v-model="serviceZipCode"
|
||||||
inputId="serviceZipCode"
|
inputId="serviceZipCode"
|
||||||
mask="#####"
|
mask="#####"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="zip-required|zip-format" />
|
validationRules="zip-required|zip-format" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="EmailAddressQuestionWidget"
|
cmsWidgetName="EmailAddressQuestionWidget"
|
||||||
v-model="emailAddress"
|
v-model="emailAddress"
|
||||||
inputId="emailAddress"
|
inputId="emailAddress"
|
||||||
isRequired
|
isRequired
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
validationRules="email-address-required|email-address-format" />
|
validationRules="email-address-required|email-address-format" />
|
||||||
<textBlock
|
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||||
cmsWidgetName="QuoteEmailTextBlockWidget"
|
|
||||||
typeStyle="caption" />
|
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="alertInvalidZip"
|
ref="alertInvalidZip"
|
||||||
v-if="displayInvalidZipAlert"
|
v-if="displayInvalidZipAlert"
|
||||||
class="my-4"
|
class="my-4"
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
class="my-4"
|
class="my-4"
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
v-model="customAlertData"
|
v-model="customAlertData"
|
||||||
v-if="displayNonServiceableZipAlert"
|
v-if="displayNonServiceableZipAlert"
|
||||||
alertClass="alert-danger" />
|
alertClass="alert-danger" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -161,8 +159,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE)
|
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE)
|
||||||
? lowerCaseParams.get(queryStrings.ZIP_CODE)
|
? lowerCaseParams.get(queryStrings.ZIP_CODE)
|
||||||
: store.getters.order.serviceLocation.zipCode;
|
: store.getters.order.serviceLocation.zipCode;
|
||||||
|
|
||||||
var vinByAddressPromise;
|
var vinByAddressPromise;
|
||||||
if (zip) {
|
if (zip) {
|
||||||
|
|
@ -180,10 +178,10 @@ export default {
|
||||||
promise: cmsContentPromise,
|
promise: cmsContentPromise,
|
||||||
},
|
},
|
||||||
zip != null &&
|
zip != null &&
|
||||||
zip != undefined && {
|
zip != undefined && {
|
||||||
resultKey: "vinByAddress",
|
resultKey: "vinByAddress",
|
||||||
promise: vinByAddressPromise,
|
promise: vinByAddressPromise,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
@ -195,13 +193,13 @@ export default {
|
||||||
vm.skipVinNotRepair = skipVinNotRepair;
|
vm.skipVinNotRepair = skipVinNotRepair;
|
||||||
if (resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.includes("|")) {
|
if (resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.includes("|")) {
|
||||||
const forwardTextOption =
|
const forwardTextOption =
|
||||||
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.split("|");
|
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.split("|");
|
||||||
if (skipVin) {
|
if (skipVin) {
|
||||||
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText =
|
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText =
|
||||||
forwardTextOption[1];
|
forwardTextOption[1];
|
||||||
} else {
|
} else {
|
||||||
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText =
|
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText =
|
||||||
forwardTextOption[0];
|
forwardTextOption[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,7 +257,7 @@ export default {
|
||||||
|
|
||||||
const payment = this.$store.getters.payment;
|
const payment = this.$store.getters.payment;
|
||||||
const vehicleChangedDuringPolicyLookupInHeritage =
|
const vehicleChangedDuringPolicyLookupInHeritage =
|
||||||
payment.isInsurance && payment.insuranceCoverage.coverageStatus;
|
payment.isInsurance && payment.insuranceCoverage.coverageStatus;
|
||||||
if (vehicleChangedDuringPolicyLookupInHeritage) {
|
if (vehicleChangedDuringPolicyLookupInHeritage) {
|
||||||
navigateToHeritageFunnel({
|
navigateToHeritageFunnel({
|
||||||
shouldSaveSession: true,
|
shouldSaveSession: true,
|
||||||
|
|
|
||||||
|
|
@ -7,90 +7,87 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false" />
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
||||||
v-model="licensePlate"
|
v-model="licensePlate"
|
||||||
isRequired
|
isRequired
|
||||||
customInputId="licensePlate"
|
customInputId="licensePlate"
|
||||||
validationRules="license-plate-required" />
|
validationRules="license-plate-required" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="RegistrationZipQuestionWidget"
|
cmsWidgetName="RegistrationZipQuestionWidget"
|
||||||
v-model="registrationZipCode"
|
v-model="registrationZipCode"
|
||||||
customInputId="zip"
|
customInputId="zip"
|
||||||
mask="#####"
|
mask="#####"
|
||||||
validationRules="registration-zip-required|zip-format" />
|
validationRules="registration-zip-required|zip-format" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="EmailAddressQuestionWidget"
|
cmsWidgetName="EmailAddressQuestionWidget"
|
||||||
v-model="email"
|
v-model="email"
|
||||||
customInputId="email"
|
customInputId="email"
|
||||||
validationRules="email-address-required|email-address-format" />
|
validationRules="email-address-required|email-address-format" />
|
||||||
|
|
||||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
v-if="displayInvalidZipAlert"
|
v-if="displayInvalidZipAlert"
|
||||||
class="my-3"
|
class="my-3"
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
v-if="displayNonServiceableZipAlert"
|
v-if="displayNonServiceableZipAlert"
|
||||||
class="my-3"
|
class="my-3"
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<div class="row mt-2" v-if="showServiceZipField">
|
<div class="row mt-2" v-if="showServiceZipField">
|
||||||
<div class="col mb-1">
|
<div class="col mb-1">
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
v-model="serviceZipCode"
|
v-model="serviceZipCode"
|
||||||
inputId="serviceZipCode"
|
inputId="serviceZipCode"
|
||||||
validationRules="zip-required|zip-format"
|
validationRules="zip-required|zip-format"
|
||||||
mask="#####" />
|
mask="#####" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
v-if="displayVinNotFoundAlert"
|
v-if="displayVinNotFoundAlert"
|
||||||
class="my-3"
|
class="my-3"
|
||||||
cmsWidgetName="AlertVinNotFoundWidget"
|
cmsWidgetName="AlertVinNotFoundWidget"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
v-if="displayMatchedDifferentVehicleAlert"
|
v-if="displayMatchedDifferentVehicleAlert"
|
||||||
class="my-3"
|
class="my-3"
|
||||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
alertClass="alert-warning"
|
alertClass="alert-warning"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -220,10 +217,10 @@ export default {
|
||||||
// If serviceZipCode is not set, then sets the response to the registrationZipValidationResponse. Calls VALIDATE_ZIP if the serviceZipCode is set.
|
// If serviceZipCode is not set, then sets the response to the registrationZipValidationResponse. Calls VALIDATE_ZIP if the serviceZipCode is set.
|
||||||
resultKey: "serviceZipValidationResponse",
|
resultKey: "serviceZipValidationResponse",
|
||||||
promise: this.serviceZipCode
|
promise: this.serviceZipCode
|
||||||
? this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
? this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
||||||
zip: this.serviceZipCode,
|
zip: this.serviceZipCode,
|
||||||
})
|
})
|
||||||
: registrationZipValidationResponse,
|
: registrationZipValidationResponse,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -253,7 +250,7 @@ export default {
|
||||||
|
|
||||||
// Check if the CarId has changed.
|
// Check if the CarId has changed.
|
||||||
this.isCarIdDifferent =
|
this.isCarIdDifferent =
|
||||||
vinLookup.data.vehicle.carId !== this.$store.getters.vehicle.carId;
|
vinLookup.data.vehicle.carId !== this.$store.getters.vehicle.carId;
|
||||||
|
|
||||||
// Handle changing car
|
// Handle changing car
|
||||||
if (
|
if (
|
||||||
|
|
@ -365,10 +362,10 @@ export default {
|
||||||
},
|
},
|
||||||
AlertMatchedDifferentVehicleBody() {
|
AlertMatchedDifferentVehicleBody() {
|
||||||
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
|
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
|
||||||
.replaceAll("{custom:damage}", getDamageString())
|
.replaceAll("{custom:damage}", getDamageString())
|
||||||
.replaceAll("{custom:plateLookupYear}", this.customAlertData?.vehicleInfo?.year)
|
.replaceAll("{custom:plateLookupYear}", this.customAlertData?.vehicleInfo?.year)
|
||||||
.replaceAll("{custom:plateLookupMake}", this.customAlertData?.vehicleInfo?.make)
|
.replaceAll("{custom:plateLookupMake}", this.customAlertData?.vehicleInfo?.make)
|
||||||
.replaceAll("{custom:plateLookupModel}", this.customAlertData?.vehicleInfo?.model);
|
.replaceAll("{custom:plateLookupModel}", this.customAlertData?.vehicleInfo?.model);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
||||||
|
|
@ -8,37 +8,37 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false" />
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
||||||
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
|
||||||
<cashOrInsuranceQuestion
|
<cashOrInsuranceQuestion
|
||||||
ref="cashOrInsurance"
|
ref="cashOrInsurance"
|
||||||
cmsWidgetName="CashOrInsuranceQuestionWidget"
|
cmsWidgetName="CashOrInsuranceQuestionWidget"
|
||||||
v-model="isInsuranceSelected"
|
v-model="isInsuranceSelected"
|
||||||
groupName="CashOrInsuranceQuestion" />
|
groupName="CashOrInsuranceQuestion" />
|
||||||
|
|
||||||
<servicePackageQuestion
|
<servicePackageQuestion
|
||||||
ref="servicePackage"
|
ref="servicePackage"
|
||||||
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
||||||
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
||||||
groupName="ServicePackageQuestion"
|
groupName="ServicePackageQuestion"
|
||||||
:availableLineItems="availableLineItems"
|
:availableLineItems="availableLineItems"
|
||||||
:isInsuranceSelected="isInsuranceSelected"
|
:isInsuranceSelected="isInsuranceSelected"
|
||||||
@vapsItemsSelected="vapsItemsSelectedAction"
|
@vapsItemsSelected="vapsItemsSelectedAction"
|
||||||
v-on="{ 'buttonEvent.openModal': openModalAction }"
|
v-on="{ 'buttonEvent.openModal': openModalAction }"
|
||||||
validationRules="option-required"
|
validationRules="option-required"
|
||||||
isRequired />
|
isRequired />
|
||||||
|
|
||||||
<textBlock
|
<textBlock
|
||||||
cmsWidgetName="quoteDisclaimer"
|
cmsWidgetName="quoteDisclaimer"
|
||||||
justifyText="left"
|
justifyText="left"
|
||||||
typeStyle="caption"
|
typeStyle="caption"
|
||||||
class="mt-4" />
|
class="mt-4" />
|
||||||
|
|
||||||
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
||||||
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
||||||
|
|
@ -46,13 +46,13 @@
|
||||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
:isBackButtonHidden="shouldHideBackButton"
|
:isBackButtonHidden="shouldHideBackButton"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -117,8 +117,8 @@ export default {
|
||||||
|
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
const clonedGlassParts = store.getters.order.lineItems.glassParts
|
const clonedGlassParts = store.getters.order.lineItems.glassParts
|
||||||
? JSON.parse(JSON.stringify(store.getters.order.lineItems.glassParts))
|
? JSON.parse(JSON.stringify(store.getters.order.lineItems.glassParts))
|
||||||
: [];
|
: [];
|
||||||
const availableLineItems = [
|
const availableLineItems = [
|
||||||
resultMap.rainDefense,
|
resultMap.rainDefense,
|
||||||
...resultMap.supportingItems,
|
...resultMap.supportingItems,
|
||||||
|
|
@ -169,101 +169,101 @@ export default {
|
||||||
(store.getters.order.damage.isRepair ||
|
(store.getters.order.damage.isRepair ||
|
||||||
(store.getters.order.lineItems?.glassParts != null &&
|
(store.getters.order.lineItems?.glassParts != null &&
|
||||||
store.getters.order.lineItems.glassParts.length > 0)) &&
|
store.getters.order.lineItems.glassParts.length > 0)) &&
|
||||||
store.getters.order.referralNumber?.length !== 6
|
store.getters.order.referralNumber?.length !== 6
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getDefaultIsInsuranceSelectedValue(availableLineItems) {
|
getDefaultIsInsuranceSelectedValue(availableLineItems) {
|
||||||
const serviceLocationState = store.getters.order.serviceLocation.state;
|
const serviceLocationState = store.getters.order.serviceLocation.state;
|
||||||
// Override if coming back from QuoteDetails. Remove override after Quote release
|
// Override if coming back from QuoteDetails. Remove override after Quote release
|
||||||
const isInsuranceOverrideValue = this.$route.query?.isInsurance;
|
const isInsuranceOverrideValue = this.$route.query?.isInsurance;
|
||||||
|
|
||||||
const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
|
const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
|
||||||
//Default to Insurance Tab if user Service zip is from certain States
|
//Default to Insurance Tab if user Service zip is from certain States
|
||||||
if (
|
if (
|
||||||
serviceLocationState != null &&
|
serviceLocationState != null &&
|
||||||
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
||||||
)
|
)
|
||||||
return true;
|
return true;
|
||||||
else if (isInsuranceOverrideValue != null) {
|
else if (isInsuranceOverrideValue != null) {
|
||||||
return isInsuranceOverrideValue == "true";
|
return isInsuranceOverrideValue == "true";
|
||||||
} else if (defaultIsInsuranceSelectedValue != null) {
|
} else if (defaultIsInsuranceSelectedValue != null) {
|
||||||
return defaultIsInsuranceSelectedValue;
|
return defaultIsInsuranceSelectedValue;
|
||||||
} else {
|
} else {
|
||||||
return availableLineItems
|
return availableLineItems
|
||||||
? baseMixin.methods.getTierOnePackagePrice(
|
? baseMixin.methods.getTierOnePackagePrice(
|
||||||
baseMixin.methods.filterOutFees(availableLineItems)
|
baseMixin.methods.filterOutFees(availableLineItems)
|
||||||
) > 300
|
) > 300
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
vapsItemsSelectedAction(vapsItemsSelected) {
|
vapsItemsSelectedAction(vapsItemsSelected) {
|
||||||
this.selectedVaps = vapsItemsSelected;
|
this.selectedVaps = vapsItemsSelected;
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
vehicleQuestionsMixin.methods.navigateBack(this);
|
vehicleQuestionsMixin.methods.navigateBack(this);
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
forwardButtonAction() {
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_PAYMENT_TYPE,
|
this.storeActions.SAVE_PAYMENT_TYPE,
|
||||||
this.isInsuranceSelected,
|
this.isInsuranceSelected,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!this.isInsuranceSelected) {
|
if (!this.isInsuranceSelected) {
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_PARENT_ACCOUNT_NUMBER,
|
this.storeActions.SAVE_PARENT_ACCOUNT_NUMBER,
|
||||||
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.$store.getters.order.payment.parentAccountNumber !=
|
this.$store.getters.order.payment.parentAccountNumber !=
|
||||||
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
|
||||||
) {
|
) {
|
||||||
this.supportingItems = this.filterOutFees(this.supportingItems);
|
this.supportingItems = this.filterOutFees(this.supportingItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.pricedGlassParts.length > 0) {
|
if (this.pricedGlassParts.length > 0) {
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_GLASS_PART_PRICES,
|
this.storeActions.SAVE_GLASS_PART_PRICES,
|
||||||
this.pricedGlassParts,
|
this.pricedGlassParts,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
|
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
|
||||||
|
|
||||||
const payment = this.$store.getters.payment;
|
const payment = this.$store.getters.payment;
|
||||||
if (payment.isInsurance) {
|
if (payment.isInsurance) {
|
||||||
navigateToHeritageFunnel({
|
navigateToHeritageFunnel({
|
||||||
shouldSaveSession: true,
|
shouldSaveSession: true,
|
||||||
loadingModal: this.$refs.loadingModal,
|
loadingModal: this.$refs.loadingModal,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$router.navigateWithSaving(
|
this.$router.navigateWithSaving(
|
||||||
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
||||||
this.$route
|
this.$route
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
navbar,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
Form,
|
Form,
|
||||||
textBlock,
|
textBlock,
|
||||||
cashOrInsuranceQuestion,
|
cashOrInsuranceQuestion,
|
||||||
servicePackageQuestion,
|
servicePackageQuestion,
|
||||||
contentGroupModal,
|
contentGroupModal,
|
||||||
loadingModal,
|
loadingModal,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.text-block {
|
.text-block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
|
@ -100,11 +100,10 @@
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,63 +1,66 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<loadingModal ref="loadingModal" />
|
<loadingModal ref="loadingModal" />
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
||||||
<template v-if="ChangeShopLink.length">
|
<template v-if="ChangeShopLink.length">
|
||||||
<textBlock
|
<textBlock
|
||||||
cmsWidgetName="ChangeShopLink"
|
cmsWidgetName="ChangeShopLink"
|
||||||
justifyText="center"
|
justifyText="center"
|
||||||
class="mb-3 text-link-small"
|
class="mb-3 text-link-small"
|
||||||
marginTopSizeOverride="1" />
|
marginTopSizeOverride="1" />
|
||||||
</template>
|
</template>
|
||||||
<locationAlerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
<locationAlerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
||||||
<datePicker
|
<datePicker
|
||||||
customComponentId="dateQuestion"
|
customComponentId="dateQuestion"
|
||||||
selectableDatesSetting="custom"
|
selectableDatesSetting="custom"
|
||||||
ref="datePicker"
|
ref="datePicker"
|
||||||
v-model="selectedDate"
|
v-model="selectedDate"
|
||||||
class="text-link-small"
|
class="text-link-small"
|
||||||
:customSelectableDatesCallback="getAvailableDatesMethod"
|
:customSelectableDatesCallback="getAvailableDatesMethod"
|
||||||
validationRules="date-required"
|
validationRules="date-required"
|
||||||
@date-clicked="openInshopTimeSlotsModal" />
|
@date-clicked="openInshopTimeSlotsModal" />
|
||||||
<timeSlotModalQuestion
|
<timeSlotModalQuestion
|
||||||
ref="timeSlotModalQuestion"
|
ref="timeSlotModalQuestion"
|
||||||
customComponentId="timeSlotModalQuestion"
|
customComponentId="timeSlotModalQuestion"
|
||||||
v-model="selectedTimeSlotInfo"
|
v-model="selectedTimeSlotInfo"
|
||||||
cmsWidgetName="TimeSlotModalQuestion"
|
cmsWidgetName="TimeSlotModalQuestion"
|
||||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||||
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
||||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||||
:selectedDate="selectedDate"
|
:selectedDate="selectedDate"
|
||||||
:appointmentType="appointmentType"
|
:appointmentType="appointmentType"
|
||||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||||
:estimatedServiceMinutesMinimum="selectableDatesData.estimatedServiceMinutesMinimum"
|
:estimatedServiceMinutesMinimum="
|
||||||
:estimatedServiceMinutesMaximum="selectableDatesData.estimatedServiceMinutesMaximum"
|
selectableDatesData.estimatedServiceMinutesMinimum
|
||||||
@time-slot-modal-closed="timeSlotModalClosed"
|
"
|
||||||
validationRules="time-slot-selection-required" />
|
:estimatedServiceMinutesMaximum="
|
||||||
<navbar
|
selectableDatesData.estimatedServiceMinutesMaximum
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
"
|
||||||
ref="navbar"
|
@time-slot-modal-closed="timeSlotModalClosed"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
validationRules="time-slot-selection-required" />
|
||||||
@back-clicked="backButtonAction"
|
<navbar
|
||||||
@ForwardClicked="forwardButtonAction" />
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Form>
|
||||||
</Form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -80,9 +83,9 @@ import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import { splitCopyOnCMSPlaceHolder } from "@/helpers/cms-content-helper";
|
import { splitCopyOnCMSPlaceHolder } from "@/helpers/cms-content-helper";
|
||||||
import {
|
import {
|
||||||
calcDaysBetweenDates,
|
calcDaysBetweenDates,
|
||||||
convertDateStringToDate,
|
convertDateStringToDate,
|
||||||
sumDateString,
|
sumDateString,
|
||||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||||
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
|
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
|
|
@ -92,431 +95,431 @@ import store from "@/store";
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule("date-required", required(errorMessages.DATE_REQUIRED));
|
defineRule("date-required", required(errorMessages.DATE_REQUIRED));
|
||||||
defineRule("time-slot-selection-required", (value) => {
|
defineRule("time-slot-selection-required", (value) => {
|
||||||
if (value?.timeSlot?.routeCode == null) {
|
if (value?.timeSlot?.routeCode == null) {
|
||||||
return errorMessages.DATE_REQUIRED;
|
return errorMessages.DATE_REQUIRED;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Define constants
|
// Define constants
|
||||||
const TIME_SLOTS_CALL_DAYS_LIMIT = 34; // needs to be 34 for API limits (35 does not consistently work)
|
const TIME_SLOTS_CALL_DAYS_LIMIT = 34; // needs to be 34 for API limits (35 does not consistently work)
|
||||||
|
|
||||||
const getAvailableDates = async (
|
const getAvailableDates = async (
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
appointmentType,
|
appointmentType,
|
||||||
providerNumber
|
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 difference = calcDaysBetweenDates(startDateString, endDateString);
|
||||||
const apiCallsCount = Math.ceil(difference / TIME_SLOTS_CALL_DAYS_LIMIT);
|
const apiCallsCount = Math.ceil(difference / TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||||
const storeActionConfigs = [];
|
const storeActionConfigs = [];
|
||||||
const timeSlotsData = {};
|
const timeSlotsData = {};
|
||||||
timeSlotsData.days = [];
|
timeSlotsData.days = [];
|
||||||
let apiStartDate = startDateString;
|
let apiStartDate = startDateString;
|
||||||
let apiEndDate = endDateString;
|
let apiEndDate = endDateString;
|
||||||
|
|
||||||
for (let i = 1; i <= apiCallsCount; i++) {
|
for (let i = 1; i <= apiCallsCount; i++) {
|
||||||
let storeActionConfig;
|
let storeActionConfig;
|
||||||
|
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
apiStartDate = sumDateString(apiEndDate, 1);
|
apiStartDate = sumDateString(apiEndDate, 1);
|
||||||
apiEndDate = sumDateString(apiStartDate, TIME_SLOTS_CALL_DAYS_LIMIT);
|
apiEndDate = sumDateString(apiStartDate, TIME_SLOTS_CALL_DAYS_LIMIT);
|
||||||
|
|
||||||
if (i === apiCallsCount) {
|
if (i === apiCallsCount) {
|
||||||
apiEndDate = endDateString;
|
apiEndDate = endDateString;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (apiEndDate > apiEndDateLimit) {
|
||||||
|
apiEndDate = apiEndDateLimit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (apiEndDate > apiEndDateLimit) {
|
if (appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||||
apiEndDate = apiEndDateLimit;
|
storeActionConfig = {
|
||||||
|
storeAction: storeActions.GET_MOBILE_TIME_SLOTS,
|
||||||
|
payload: {
|
||||||
|
startDate: apiStartDate,
|
||||||
|
endDate: apiEndDate,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
storeActionConfig = {
|
||||||
|
storeAction: storeActions.GET_SHOP_TIME_SLOTS,
|
||||||
|
payload: {
|
||||||
|
startDate: apiStartDate,
|
||||||
|
endDate: apiEndDate,
|
||||||
|
shopAppointmentType: appointmentType,
|
||||||
|
providerNumber: providerNumber,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
if (apiStartDate < apiEndDate) storeActionConfigs.push(storeActionConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appointmentType === AppointmentTypeStrings.MOBILE) {
|
const timeSlotsResponsesData = {
|
||||||
storeActionConfig = {
|
days: [],
|
||||||
storeAction: storeActions.GET_MOBILE_TIME_SLOTS,
|
};
|
||||||
payload: {
|
|
||||||
startDate: apiStartDate,
|
function compareDayStrings(a, b) {
|
||||||
endDate: apiEndDate,
|
if (a.date < b.date) return -1;
|
||||||
},
|
if (a.date > b.date) return 1;
|
||||||
};
|
return 0;
|
||||||
} else {
|
|
||||||
storeActionConfig = {
|
|
||||||
storeAction: storeActions.GET_SHOP_TIME_SLOTS,
|
|
||||||
payload: {
|
|
||||||
startDate: apiStartDate,
|
|
||||||
endDate: apiEndDate,
|
|
||||||
shopAppointmentType: appointmentType,
|
|
||||||
providerNumber: providerNumber,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (apiStartDate < apiEndDate) storeActionConfigs.push(storeActionConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeSlotsResponsesData = {
|
const makeParallelCalls = async () => {
|
||||||
days: [],
|
await Promise.all(
|
||||||
};
|
storeActionConfigs.map(async (storeAction) => {
|
||||||
|
const timeSlotsResponse = await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeAction.storeAction,
|
||||||
|
storeAction.payload,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
timeSlotsResponsesData.estimatedServiceMinutesMinimum =
|
||||||
|
timeSlotsResponse.data.estimatedServiceMinutesMinimum;
|
||||||
|
timeSlotsResponsesData.estimatedServiceMinutesMaximum =
|
||||||
|
timeSlotsResponse.data.estimatedServiceMinutesMaximum;
|
||||||
|
timeSlotsResponsesData.days = [
|
||||||
|
...timeSlotsResponsesData.days,
|
||||||
|
...timeSlotsResponse.data.days,
|
||||||
|
];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
function compareDayStrings(a, b) {
|
return makeParallelCalls().then(() => {
|
||||||
if (a.date < b.date) return -1;
|
// sort days chronologically
|
||||||
if (a.date > b.date) return 1;
|
timeSlotsResponsesData.days.sort(compareDayStrings);
|
||||||
return 0;
|
return timeSlotsResponsesData;
|
||||||
}
|
});
|
||||||
|
|
||||||
const makeParallelCalls = async () => {
|
|
||||||
await Promise.all(
|
|
||||||
storeActionConfigs.map(async (storeAction) => {
|
|
||||||
const timeSlotsResponse = await baseMixin.methods.dispatchStoreAction(
|
|
||||||
storeAction.storeAction,
|
|
||||||
storeAction.payload,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
timeSlotsResponsesData.estimatedServiceMinutesMinimum =
|
|
||||||
timeSlotsResponse.data.estimatedServiceMinutesMinimum;
|
|
||||||
timeSlotsResponsesData.estimatedServiceMinutesMaximum =
|
|
||||||
timeSlotsResponse.data.estimatedServiceMinutesMaximum;
|
|
||||||
timeSlotsResponsesData.days = [
|
|
||||||
...timeSlotsResponsesData.days,
|
|
||||||
...timeSlotsResponse.data.days,
|
|
||||||
];
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return makeParallelCalls().then(() => {
|
|
||||||
// sort days chronologically
|
|
||||||
timeSlotsResponsesData.days.sort(compareDayStrings);
|
|
||||||
return timeSlotsResponsesData;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "schedule",
|
name: "schedule",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedDate: this.getSelectedDate(),
|
selectedDate: this.getSelectedDate(),
|
||||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||||
selectableDatesData: [],
|
selectableDatesData: [],
|
||||||
mobilePremiumAppointmentFee: null,
|
mobilePremiumAppointmentFee: null,
|
||||||
};
|
|
||||||
},
|
|
||||||
async beforeRouteEnter(to, from, next) {
|
|
||||||
// Call APIs
|
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
|
||||||
let preSelectedDate = await store.getters.order.schedule.date;
|
|
||||||
if (!preSelectedDate || preSelectedDate.startTime === null) {
|
|
||||||
preSelectedDate = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const datePickerInitialDataPromise = await datePicker.methods.loadInitialData({
|
|
||||||
// setup config options for date-picker
|
|
||||||
selectableDatesSetting: "custom",
|
|
||||||
initialViewRowsToShow: 5,
|
|
||||||
customSelectableDatesCallback: getAvailableDates,
|
|
||||||
preSelectedDate: preSelectedDate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const premiumFeePromise = baseMixin.methods.dispatchStoreAction(
|
|
||||||
storeActions.GET_MOBILE_PREMIUM_FEE
|
|
||||||
);
|
|
||||||
|
|
||||||
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
|
||||||
if (result.data) {
|
|
||||||
return baseMixin.methods.dispatchStoreAction(
|
|
||||||
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
|
||||||
{
|
|
||||||
availableLineItems: [result.data],
|
|
||||||
},
|
|
||||||
false
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return result.data;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
|
||||||
store.getters.order.serviceLocation.zipCodeCtu,
|
|
||||||
store.getters.order.serviceLocation.provider?.address?.zipCodeCtu
|
|
||||||
);
|
|
||||||
|
|
||||||
// Settle promises and get results
|
|
||||||
const promiseResultMap = [
|
|
||||||
{
|
|
||||||
resultKey: "cmsContent",
|
|
||||||
promise: cmsContentPromise,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: "alertReasons",
|
|
||||||
promise: alertReasonsPromise,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: "datePickerInitialData",
|
|
||||||
promise: datePickerInitialDataPromise,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resultKey: "premiumFeeWithPrice",
|
|
||||||
promise: premiumFeeWithPricePromise,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
|
||||||
next((vm) => {
|
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
|
||||||
vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData);
|
|
||||||
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
|
||||||
vm.selectableDatesData = resultMap.datePickerInitialData.initialShopTimeSlotsResponse;
|
|
||||||
vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice
|
|
||||||
? resultMap.premiumFeeWithPrice[0]
|
|
||||||
: null;
|
|
||||||
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
ChangeShopLinkText() {
|
|
||||||
return this.getCmsContent("ChangeShopLink", "Text");
|
|
||||||
},
|
|
||||||
ChangeShopLink() {
|
|
||||||
// Splits content when brackets are found in text so that text can be looped through and router-link can be injected when needed
|
|
||||||
return this.splitCopyOnCMSPlaceHolder(this.ChangeShopLinkText);
|
|
||||||
},
|
|
||||||
appointmentType() {
|
|
||||||
return this.$store.getters.order.serviceLocation.appointmentType;
|
|
||||||
},
|
|
||||||
timeSlotsForSelectedDate() {
|
|
||||||
if (!this.selectedDate) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.selectableDatesData.days?.find(
|
|
||||||
(selectableDate) => selectableDate.date === this.selectedDate
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
splitCopyOnCMSPlaceHolder,
|
|
||||||
arePagePrerequisitesValid() {
|
|
||||||
const serviceLocation = store.getters.order.serviceLocation;
|
|
||||||
|
|
||||||
const serviceLocationPreReqs =
|
|
||||||
serviceLocation.zipCode &&
|
|
||||||
serviceLocation.zipCodeCtu &&
|
|
||||||
serviceLocation.appointmentType &&
|
|
||||||
(serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE ||
|
|
||||||
serviceLocation.provider.providerNumber);
|
|
||||||
|
|
||||||
const paymentInfo = store.getters.payment.isInsurance !== null;
|
|
||||||
const supportingItems = store.getters.lineItems.supportingItems !== null;
|
|
||||||
|
|
||||||
const damageInfo =
|
|
||||||
store.getters.order.damage.isRepair ||
|
|
||||||
(store.getters.order.lineItems?.glassParts != null &&
|
|
||||||
store.getters.order.lineItems.glassParts.length > 0);
|
|
||||||
|
|
||||||
return serviceLocationPreReqs && paymentInfo && supportingItems && damageInfo;
|
|
||||||
},
|
|
||||||
async getAvailableDatesMethod(startDate, endDate) {
|
|
||||||
const newShopTimeSlots = await getAvailableDates(
|
|
||||||
startDate,
|
|
||||||
endDate,
|
|
||||||
this.appointmentType,
|
|
||||||
this.$store.getters.order.serviceLocation.provider.providerNumber
|
|
||||||
);
|
|
||||||
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
|
||||||
this.selectableDatesData.days = this.selectableDatesData.days.concat(
|
|
||||||
newShopTimeSlots.days
|
|
||||||
);
|
|
||||||
return newShopTimeSlots;
|
|
||||||
},
|
|
||||||
getAvailableDates,
|
|
||||||
getServiceZipCtuCodeFromStore() {
|
|
||||||
return store.getters.order.serviceLocation.zipCodeCtu;
|
|
||||||
},
|
|
||||||
openInshopTimeSlotsModal() {
|
|
||||||
this.$refs["timeSlotModalQuestion"].openModal();
|
|
||||||
},
|
|
||||||
getSelectedDate() {
|
|
||||||
return store.getters.order.schedule.date;
|
|
||||||
},
|
|
||||||
getSelectedTimeSlotInfo() {
|
|
||||||
const supportingItems = this.getSupportingItems();
|
|
||||||
const isPremiumAppointment =
|
|
||||||
!!supportingItems.filter((lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE)
|
|
||||||
.length > 0;
|
|
||||||
|
|
||||||
const selectedTimeSlotInfo = {
|
|
||||||
timeSlot: store.getters.order.schedule,
|
|
||||||
isPremiumAppointment: isPremiumAppointment,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return selectedTimeSlotInfo;
|
|
||||||
},
|
},
|
||||||
getSupportingItems() {
|
async beforeRouteEnter(to, from, next) {
|
||||||
return store.getters.lineItems.supportingItems;
|
// Call APIs
|
||||||
},
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
timeSlotModalClosed() {
|
let preSelectedDate = await store.getters.order.schedule.date;
|
||||||
// Clear the selectedDate if no timeSlot has been selected
|
if (!preSelectedDate || preSelectedDate.startTime === null) {
|
||||||
if (this.selectedTimeSlotInfo.timeSlot.routeCode == null) {
|
preSelectedDate = null;
|
||||||
this.selectedDate = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateFooterButtonText(timeSlotInfo) {
|
|
||||||
let navbarButtonText;
|
|
||||||
if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) {
|
|
||||||
navbarButtonText = "Continue";
|
|
||||||
} else {
|
|
||||||
navbarButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(
|
|
||||||
timeSlotInfo.timeSlot.date
|
|
||||||
)}`;
|
|
||||||
|
|
||||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
|
||||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
|
||||||
timeSlotInfo.timeSlot.startTime
|
|
||||||
)}`;
|
|
||||||
} else if (
|
|
||||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
|
||||||
!timeSlotInfo.isPremiumAppointment
|
|
||||||
) {
|
|
||||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
|
||||||
timeSlotInfo.timeSlot.startTime,
|
|
||||||
true
|
|
||||||
)} - ${this.getDisplayTextForMilitaryTime(
|
|
||||||
timeSlotInfo.timeSlot.endTime,
|
|
||||||
true
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$refs.navbar.updateButtonText(navbarButtonText);
|
|
||||||
},
|
|
||||||
convertSelectedDateToShortMonthAndDay(selectedDate) {
|
|
||||||
// This conversion ensures we don't get get GMT induced date changes
|
|
||||||
const dateObject = convertDateStringToDate(selectedDate);
|
|
||||||
// Ex: April 25
|
|
||||||
return dateObject.toLocaleDateString("en-us", { month: "short", day: "numeric" });
|
|
||||||
},
|
|
||||||
getDisplayTextForMilitaryTime(militaryTimeInput, shouldTrimMinutesIfEmpty = false) {
|
|
||||||
// Expected input: "HH:MM"
|
|
||||||
let hours = parseInt(militaryTimeInput.split(":")[0]);
|
|
||||||
const minutes = militaryTimeInput.split(":")[1];
|
|
||||||
const meridianNotation = hours > 11 ? "PM" : "AM";
|
|
||||||
|
|
||||||
if (hours > 12) {
|
|
||||||
hours -= 12;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldTrimMinutesIfEmpty && minutes === "00") {
|
const datePickerInitialDataPromise = await datePicker.methods.loadInitialData({
|
||||||
return `${hours} ${meridianNotation}`;
|
// setup config options for date-picker
|
||||||
} else {
|
selectableDatesSetting: "custom",
|
||||||
return `${hours}:${minutes} ${meridianNotation}`;
|
initialViewRowsToShow: 5,
|
||||||
}
|
customSelectableDatesCallback: getAvailableDates,
|
||||||
},
|
preSelectedDate: preSelectedDate,
|
||||||
backButtonAction() {
|
});
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
|
||||||
},
|
|
||||||
forwardButtonAction() {
|
|
||||||
this.updateSupportingItems();
|
|
||||||
|
|
||||||
this.dispatchStoreAction(
|
const premiumFeePromise = baseMixin.methods.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_SCHEDULE,
|
storeActions.GET_MOBILE_PREMIUM_FEE
|
||||||
this.selectedTimeSlotInfo.timeSlot,
|
|
||||||
false
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
||||||
},
|
if (result.data) {
|
||||||
updateSupportingItems() {
|
return baseMixin.methods.dispatchStoreAction(
|
||||||
const supportingItems = this.getSupportingItems();
|
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||||
|
{
|
||||||
// if we have a premium fee(early bird), then save/update supporting items
|
availableLineItems: [result.data],
|
||||||
if (
|
},
|
||||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
false
|
||||||
this.selectedTimeSlotInfo?.isPremiumAppointment
|
);
|
||||||
) {
|
|
||||||
const earlyBirdIndex = supportingItems.findIndex(
|
|
||||||
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
|
||||||
);
|
|
||||||
|
|
||||||
if (earlyBirdIndex >= 0) {
|
|
||||||
supportingItems[earlyBirdIndex].laborAmount =
|
|
||||||
this.mobilePremiumAppointmentFee.laborAmount;
|
|
||||||
supportingItems[earlyBirdIndex].selingPrice =
|
|
||||||
this.mobilePremiumAppointmentFee.selingPrice;
|
|
||||||
supportingItems[earlyBirdIndex].kitPrice =
|
|
||||||
this.mobilePremiumAppointmentFee.kitPrice;
|
|
||||||
} else {
|
} else {
|
||||||
supportingItems.push(this.mobilePremiumAppointmentFee);
|
return result.data;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
||||||
|
store.getters.order.serviceLocation.zipCodeCtu,
|
||||||
|
store.getters.order.serviceLocation.provider?.address?.zipCodeCtu
|
||||||
|
);
|
||||||
|
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [
|
||||||
|
{
|
||||||
|
resultKey: "cmsContent",
|
||||||
|
promise: cmsContentPromise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: "alertReasons",
|
||||||
|
promise: alertReasonsPromise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: "datePickerInitialData",
|
||||||
|
promise: datePickerInitialDataPromise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: "premiumFeeWithPrice",
|
||||||
|
promise: premiumFeeWithPricePromise,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
|
// Call the "next" function to complete the transition to this page.
|
||||||
|
next((vm) => {
|
||||||
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData);
|
||||||
|
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
||||||
|
vm.selectableDatesData = resultMap.datePickerInitialData.initialShopTimeSlotsResponse;
|
||||||
|
vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice
|
||||||
|
? resultMap.premiumFeeWithPrice[0]
|
||||||
|
: null;
|
||||||
|
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
ChangeShopLinkText() {
|
||||||
|
return this.getCmsContent("ChangeShopLink", "Text");
|
||||||
|
},
|
||||||
|
ChangeShopLink() {
|
||||||
|
// Splits content when brackets are found in text so that text can be looped through and router-link can be injected when needed
|
||||||
|
return this.splitCopyOnCMSPlaceHolder(this.ChangeShopLinkText);
|
||||||
|
},
|
||||||
|
appointmentType() {
|
||||||
|
return this.$store.getters.order.serviceLocation.appointmentType;
|
||||||
|
},
|
||||||
|
timeSlotsForSelectedDate() {
|
||||||
|
if (!this.selectedDate) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.selectableDatesData.days?.find(
|
||||||
|
(selectableDate) => selectableDate.date === this.selectedDate
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
splitCopyOnCMSPlaceHolder,
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
const serviceLocation = store.getters.order.serviceLocation;
|
||||||
|
|
||||||
|
const serviceLocationPreReqs =
|
||||||
|
serviceLocation.zipCode &&
|
||||||
|
serviceLocation.zipCodeCtu &&
|
||||||
|
serviceLocation.appointmentType &&
|
||||||
|
(serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE ||
|
||||||
|
serviceLocation.provider.providerNumber);
|
||||||
|
|
||||||
|
const paymentInfo = store.getters.payment.isInsurance !== null;
|
||||||
|
const supportingItems = store.getters.lineItems.supportingItems !== null;
|
||||||
|
|
||||||
|
const damageInfo =
|
||||||
|
store.getters.order.damage.isRepair ||
|
||||||
|
(store.getters.order.lineItems?.glassParts != null &&
|
||||||
|
store.getters.order.lineItems.glassParts.length > 0);
|
||||||
|
|
||||||
|
return serviceLocationPreReqs && paymentInfo && supportingItems && damageInfo;
|
||||||
|
},
|
||||||
|
async getAvailableDatesMethod(startDate, endDate) {
|
||||||
|
const newShopTimeSlots = await getAvailableDates(
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
this.appointmentType,
|
||||||
|
this.$store.getters.order.serviceLocation.provider.providerNumber
|
||||||
|
);
|
||||||
|
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
||||||
|
this.selectableDatesData.days = this.selectableDatesData.days.concat(
|
||||||
|
newShopTimeSlots.days
|
||||||
|
);
|
||||||
|
return newShopTimeSlots;
|
||||||
|
},
|
||||||
|
getAvailableDates,
|
||||||
|
getServiceZipCtuCodeFromStore() {
|
||||||
|
return store.getters.order.serviceLocation.zipCodeCtu;
|
||||||
|
},
|
||||||
|
openInshopTimeSlotsModal() {
|
||||||
|
this.$refs["timeSlotModalQuestion"].openModal();
|
||||||
|
},
|
||||||
|
getSelectedDate() {
|
||||||
|
return store.getters.order.schedule.date;
|
||||||
|
},
|
||||||
|
getSelectedTimeSlotInfo() {
|
||||||
|
const supportingItems = this.getSupportingItems();
|
||||||
|
const isPremiumAppointment =
|
||||||
|
!!supportingItems.filter((lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE)
|
||||||
|
.length > 0;
|
||||||
|
|
||||||
|
const selectedTimeSlotInfo = {
|
||||||
|
timeSlot: store.getters.order.schedule,
|
||||||
|
isPremiumAppointment: isPremiumAppointment,
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectedTimeSlotInfo;
|
||||||
|
},
|
||||||
|
getSupportingItems() {
|
||||||
|
return store.getters.lineItems.supportingItems;
|
||||||
|
},
|
||||||
|
timeSlotModalClosed() {
|
||||||
|
// Clear the selectedDate if no timeSlot has been selected
|
||||||
|
if (this.selectedTimeSlotInfo.timeSlot.routeCode == null) {
|
||||||
|
this.selectedDate = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateFooterButtonText(timeSlotInfo) {
|
||||||
|
let navbarButtonText;
|
||||||
|
if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) {
|
||||||
|
navbarButtonText = "Continue";
|
||||||
|
} else {
|
||||||
|
navbarButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(
|
||||||
|
timeSlotInfo.timeSlot.date
|
||||||
|
)}`;
|
||||||
|
|
||||||
|
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||||
|
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||||
|
timeSlotInfo.timeSlot.startTime
|
||||||
|
)}`;
|
||||||
|
} else if (
|
||||||
|
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||||
|
!timeSlotInfo.isPremiumAppointment
|
||||||
|
) {
|
||||||
|
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||||
|
timeSlotInfo.timeSlot.startTime,
|
||||||
|
true
|
||||||
|
)} - ${this.getDisplayTextForMilitaryTime(
|
||||||
|
timeSlotInfo.timeSlot.endTime,
|
||||||
|
true
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$refs.navbar.updateButtonText(navbarButtonText);
|
||||||
|
},
|
||||||
|
convertSelectedDateToShortMonthAndDay(selectedDate) {
|
||||||
|
// This conversion ensures we don't get get GMT induced date changes
|
||||||
|
const dateObject = convertDateStringToDate(selectedDate);
|
||||||
|
// Ex: April 25
|
||||||
|
return dateObject.toLocaleDateString("en-us", { month: "short", day: "numeric" });
|
||||||
|
},
|
||||||
|
getDisplayTextForMilitaryTime(militaryTimeInput, shouldTrimMinutesIfEmpty = false) {
|
||||||
|
// Expected input: "HH:MM"
|
||||||
|
let hours = parseInt(militaryTimeInput.split(":")[0]);
|
||||||
|
const minutes = militaryTimeInput.split(":")[1];
|
||||||
|
const meridianNotation = hours > 11 ? "PM" : "AM";
|
||||||
|
|
||||||
|
if (hours > 12) {
|
||||||
|
hours -= 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldTrimMinutesIfEmpty && minutes === "00") {
|
||||||
|
return `${hours} ${meridianNotation}`;
|
||||||
|
} else {
|
||||||
|
return `${hours}:${minutes} ${meridianNotation}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
backButtonAction() {
|
||||||
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
},
|
||||||
|
forwardButtonAction() {
|
||||||
|
this.updateSupportingItems();
|
||||||
|
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
this.storeActions.SAVE_SCHEDULE,
|
||||||
supportingItems,
|
this.selectedTimeSlotInfo.timeSlot,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
// if it's not a mobile and/or premium early bird, then make sure we remove any that may have been added
|
|
||||||
const removeEarlyBirdIndex = supportingItems.findIndex(
|
|
||||||
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
|
||||||
);
|
|
||||||
|
|
||||||
if (removeEarlyBirdIndex >= 0) {
|
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||||
supportingItems.splice(removeEarlyBirdIndex, 1);
|
},
|
||||||
|
updateSupportingItems() {
|
||||||
|
const supportingItems = this.getSupportingItems();
|
||||||
|
|
||||||
|
// if we have a premium fee(early bird), then save/update supporting items
|
||||||
|
if (
|
||||||
|
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||||
|
this.selectedTimeSlotInfo?.isPremiumAppointment
|
||||||
|
) {
|
||||||
|
const earlyBirdIndex = supportingItems.findIndex(
|
||||||
|
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (earlyBirdIndex >= 0) {
|
||||||
|
supportingItems[earlyBirdIndex].laborAmount =
|
||||||
|
this.mobilePremiumAppointmentFee.laborAmount;
|
||||||
|
supportingItems[earlyBirdIndex].selingPrice =
|
||||||
|
this.mobilePremiumAppointmentFee.selingPrice;
|
||||||
|
supportingItems[earlyBirdIndex].kitPrice =
|
||||||
|
this.mobilePremiumAppointmentFee.kitPrice;
|
||||||
|
} else {
|
||||||
|
supportingItems.push(this.mobilePremiumAppointmentFee);
|
||||||
|
}
|
||||||
|
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
||||||
supportingItems,
|
supportingItems,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// if it's not a mobile and/or premium early bird, then make sure we remove any that may have been added
|
||||||
|
const removeEarlyBirdIndex = supportingItems.findIndex(
|
||||||
|
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (removeEarlyBirdIndex >= 0) {
|
||||||
|
supportingItems.splice(removeEarlyBirdIndex, 1);
|
||||||
|
this.dispatchStoreAction(
|
||||||
|
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
||||||
|
supportingItems,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
watch: {
|
||||||
watch: {
|
selectedDate(newValue, oldValue) {
|
||||||
selectedDate(newValue, oldValue) {
|
// Clear time slot selection if date selected changes
|
||||||
// Clear time slot selection if date selected changes
|
if (newValue !== oldValue) {
|
||||||
if (newValue !== oldValue) {
|
this.selectedTimeSlotInfo = {
|
||||||
this.selectedTimeSlotInfo = {
|
timeSlot: {
|
||||||
timeSlot: {
|
date: null,
|
||||||
date: null,
|
routeCode: null,
|
||||||
routeCode: null,
|
startTime: null,
|
||||||
startTime: null,
|
endTime: null,
|
||||||
endTime: null,
|
jobMaxMinutes: null,
|
||||||
jobMaxMinutes: null,
|
jobMinMinutes: null,
|
||||||
jobMinMinutes: null,
|
},
|
||||||
},
|
isPremiumAppointment: null,
|
||||||
isPremiumAppointment: null,
|
};
|
||||||
};
|
}
|
||||||
}
|
},
|
||||||
|
selectedTimeSlotInfo(newValue) {
|
||||||
|
this.updateFooterButtonText(newValue);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectedTimeSlotInfo(newValue) {
|
components: {
|
||||||
this.updateFooterButtonText(newValue);
|
funnelHeader,
|
||||||
|
navbar,
|
||||||
|
funnelSubHeader,
|
||||||
|
Form,
|
||||||
|
loadingModal,
|
||||||
|
datePicker,
|
||||||
|
locationAlerts,
|
||||||
|
timeSlotModalQuestion,
|
||||||
|
textBlock,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
components: {
|
|
||||||
funnelHeader,
|
|
||||||
navbar,
|
|
||||||
funnelSubHeader,
|
|
||||||
Form,
|
|
||||||
loadingModal,
|
|
||||||
datePicker,
|
|
||||||
locationAlerts,
|
|
||||||
timeSlotModalQuestion,
|
|
||||||
textBlock,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.text-link-small {
|
.text-link-small {
|
||||||
a,
|
a,
|
||||||
.btn-link {
|
.btn-link {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.funnel-sub-header {
|
.funnel-sub-header {
|
||||||
h5.dark-header {
|
h5.dark-header {
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -8,101 +8,100 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
||||||
|
|
||||||
<serviceZipModalQuestion
|
<serviceZipModalQuestion
|
||||||
v-model="serviceZipCodeQuestion"
|
v-model="serviceZipCodeQuestion"
|
||||||
ref="serviceZipCodeQuestion"
|
ref="serviceZipCodeQuestion"
|
||||||
:mobileFeePart="mobileFeePart"
|
:mobileFeePart="mobileFeePart"
|
||||||
@updated-mobile-fee-part="setMobileFeePart"
|
@updated-mobile-fee-part="setMobileFeePart"
|
||||||
@updated-serviceability="setServiceabilityDetails"
|
@updated-serviceability="setServiceabilityDetails"
|
||||||
@updated-contains-military-base="setContainsMilitaryBase"
|
@updated-contains-military-base="setContainsMilitaryBase"
|
||||||
linkWidgetName="ServiceZipLinkWidget"
|
linkWidgetName="ServiceZipLinkWidget"
|
||||||
modalWidgetName="ServiceZipModalWidget"
|
modalWidgetName="ServiceZipModalWidget"
|
||||||
:onZipUpdateCallback="reloadShopData" />
|
:onZipUpdateCallback="reloadShopData" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="alertMilitaryBaseZip"
|
ref="alertMilitaryBaseZip"
|
||||||
class="my-5"
|
class="my-5"
|
||||||
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
||||||
v-if="displayMilitaryZipAlert"
|
v-if="displayMilitaryZipAlert"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="alertMobileOnly"
|
ref="alertMobileOnly"
|
||||||
class="my-5"
|
class="my-5"
|
||||||
cmsWidgetName="AlertMobileOnlyWidget"
|
cmsWidgetName="AlertMobileOnlyWidget"
|
||||||
v-if="displayServiceableMobileOnly"
|
v-if="displayServiceableMobileOnly"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="alertRecalNoMobile"
|
ref="alertRecalNoMobile"
|
||||||
class="my-5"
|
class="my-5"
|
||||||
cmsWidgetName="AlertRecalNoMobileWidget"
|
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||||
v-if="displayRecalibrationWarning"
|
v-if="displayRecalibrationWarning"
|
||||||
@text-link-clicked="openModalAction"
|
@text-link-clicked="openModalAction"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="alertInshopOnly"
|
ref="alertInshopOnly"
|
||||||
class="my-5"
|
class="my-5"
|
||||||
cmsWidgetName="AlertInshopOnlyWidget"
|
cmsWidgetName="AlertInshopOnlyWidget"
|
||||||
v-if="displayServiceableInshopOnly"
|
v-if="displayServiceableInshopOnly"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="alertNoShops"
|
ref="alertNoShops"
|
||||||
class="my-5"
|
class="my-5"
|
||||||
cmsWidgetName="AlertNoShopsWidget"
|
cmsWidgetName="AlertNoShopsWidget"
|
||||||
v-if="displayNoShopsAlert"
|
v-if="displayNoShopsAlert"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
|
|
||||||
<appointmentTypeQuestion
|
<appointmentTypeQuestion
|
||||||
v-model="selectedAppointmentType"
|
v-model="selectedAppointmentType"
|
||||||
v-show="isAppointmentTypeDisplayed"
|
v-show="isAppointmentTypeDisplayed"
|
||||||
:isServiceableMobile="isServiceableMobile"
|
:isServiceableMobile="isServiceableMobile"
|
||||||
:isServiceableInshop="isServiceableInshop"
|
:isServiceableInshop="isServiceableInshop"
|
||||||
:isDisplayed="isAppointmentTypeDisplayed"
|
:isDisplayed="isAppointmentTypeDisplayed"
|
||||||
ref="appointmentTypeQuestion"
|
ref="appointmentTypeQuestion"
|
||||||
groupName="appointmentTypeQuestion"
|
groupName="appointmentTypeQuestion"
|
||||||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||||
validationRules="option-required" />
|
validationRules="option-required" />
|
||||||
|
|
||||||
<mobileLocationModalQuestions
|
<mobileLocationModalQuestions
|
||||||
customComponentId="mobileLocationQuestions"
|
customComponentId="mobileLocationQuestions"
|
||||||
v-if="selectedAppointmentType === 'Mobile'"
|
v-if="selectedAppointmentType === 'Mobile'"
|
||||||
v-model="mobileLocationQuestions"
|
v-model="mobileLocationQuestions"
|
||||||
:mobileFeePart="mobileFeePart"
|
:mobileFeePart="mobileFeePart"
|
||||||
@updated-mobile-fee-part="setMobileFeePart"
|
@updated-mobile-fee-part="setMobileFeePart"
|
||||||
@updated-serviceability="setServiceabilityDetails"
|
@updated-serviceability="setServiceabilityDetails"
|
||||||
@updated-contains-military-base="setContainsMilitaryBase"
|
@updated-contains-military-base="setContainsMilitaryBase"
|
||||||
validationRules="mobile-location-required"
|
validationRules="mobile-location-required"
|
||||||
ref="mobileLocationQuestions"
|
ref="mobileLocationQuestions"
|
||||||
linkWidgetName="MobileLocationLinkWidget"
|
linkWidgetName="MobileLocationLinkWidget"
|
||||||
modalWidgetName="MobileLocationModalWidget"
|
modalWidgetName="MobileLocationModalWidget"
|
||||||
:onZipUpdateCallback="reloadShopData" />
|
:onZipUpdateCallback="reloadShopData" />
|
||||||
|
|
||||||
<shopQuestion
|
<shopQuestion
|
||||||
ref="shopQuestion"
|
ref="shopQuestion"
|
||||||
v-show="isShopQuestionDisplayed"
|
v-show="isShopQuestionDisplayed"
|
||||||
v-model="selectedProvider"
|
v-model="selectedProvider"
|
||||||
:selectedAppointmentType="selectedAppointmentType"
|
:selectedAppointmentType="selectedAppointmentType"
|
||||||
:isDisplayed="isShopQuestionDisplayed"
|
:isDisplayed="isShopQuestionDisplayed"
|
||||||
cmsWidgetName="ShopQuestionWidget" />
|
cmsWidgetName="ShopQuestionWidget" />
|
||||||
|
|
||||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid || displayNoShopsAlert"
|
:isForwardActionDisabled="!meta.valid || displayNoShopsAlert"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -262,7 +261,7 @@ export default {
|
||||||
set: function (newValue) {
|
set: function (newValue) {
|
||||||
this.streetAddress = newValue.addressQuestions.streetAddress;
|
this.streetAddress = newValue.addressQuestions.streetAddress;
|
||||||
this.apartmentNumberOrBusinessName =
|
this.apartmentNumberOrBusinessName =
|
||||||
newValue.addressQuestions.apartmentNumberOrBusinessName;
|
newValue.addressQuestions.apartmentNumberOrBusinessName;
|
||||||
this.city = newValue.addressQuestions.city;
|
this.city = newValue.addressQuestions.city;
|
||||||
this.state = newValue.addressQuestions.state;
|
this.state = newValue.addressQuestions.state;
|
||||||
this.zipCode = newValue.addressQuestions.zipCode;
|
this.zipCode = newValue.addressQuestions.zipCode;
|
||||||
|
|
@ -391,10 +390,10 @@ export default {
|
||||||
setServiceabilityDetails(serviceabilityDetails) {
|
setServiceabilityDetails(serviceabilityDetails) {
|
||||||
this.isGlassServiceableInshop = serviceabilityDetails.isGlassServiceableInshop;
|
this.isGlassServiceableInshop = serviceabilityDetails.isGlassServiceableInshop;
|
||||||
this.isRecalibrationServiceableInshop =
|
this.isRecalibrationServiceableInshop =
|
||||||
serviceabilityDetails.isRecalibrationServiceableInshop;
|
serviceabilityDetails.isRecalibrationServiceableInshop;
|
||||||
this.isGlassServiceableMobile = serviceabilityDetails.isGlassServiceableMobile;
|
this.isGlassServiceableMobile = serviceabilityDetails.isGlassServiceableMobile;
|
||||||
this.isRecalibrationServiceableMobile =
|
this.isRecalibrationServiceableMobile =
|
||||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false" />
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="vehicleChangeAlert"
|
ref="vehicleChangeAlert"
|
||||||
v-if="shouldDisplayVehicleChangeAlert"
|
v-if="shouldDisplayVehicleChangeAlert"
|
||||||
class="mt-5 mb-0"
|
class="mt-5 mb-0"
|
||||||
|
|
@ -23,27 +23,27 @@
|
||||||
alertClass="alert-warning"
|
alertClass="alert-warning"
|
||||||
:isDismissible="false" />
|
:isDismissible="false" />
|
||||||
|
|
||||||
<damageLocationQuestion
|
<damageLocationQuestion
|
||||||
ref="damageLocation"
|
ref="damageLocation"
|
||||||
cmsWidgetName="DamageLocationQuestion"
|
cmsWidgetName="DamageLocationQuestion"
|
||||||
v-model="selectedDamageLocations"
|
v-model="selectedDamageLocations"
|
||||||
groupName="DamageLocationQuestion" />
|
groupName="DamageLocationQuestion" />
|
||||||
|
|
||||||
<windshieldOptions
|
<windshieldOptions
|
||||||
ref="windshieldOptions"
|
ref="windshieldOptions"
|
||||||
v-model="selectedWindshieldOptions"
|
v-model="selectedWindshieldOptions"
|
||||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||||
:selectedDamageLocations="selectedDamageLocations" />
|
:selectedDamageLocations="selectedDamageLocations" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
v-if="hasRepairReplaceConflict"
|
v-if="hasRepairReplaceConflict"
|
||||||
class="my-5"
|
class="my-5"
|
||||||
cmsWidgetName="HasReplacementConflict"
|
cmsWidgetName="HasReplacementConflict"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
:isDismissible="false" />
|
:isDismissible="false" />
|
||||||
|
|
||||||
<sideDoorOptions
|
<sideDoorOptions
|
||||||
ref="sideDoorOptions"
|
ref="sideDoorOptions"
|
||||||
cmsWidgetName="SideDoorSideQuestion"
|
cmsWidgetName="SideDoorSideQuestion"
|
||||||
groupName="SideDoorSideQuestion"
|
groupName="SideDoorSideQuestion"
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
v-show="!hasRepairReplaceConflict"
|
v-show="!hasRepairReplaceConflict"
|
||||||
:selectedDamageLocations="selectedDamageLocations" />
|
:selectedDamageLocations="selectedDamageLocations" />
|
||||||
|
|
||||||
<replaceOptionsQuestion
|
<replaceOptionsQuestion
|
||||||
ref="backGlassOptions"
|
ref="backGlassOptions"
|
||||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||||
|
|
@ -59,16 +59,16 @@
|
||||||
groupName="BackGlassReplaceOptionsQuestion"
|
groupName="BackGlassReplaceOptionsQuestion"
|
||||||
validationRules="replace-options-required" />
|
validationRules="replace-options-required" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
:isBackButtonHidden="shouldHideBackButton"
|
:isBackButtonHidden="shouldHideBackButton"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -235,7 +235,7 @@ export default {
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
windShieldOptions.selectedWindshieldDamageType =
|
windShieldOptions.selectedWindshieldDamageType =
|
||||||
damageLocationsSelected.REPLACE;
|
damageLocationsSelected.REPLACE;
|
||||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||||
damageLocationsSelected.SINGLE
|
damageLocationsSelected.SINGLE
|
||||||
);
|
);
|
||||||
|
|
@ -250,7 +250,7 @@ export default {
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
windShieldOptions.selectedWindshieldDamageType =
|
windShieldOptions.selectedWindshieldDamageType =
|
||||||
damageLocationsSelected.REPLACE;
|
damageLocationsSelected.REPLACE;
|
||||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||||
damageLocationsSelected.DRIVER
|
damageLocationsSelected.DRIVER
|
||||||
);
|
);
|
||||||
|
|
@ -265,7 +265,7 @@ export default {
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
windShieldOptions.selectedWindshieldDamageType =
|
windShieldOptions.selectedWindshieldDamageType =
|
||||||
damageLocationsSelected.REPLACE;
|
damageLocationsSelected.REPLACE;
|
||||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||||
damageLocationsSelected.PASSENGER
|
damageLocationsSelected.PASSENGER
|
||||||
);
|
);
|
||||||
|
|
@ -335,7 +335,7 @@ export default {
|
||||||
isWindshieldRepair: this.isWindshieldRepair,
|
isWindshieldRepair: this.isWindshieldRepair,
|
||||||
selectedGlassToReplace: this.selectedGlassToReplace(),
|
selectedGlassToReplace: this.selectedGlassToReplace(),
|
||||||
selectedWindshieldChipCount:
|
selectedWindshieldChipCount:
|
||||||
this.selectedWindshieldOptions.selectedWindshieldChipCount,
|
this.selectedWindshieldOptions.selectedWindshieldChipCount,
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
@ -358,9 +358,9 @@ export default {
|
||||||
const payment = this.$store.getters.payment;
|
const payment = this.$store.getters.payment;
|
||||||
|
|
||||||
const vehicleChangedDuringPolicyLookupInHeritage =
|
const vehicleChangedDuringPolicyLookupInHeritage =
|
||||||
payment.isInsurance &&
|
payment.isInsurance &&
|
||||||
payment.insuranceCoverage.coverageStatus &&
|
payment.insuranceCoverage.coverageStatus &&
|
||||||
payment.insuranceCoverage.coverageStatus !== "";
|
payment.insuranceCoverage.coverageStatus !== "";
|
||||||
if (vehicleChangedDuringPolicyLookupInHeritage) {
|
if (vehicleChangedDuringPolicyLookupInHeritage) {
|
||||||
if (store.getters.damage.isRepair) {
|
if (store.getters.damage.isRepair) {
|
||||||
this.$router.navigateWithSaving(
|
this.$router.navigateWithSaving(
|
||||||
|
|
@ -370,7 +370,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.$router.navigateWithSaving(
|
this.$router.navigateWithSaving(
|
||||||
this.navigationScenarios
|
this.navigationScenarios
|
||||||
.CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE,
|
.CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE,
|
||||||
this.$route
|
this.$route
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -452,7 +452,7 @@ export default {
|
||||||
return (
|
return (
|
||||||
this.isWindshieldDamageLocation &&
|
this.isWindshieldDamageLocation &&
|
||||||
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
||||||
damageLocationsSelected.REPAIR
|
damageLocationsSelected.REPAIR
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
isDriverSideReplace() {
|
isDriverSideReplace() {
|
||||||
|
|
@ -480,10 +480,10 @@ export default {
|
||||||
if (
|
if (
|
||||||
!this.selectedDamageLocations?.includes("Windshield") ||
|
!this.selectedDamageLocations?.includes("Windshield") ||
|
||||||
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
||||||
damageLocationsSelected.REPAIR ||
|
damageLocationsSelected.REPAIR ||
|
||||||
!this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
|
!this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||||
|
|
@ -502,14 +502,14 @@ export default {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
) ||
|
) ||
|
||||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||||
(selectedPassengerWindshield) => {
|
(selectedPassengerWindshield) => {
|
||||||
return (
|
return (
|
||||||
selectedPassengerWindshield.toUpperCase() ===
|
selectedPassengerWindshield.toUpperCase() ===
|
||||||
damageLocationsSelected.PASSENGER.toUpperCase()
|
damageLocationsSelected.PASSENGER.toUpperCase()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
shouldDisplayVehicleChangeAlert() {
|
shouldDisplayVehicleChangeAlert() {
|
||||||
|
|
|
||||||
|
|
@ -9,44 +9,48 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
ref="vehicleBanner"
|
ref="vehicleBanner"
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false" />
|
:displayGenericVehicleImage="false" />
|
||||||
<funnelSubHeader ref="funnelSubHeader" cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader
|
||||||
<div class="prevent-squish my-5">
|
ref="funnelSubHeader"
|
||||||
<div class="row">
|
cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div class="col pb-0">
|
<div class="prevent-squish my-5">
|
||||||
<alert
|
<div class="row">
|
||||||
class="rounded border-0 shadow-sm"
|
<div class="col pb-0">
|
||||||
alertClass="alert-warning"
|
<alert
|
||||||
cmsWidgetName="AlertWidget"
|
class="rounded border-0 shadow-sm"
|
||||||
:isDismissible="false" />
|
alertClass="alert-warning"
|
||||||
</div>
|
cmsWidgetName="AlertWidget"
|
||||||
|
:isDismissible="false" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
</div>
|
||||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
||||||
<hr v-if="i > 0" />
|
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||||
<glassPartQuestion
|
<hr v-if="i > 0" />
|
||||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
<glassPartQuestion
|
||||||
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
|
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||||
:glassLocation="item.glassLocation"
|
v-model="
|
||||||
:glassName="item.glassName"
|
selectedGlassParts[item.glassLocation + '-' + item.glassName]
|
||||||
:colorAnswers="item.colorAnswers"
|
"
|
||||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
:glassLocation="item.glassLocation"
|
||||||
</div>
|
:glassName="item.glassName"
|
||||||
<navbar
|
:colorAnswers="item.colorAnswers"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||||
ref="navbar"
|
</div>
|
||||||
:isForwardActionDisabled="isForwardActionDisabled"
|
<navbar
|
||||||
@back-clicked="navigateBack"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="isForwardActionDisabled"
|
||||||
|
@back-clicked="navigateBack"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3 col-lg-4"> </div>
|
<div class="d-none d-md-block col-md-3 col-lg-4"> </div>
|
||||||
<div class="col-md-6 col-lg-4">
|
<div class="col-md-6 col-lg-4">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
|
||||||
<vehicleQuestion
|
<vehicleQuestion
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
ref="navbar" />
|
ref="navbar" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 col-lg-4"> </div>
|
<div class="d-none d-md-block col-md-3 col-lg-4"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
||||||
|
|
@ -8,126 +8,122 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
<div class="col-md-8 col-lg-6">
|
<div class="col-md-8 col-lg-6">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false" />
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="VinNumberQuestionWidget"
|
cmsWidgetName="VinNumberQuestionWidget"
|
||||||
v-model="vin"
|
v-model="vin"
|
||||||
customInputId="vin"
|
customInputId="vin"
|
||||||
isRequired
|
isRequired
|
||||||
:validationRules="
|
:validationRules="!vinPopulatedOnPageLoad ? 'vin-required|vin-format' : ''"
|
||||||
!vinPopulatedOnPageLoad ? 'vin-required|vin-format' : ''
|
:isDisabled="vinPopulatedOnPageLoad"
|
||||||
"
|
maxLength="17"
|
||||||
:isDisabled="vinPopulatedOnPageLoad"
|
:mask="vinMask"
|
||||||
maxLength="17"
|
includeImageQuestion
|
||||||
:mask="vinMask"
|
:imageQuestionSubmitHandler="getVinFromImage"
|
||||||
includeImageQuestion
|
:maxFileSize="imageUploadMaxFileSize"
|
||||||
:imageQuestionSubmitHandler="getVinFromImage"
|
@image-lookup-error="displayVinScanAlert"
|
||||||
:maxFileSize="imageUploadMaxFileSize"
|
@image-validity-error="displayVinScanAlert"
|
||||||
@image-lookup-error="displayVinScanAlert"
|
data-test="vin-lookup-field"
|
||||||
@image-validity-error="displayVinScanAlert"
|
ref="vinLookupQuestion" />
|
||||||
data-test="vin-lookup-field"
|
|
||||||
ref="vinLookupQuestion" />
|
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
cmsWidgetName="AlertVinScanFailed"
|
cmsWidgetName="AlertVinScanFailed"
|
||||||
v-if="displayVinScanFailedAlert"
|
v-if="displayVinScanFailedAlert"
|
||||||
alertClass="alert-danger" />
|
alertClass="alert-danger" />
|
||||||
|
|
||||||
<vinInformation />
|
<vinInformation />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
v-model="serviceZipCode"
|
v-model="serviceZipCode"
|
||||||
customInputId="serviceZipCode"
|
customInputId="serviceZipCode"
|
||||||
mask="#####"
|
mask="#####"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="zip-required|zip-format" />
|
validationRules="zip-required|zip-format" />
|
||||||
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
cmsWidgetName="EmailAddressQuestionWidget"
|
cmsWidgetName="EmailAddressQuestionWidget"
|
||||||
v-model="emailAddress"
|
v-model="emailAddress"
|
||||||
customInputId="emailAddress"
|
customInputId="emailAddress"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="email-address-required|email-address-format" />
|
validationRules="email-address-required|email-address-format" />
|
||||||
|
|
||||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="alertInvalidZip"
|
ref="alertInvalidZip"
|
||||||
v-if="displayInvalidZipAlert"
|
v-if="displayInvalidZipAlert"
|
||||||
class="my-4"
|
class="my-4"
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
class="my-4"
|
class="my-4"
|
||||||
:manualHeadline="AlertPerfectMatchInsuranceVerifiedHeader"
|
:manualHeadline="AlertPerfectMatchInsuranceVerifiedHeader"
|
||||||
:manualCopy="AlertPerfectMatchInsuranceVerifiedBody"
|
:manualCopy="AlertPerfectMatchInsuranceVerifiedBody"
|
||||||
v-model="customAlertData"
|
v-model="customAlertData"
|
||||||
v-if="
|
v-if="
|
||||||
vinPopulatedOnPageLoad &&
|
vinPopulatedOnPageLoad &&
|
||||||
isInsuranceVerified &&
|
isInsuranceVerified &&
|
||||||
!displayInvalidZipAlert &&
|
!displayInvalidZipAlert &&
|
||||||
!displayNonServiceableZipAlert
|
!displayNonServiceableZipAlert
|
||||||
"
|
"
|
||||||
alertClass="alert-success" />
|
alertClass="alert-success" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
class="my-4"
|
class="my-4"
|
||||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
v-model="customAlertData"
|
v-model="customAlertData"
|
||||||
v-if="displayMatchedDifferentVehicleAlert"
|
v-if="displayMatchedDifferentVehicleAlert"
|
||||||
alertClass="alert-warning" />
|
alertClass="alert-warning" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
class="my-4"
|
class="my-4"
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
v-model="customAlertData"
|
v-model="customAlertData"
|
||||||
v-if="displayNonServiceableZipAlert"
|
v-if="displayNonServiceableZipAlert"
|
||||||
alertClass="alert-danger" />
|
alertClass="alert-danger" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
class="my-4"
|
class="my-4"
|
||||||
v-model="customAlertData"
|
v-model="customAlertData"
|
||||||
v-if="displayVinNotFoundAlert"
|
v-if="displayVinNotFoundAlert"
|
||||||
alertClass="alert-danger"
|
alertClass="alert-danger"
|
||||||
cmsWidgetName="AlertVinNotFoundWidget" />
|
cmsWidgetName="AlertVinNotFoundWidget" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
class="my-4"
|
class="my-4"
|
||||||
:manualHeadline="AlertPerfectMatchInsuranceNotVerifiedHeader"
|
:manualHeadline="AlertPerfectMatchInsuranceNotVerifiedHeader"
|
||||||
:manualCopy="AlertPerfectMatchInsuranceNotVerifiedBody"
|
:manualCopy="AlertPerfectMatchInsuranceNotVerifiedBody"
|
||||||
v-model="customAlertData"
|
v-model="customAlertData"
|
||||||
v-if="
|
v-if="
|
||||||
vinPopulatedOnPageLoad &&
|
vinPopulatedOnPageLoad &&
|
||||||
!isInsuranceVerified &&
|
!isInsuranceVerified &&
|
||||||
!displayInvalidZipAlert &&
|
!displayInvalidZipAlert &&
|
||||||
!displayNonServiceableZipAlert
|
!displayNonServiceableZipAlert
|
||||||
"
|
"
|
||||||
alertClass="alert-success" />
|
alertClass="alert-success" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 col-lg-3"> </div>
|
<div class="d-none d-md-block col-md-2 col-lg-3"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -300,7 +296,7 @@ export default {
|
||||||
|
|
||||||
// Check if the CarId is different from the lookup vs what is in state currently.
|
// Check if the CarId is different from the lookup vs what is in state currently.
|
||||||
this.isCarIdDifferent =
|
this.isCarIdDifferent =
|
||||||
resultMap.vehicleLookupResponse.carId !== this.$store.getters.vehicle.carId;
|
resultMap.vehicleLookupResponse.carId !== this.$store.getters.vehicle.carId;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.isCarIdDifferent &&
|
this.isCarIdDifferent &&
|
||||||
|
|
@ -400,16 +396,16 @@ export default {
|
||||||
getVinFromImage(image) {
|
getVinFromImage(image) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_IMAGE, image)
|
this.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_IMAGE, image)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.data.length > 0) {
|
if (response.data.length > 0) {
|
||||||
resolve(response.data[0]);
|
resolve(response.data[0]);
|
||||||
} else {
|
} else {
|
||||||
reject("No VINs detected.");
|
reject("No VINs detected.");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
reject("An error occurred during the lookup.");
|
reject("An error occurred during the lookup.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
resetAlerts() {
|
resetAlerts() {
|
||||||
|
|
@ -432,10 +428,10 @@ export default {
|
||||||
},
|
},
|
||||||
AlertMatchedDifferentVehicleBody() {
|
AlertMatchedDifferentVehicleBody() {
|
||||||
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
|
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
|
||||||
.replaceAll("{custom:damage}", getDamageString())
|
.replaceAll("{custom:damage}", getDamageString())
|
||||||
.replaceAll("{custom:vinlookupYear}", this.customAlertData?.vehicleInfo?.year)
|
.replaceAll("{custom:vinlookupYear}", this.customAlertData?.vehicleInfo?.year)
|
||||||
.replaceAll("{custom:vinlookupMake}", this.customAlertData?.vehicleInfo?.make)
|
.replaceAll("{custom:vinlookupMake}", this.customAlertData?.vehicleInfo?.make)
|
||||||
.replaceAll("{custom:vinlookupModel}", this.customAlertData?.vehicleInfo?.model);
|
.replaceAll("{custom:vinlookupModel}", this.customAlertData?.vehicleInfo?.model);
|
||||||
},
|
},
|
||||||
AlertNonServiceableZipHeader() {
|
AlertNonServiceableZipHeader() {
|
||||||
return this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll(
|
return this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue