Merge pull request #3026 from Safelite/rlsmerge/2026.01.29-to-develop
Rlsmerge/2026.01.29 to develop
This commit is contained in:
commit
56979a542f
14 changed files with 395 additions and 4 deletions
|
|
@ -15,6 +15,7 @@ const GaCategories = {
|
||||||
APPOINTMENT: "Appointment",
|
APPOINTMENT: "Appointment",
|
||||||
SERVICE_LOCATION: "service-location",
|
SERVICE_LOCATION: "service-location",
|
||||||
CONFIRMATION_CLICKED: "confirmation clicked",
|
CONFIRMATION_CLICKED: "confirmation clicked",
|
||||||
|
RECAL_DISCLAIMER: "Recalibration disclaimer",
|
||||||
};
|
};
|
||||||
|
|
||||||
const GaActions = {
|
const GaActions = {
|
||||||
|
|
@ -29,6 +30,7 @@ const GaActions = {
|
||||||
MORE_LOCATIONS_CLICKED: "more_locations_clicked",
|
MORE_LOCATIONS_CLICKED: "more_locations_clicked",
|
||||||
YES: "yes",
|
YES: "yes",
|
||||||
NO: "no",
|
NO: "no",
|
||||||
|
ACKNOWLEDGED: "Acknowledged",
|
||||||
};
|
};
|
||||||
|
|
||||||
const GaLabels = {
|
const GaLabels = {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ const experimentSettings = {
|
||||||
SUPPRESS_VIN_CAPTURE: "SuppressVinCapture",
|
SUPPRESS_VIN_CAPTURE: "SuppressVinCapture",
|
||||||
DISPLAY_AVAILABILITY_INDICATORS: "DisplayAvailabilityIndicators",
|
DISPLAY_AVAILABILITY_INDICATORS: "DisplayAvailabilityIndicators",
|
||||||
PIA_EXPERIENCE: "PIA Experience",
|
PIA_EXPERIENCE: "PIA Experience",
|
||||||
|
CONDITIONAL_PROVIDER_NUMBERS: "ConditionalProviderNumbers",
|
||||||
|
CONDITIONAL_PROVIDER_NUMBERS_2: "ConditionalProviderNumbers2",
|
||||||
|
CONDITIONAL_PROVIDER_SHUTOFF_DATE: "ConditionalProviderShutoffDate",
|
||||||
PIA_INSURANCE: "DisplayPIAInsurance",
|
PIA_INSURANCE: "DisplayPIAInsurance",
|
||||||
SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA",
|
SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA",
|
||||||
IS_EMAIL_OPTIONAL: "isEmailOptional",
|
IS_EMAIL_OPTIONAL: "isEmailOptional",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ const PREMIUM_FEE_PART_TYPE = "EARLY BIRD";
|
||||||
|
|
||||||
const PRICING_BY_DAY_PART_TYPE = "PREMAPPT GEN";
|
const PRICING_BY_DAY_PART_TYPE = "PREMAPPT GEN";
|
||||||
|
|
||||||
|
const RECAL_ACK_YES = "Yes";
|
||||||
|
|
||||||
const RouteCodeFlags = {
|
const RouteCodeFlags = {
|
||||||
ALL_DAY_DROP_OFF: "ALL DAY DROP OFF",
|
ALL_DAY_DROP_OFF: "ALL DAY DROP OFF",
|
||||||
OVERNIGHT_DROP_OFF: "OVERNIGHT DROP OFF",
|
OVERNIGHT_DROP_OFF: "OVERNIGHT DROP OFF",
|
||||||
|
|
@ -31,4 +33,5 @@ export {
|
||||||
PRICING_BY_DAY_PART_TYPE,
|
PRICING_BY_DAY_PART_TYPE,
|
||||||
RouteCodeFlags,
|
RouteCodeFlags,
|
||||||
cmsWidgetFieldMappings,
|
cmsWidgetFieldMappings,
|
||||||
|
RECAL_ACK_YES,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ const storeActions = {
|
||||||
SAVE_PAYPAL_TOKEN: "savePaypalToken",
|
SAVE_PAYPAL_TOKEN: "savePaypalToken",
|
||||||
SAVE_NEXTGEN_SETTLED_AMOUNT: "saveNextGenSettledAmount",
|
SAVE_NEXTGEN_SETTLED_AMOUNT: "saveNextGenSettledAmount",
|
||||||
SAVE_IS_RECAL_ACK_OPT_IN: "saveIsRecalAckOptIn",
|
SAVE_IS_RECAL_ACK_OPT_IN: "saveIsRecalAckOptIn",
|
||||||
|
SAVE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING: "saveIsRecalAcknowledgedForScheduling",
|
||||||
SAVE_IS_OEM_GLASS_SELECTED: "saveIsOemGlassSelected",
|
SAVE_IS_OEM_GLASS_SELECTED: "saveIsOemGlassSelected",
|
||||||
SAVE_IS_MSR_FEE_APPLICABLE: "saveIsMSRFeeApplicable",
|
SAVE_IS_MSR_FEE_APPLICABLE: "saveIsMSRFeeApplicable",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ const storeMutations = {
|
||||||
LOCK_TOKEN: "updateLockToken",
|
LOCK_TOKEN: "updateLockToken",
|
||||||
UPDATE_SETTLED_TENDER_AMOUNT: "updateSettledTenderAmount",
|
UPDATE_SETTLED_TENDER_AMOUNT: "updateSettledTenderAmount",
|
||||||
UPDATE_IS_RECAL_ACK_OPT_IN: "updateIsRecalAckOptIn",
|
UPDATE_IS_RECAL_ACK_OPT_IN: "updateIsRecalAckOptIn",
|
||||||
|
UPDATE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING: "updateIsRecalAcknowledgedForScheduling",
|
||||||
UPDATE_IS_OEM_GLASS_SELECTED: "updateIsOemGlassSelected",
|
UPDATE_IS_OEM_GLASS_SELECTED: "updateIsOemGlassSelected",
|
||||||
UPDATE_IS_MSR_FEE_APPLICABLE: "updateIsMSRFeeApplicable",
|
UPDATE_IS_MSR_FEE_APPLICABLE: "updateIsMSRFeeApplicable",
|
||||||
UPDATE_CASH_PRICE_SUBTOTAL: "updateCashPriceSubTotal",
|
UPDATE_CASH_PRICE_SUBTOTAL: "updateCashPriceSubTotal",
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,14 @@ import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
|
|
||||||
const recalPartTypes = [partTypeStrings.RECALIBRATION, partTypeStrings.ADAS_RECALIBRATION];
|
const recalPartTypes = [partTypeStrings.RECALIBRATION, partTypeStrings.ADAS_RECALIBRATION];
|
||||||
|
|
||||||
|
export function anyPartWithRequiresRecalFlag(lineItems) {
|
||||||
|
if (!lineItems) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lineItems.glassParts?.some((li) => li.requiresRecalibration === true);
|
||||||
|
}
|
||||||
|
|
||||||
export function isRecalPartOrHasChildRecalPart(lineItem) {
|
export function isRecalPartOrHasChildRecalPart(lineItem) {
|
||||||
if (lineItem.childParts && lineItem.childParts.length > 0) {
|
if (lineItem.childParts && lineItem.childParts.length > 0) {
|
||||||
return isRecalPart(lineItem) || containsRecalParts(lineItem.childParts);
|
return isRecalPart(lineItem) || containsRecalParts(lineItem.childParts);
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@
|
||||||
:isItac="isItac"
|
:isItac="isItac"
|
||||||
:isNoComp="isNoComp"
|
:isNoComp="isNoComp"
|
||||||
:isCollapsible="false" />
|
:isCollapsible="false" />
|
||||||
|
<textBlock
|
||||||
|
class="payment-disclaimer"
|
||||||
|
marginTopSizeOverride="0"
|
||||||
|
cmsWidgetName="PaymentDisclaimerWidget" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -56,6 +60,7 @@ import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
|
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
|
@ -645,6 +650,7 @@ export default {
|
||||||
navbar,
|
navbar,
|
||||||
cart,
|
cart,
|
||||||
alert,
|
alert,
|
||||||
|
textBlock,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -671,5 +677,10 @@ export default {
|
||||||
margin: 0 0.5rem;
|
margin: 0 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.payment-disclaimer p {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -810,11 +810,51 @@ export default {
|
||||||
const piaInsurance = this.getSettingValue(experimentSettings.PIA_INSURANCE);
|
const piaInsurance = this.getSettingValue(experimentSettings.PIA_INSURANCE);
|
||||||
|
|
||||||
if (this.isInsurance) {
|
if (this.isInsurance) {
|
||||||
return piaInsurance === "true" && this.currentDeductible > 0;
|
return (
|
||||||
|
(piaInsurance === "true" || this.isConditionalPIAEnabled) &&
|
||||||
|
this.currentDeductible > 0
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return piaExperience === "PIA Optional" || piaExperience === "PIA Required";
|
if (piaExperience?.includes("PIA Disabled")) {
|
||||||
|
return this.isConditionalPIAEnabled;
|
||||||
|
} else {
|
||||||
|
return piaExperience === "PIA Optional" || piaExperience === "PIA Required";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
isConditionalPIAEnabled() {
|
||||||
|
const conditionalProviderNumbers = this.getSettingValue(
|
||||||
|
experimentSettings.CONDITIONAL_PROVIDER_NUMBERS
|
||||||
|
);
|
||||||
|
const conditionalProviderNumbers2 = this.getSettingValue(
|
||||||
|
experimentSettings.CONDITIONAL_PROVIDER_NUMBERS_2
|
||||||
|
);
|
||||||
|
const conditionalProviderShutoffDate = this.getSettingValue(
|
||||||
|
experimentSettings.CONDITIONAL_PROVIDER_SHUTOFF_DATE
|
||||||
|
);
|
||||||
|
|
||||||
|
const allConditionalProviderNumbers = [
|
||||||
|
conditionalProviderNumbers,
|
||||||
|
conditionalProviderNumbers2,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(",");
|
||||||
|
const providerNumber =
|
||||||
|
this.$store.getters.order.serviceLocation.provider.providerNumber;
|
||||||
|
const appointmentDate = new Date(this.$store.getters.order.schedule.date);
|
||||||
|
const shutoffDate = new Date(conditionalProviderShutoffDate);
|
||||||
|
if (allConditionalProviderNumbers && conditionalProviderShutoffDate) {
|
||||||
|
const providerNumbersArray = allConditionalProviderNumbers
|
||||||
|
.split(",")
|
||||||
|
.map((num) => num.trim());
|
||||||
|
if (!providerNumbersArray.includes(providerNumber)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return appointmentDate <= shutoffDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
paymentMethod() {
|
paymentMethod() {
|
||||||
if (!this.isPiaEnabled) {
|
if (!this.isPiaEnabled) {
|
||||||
return paymentMethods.LATER;
|
return paymentMethods.LATER;
|
||||||
|
|
|
||||||
223
src/layouts/schedule/recal-ack-modal/recal-ack-modal.vue
Normal file
223
src/layouts/schedule/recal-ack-modal/recal-ack-modal.vue
Normal file
|
|
@ -0,0 +1,223 @@
|
||||||
|
// This modal is used to acknowledge the recal disclaimer during scheduling. // It will trigger when
|
||||||
|
there is a glass part with requiresRecalibration = true // but there is no recalibration part in
|
||||||
|
lineItems. This mostly occurs when // a zip code that does mobile only is selected but the vehicle
|
||||||
|
requires // recalibration.
|
||||||
|
<template>
|
||||||
|
<div id="recal-ack-modal-container">
|
||||||
|
<modal
|
||||||
|
:ref="modalName"
|
||||||
|
suppressPageScroll
|
||||||
|
:onModalClosedCallback="onModalClosed"
|
||||||
|
:footerButtonText="modalFooterText"
|
||||||
|
:isFooterButtonPrimary="true"
|
||||||
|
@footer-button-event="ackRecalDisclaimer">
|
||||||
|
<p class="modal-body-inner" v-html="modalBodyText"></p>
|
||||||
|
<div>
|
||||||
|
<div class="learn-more">
|
||||||
|
<a href="javascript:;" @click="learnMore = !learnMore">{{ learnMoreLabel }}</a>
|
||||||
|
<div v-if="learnMore">{{ learnMoreText }}</div>
|
||||||
|
</div>
|
||||||
|
<buttonQuestion
|
||||||
|
:questionText="questionText"
|
||||||
|
:answers="answersFromCms"
|
||||||
|
:groupName="groupName"
|
||||||
|
buttonTypeString="listButtonHorizontal"
|
||||||
|
v-model="selectedValues"
|
||||||
|
isRequired />
|
||||||
|
</div>
|
||||||
|
<template v-slot:modal-header-slot>
|
||||||
|
<span>{{ modalHeaderText }}</span>
|
||||||
|
</template>
|
||||||
|
</modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import modal from "@/digital-components/modal/modal";
|
||||||
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
|
import { RECAL_ACK_YES } from "@/constants/schedule-constants";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "recal-ack-modal",
|
||||||
|
props: {
|
||||||
|
agreementWidgetName: String,
|
||||||
|
modalWidgetName: String,
|
||||||
|
groupName: String,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
learnMore: false,
|
||||||
|
isModalOpen: true,
|
||||||
|
isRecalAcknowledged: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openModal() {
|
||||||
|
this.modal.openModal();
|
||||||
|
},
|
||||||
|
onModalClosed() {
|
||||||
|
this.$emit("recal-ack-modal");
|
||||||
|
},
|
||||||
|
closeModal() {
|
||||||
|
this.modal.closeModal();
|
||||||
|
},
|
||||||
|
setIsModalOpen(isOpen) {
|
||||||
|
this.isModalOpen = isOpen;
|
||||||
|
},
|
||||||
|
ackRecalDisclaimer() {
|
||||||
|
this.modal.closeModal();
|
||||||
|
|
||||||
|
if (this.isRecalAcknowledged === RECAL_ACK_YES) {
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.GaCategories.RECAL_DISCLAIMER,
|
||||||
|
this.GaActions.ACKNOWLEDGED,
|
||||||
|
this.isRecalAcknowledged,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
this.$emit("recalAcknowledged", this.isRecalAcknowledged);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
questionText() {
|
||||||
|
return this.getCmsContent(this.agreementWidgetName, "QuestionText");
|
||||||
|
},
|
||||||
|
answersFromCms() {
|
||||||
|
return this.getCmsContent(this.agreementWidgetName, "Answers");
|
||||||
|
},
|
||||||
|
learnMoreLabel() {
|
||||||
|
return this.getCmsContent(this.modalWidgetName, "SubheaderText");
|
||||||
|
},
|
||||||
|
learnMoreText() {
|
||||||
|
return this.getCmsContent(this.modalWidgetName, "FooterText2");
|
||||||
|
},
|
||||||
|
modalName() {
|
||||||
|
return this.modalWidgetName;
|
||||||
|
},
|
||||||
|
modal() {
|
||||||
|
return this.$refs[this.modalName];
|
||||||
|
},
|
||||||
|
modalHeaderText() {
|
||||||
|
return this.getCmsContent(this.modalWidgetName, "HeaderText");
|
||||||
|
},
|
||||||
|
modalBodyText() {
|
||||||
|
return this.getCmsContent(this.modalWidgetName, "BodyText");
|
||||||
|
},
|
||||||
|
modalFooterText() {
|
||||||
|
return this.getCmsContent(this.modalWidgetName, "FooterText");
|
||||||
|
},
|
||||||
|
selectedValues: {
|
||||||
|
get: function () {
|
||||||
|
return this.isRecalAcknowledged;
|
||||||
|
},
|
||||||
|
set: function (newValue) {
|
||||||
|
this.isRecalAcknowledged = this.answersFromCms.find(
|
||||||
|
(a) => a.Name === newValue
|
||||||
|
)?.Text;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: { modal, buttonQuestion },
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
#recal-ack-modal-container {
|
||||||
|
.modal-component {
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
.modal-dialog {
|
||||||
|
left: 0;
|
||||||
|
align-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 34.875rem;
|
||||||
|
transform: translate(0, 0);
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.modal-dialog {
|
||||||
|
.modal-content {
|
||||||
|
.btn-close {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.modal-header {
|
||||||
|
width: 75%;
|
||||||
|
padding: 0 1.25rem 0 1.25rem;
|
||||||
|
flex-direction: column;
|
||||||
|
& > span {
|
||||||
|
color: $black;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-title {
|
||||||
|
font-size: $font-size-20;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.modal-body {
|
||||||
|
padding: 0.875rem 1.25rem 1.875rem 1.25rem;
|
||||||
|
|
||||||
|
.modal-body-inner {
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
font-size: $font-size-14;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-inner-wrapper > .col:first-child .list-button-horizontal {
|
||||||
|
border-bottom-left-radius: 50rem;
|
||||||
|
border-top-left-radius: 50rem;
|
||||||
|
}
|
||||||
|
.col:first-of-type .list-button-horizontal .list-button-horizontal-content,
|
||||||
|
.list-group:first-of-type
|
||||||
|
.list-button-horizontal
|
||||||
|
.list-button-horizontal-content {
|
||||||
|
border-bottom-left-radius: 50rem;
|
||||||
|
border-top-left-radius: 50rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-inner-wrapper > .col:last-child .list-button-horizontal {
|
||||||
|
border-bottom-right-radius: 50rem;
|
||||||
|
border-top-right-radius: 50rem;
|
||||||
|
}
|
||||||
|
.col:last-of-type .list-button-horizontal .list-button-horizontal-content,
|
||||||
|
.list-group:first-of-type
|
||||||
|
.list-button-horizontal
|
||||||
|
.list-button-horizontal-content {
|
||||||
|
border-bottom-right-radius: 50rem;
|
||||||
|
border-top-right-radius: 50rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn-more {
|
||||||
|
padding-bottom: 0;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
a {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.question-text {
|
||||||
|
margin-top: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.modal-footer {
|
||||||
|
flex-flow: wrap-reverse;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
}
|
||||||
|
.modal-footer .modal-footer-button:hover {
|
||||||
|
background-color: $red-1000;
|
||||||
|
border-color: $red-1100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -6,6 +6,12 @@
|
||||||
modalWidgetName="MobileFirstModalWidget"
|
modalWidgetName="MobileFirstModalWidget"
|
||||||
ref="mobileFirstModal"
|
ref="mobileFirstModal"
|
||||||
@confirm-appointment="updateTimeSlotandNavigateForward" />
|
@confirm-appointment="updateTimeSlotandNavigateForward" />
|
||||||
|
<recalAckModal
|
||||||
|
modalWidgetName="RecalAckModalWidget"
|
||||||
|
agreementWidgetName="RecalAgreementQuestionWidget"
|
||||||
|
groupName="recalAckGroup"
|
||||||
|
@recalAcknowledged="updateRecalAcknowledgedAndNavigateForward"
|
||||||
|
ref="recalAckModal" />
|
||||||
<div
|
<div
|
||||||
class="container page-container-grouped-styles"
|
class="container page-container-grouped-styles"
|
||||||
:class="[isMobileFirstModalOpen ? 'hidden-background' : '']">
|
:class="[isMobileFirstModalOpen ? 'hidden-background' : '']">
|
||||||
|
|
@ -190,6 +196,7 @@ import shopLocation from "@/layouts/schedule/shop-location/shop-location";
|
||||||
import timeSlotQuestion from "@/layouts/schedule/time-slot-question/time-slot-question.vue";
|
import timeSlotQuestion from "@/layouts/schedule/time-slot-question/time-slot-question.vue";
|
||||||
import durationTextBlock from "@/layouts/schedule/duration-text-block/duration-text-block.vue";
|
import durationTextBlock from "@/layouts/schedule/duration-text-block/duration-text-block.vue";
|
||||||
import mobileFirstModal from "@/layouts/schedule/mobile-first-modal/mobile-first-modal.vue";
|
import mobileFirstModal from "@/layouts/schedule/mobile-first-modal/mobile-first-modal.vue";
|
||||||
|
import recalAckModal from "@/layouts/schedule/recal-ack-modal/recal-ack-modal.vue";
|
||||||
|
|
||||||
import shopQuestion from "@/layouts/service-location/shop-question/shop-question";
|
import shopQuestion from "@/layouts/service-location/shop-question/shop-question";
|
||||||
import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup";
|
import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup";
|
||||||
|
|
@ -216,6 +223,7 @@ import {
|
||||||
RouteCodeFlags,
|
RouteCodeFlags,
|
||||||
PREMIUM_FEE_PART_TYPE,
|
PREMIUM_FEE_PART_TYPE,
|
||||||
PRICING_BY_DAY_PART_TYPE,
|
PRICING_BY_DAY_PART_TYPE,
|
||||||
|
RECAL_ACK_YES,
|
||||||
} from "@/constants/schedule-constants";
|
} from "@/constants/schedule-constants";
|
||||||
|
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
|
@ -242,6 +250,7 @@ import {
|
||||||
isDropOffRouteCode,
|
isDropOffRouteCode,
|
||||||
getTodayDate,
|
getTodayDate,
|
||||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||||
|
import { containsRecalParts, anyPartWithRequiresRecalFlag } from "@/helpers/recal-helper";
|
||||||
|
|
||||||
import { DAYS_OF_WEEK } from "@/digital-components/date-picker/mixins/constants";
|
import { DAYS_OF_WEEK } from "@/digital-components/date-picker/mixins/constants";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { required } from "@/helpers/validation-rules";
|
||||||
|
|
@ -430,6 +439,7 @@ export default {
|
||||||
name: "schedule",
|
name: "schedule",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
isRecalAcknowledgedForScheduling: this.getIsRecalAcknowledgedForSchedulingFromStore(),
|
||||||
selectedDate: this.getSelectedDateFromStore(),
|
selectedDate: this.getSelectedDateFromStore(),
|
||||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||||
mobilePremiumAppointmentFee: null,
|
mobilePremiumAppointmentFee: null,
|
||||||
|
|
@ -1233,6 +1243,9 @@ export default {
|
||||||
|
|
||||||
this.isShowMobileFirstAppt && this.hideLoadingModal();
|
this.isShowMobileFirstAppt && this.hideLoadingModal();
|
||||||
},
|
},
|
||||||
|
getIsRecalAcknowledgedForSchedulingFromStore() {
|
||||||
|
return store.getters.order.isRecalAcknowledgedForScheduling;
|
||||||
|
},
|
||||||
getScheduleApiResponse,
|
getScheduleApiResponse,
|
||||||
getServiceZipCtuCodeFromStore() {
|
getServiceZipCtuCodeFromStore() {
|
||||||
return store.getters.order.serviceLocation.zipCodeCtu;
|
return store.getters.order.serviceLocation.zipCodeCtu;
|
||||||
|
|
@ -1351,7 +1364,25 @@ export default {
|
||||||
hideLoadingModal() {
|
hideLoadingModal() {
|
||||||
this.$refs.loadingModal.hideModal();
|
this.$refs.loadingModal.hideModal();
|
||||||
},
|
},
|
||||||
|
async closeRecalAcknowledgementPopup() {
|
||||||
|
this.showRecalAcknowledgementPopup = false;
|
||||||
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
|
const showRecalAcknowledgementModal = this.showRecalAcknowledgementModal();
|
||||||
|
if (
|
||||||
|
showRecalAcknowledgementModal &&
|
||||||
|
this.isRecalAcknowledgedForScheduling !== RECAL_ACK_YES
|
||||||
|
) {
|
||||||
|
this.showRecalAcknowledgementPopup = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING,
|
||||||
|
this.isRecalAcknowledgedForScheduling,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
this.navigatingForward = true;
|
this.navigatingForward = true;
|
||||||
var ctu = this.zipCodeCtu;
|
var ctu = this.zipCodeCtu;
|
||||||
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||||
|
|
@ -1675,7 +1706,27 @@ export default {
|
||||||
this.selectedProvider = this.shopProviderData.shopProviders[0];
|
this.selectedProvider = this.shopProviderData.shopProviders[0];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleZipCodeChange(newZipCode) {
|
async handleZipCodeChange(newZipCode) {
|
||||||
|
// if we were showing the recal ack modal and now are changing the zip, we need to navigate
|
||||||
|
// to service-zip so we can get call parts again to add the recal part if needed
|
||||||
|
if (this.shouldShowRecalAckModal()) {
|
||||||
|
await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
|
{
|
||||||
|
zipCode: newZipCode.zipCode,
|
||||||
|
state: newZipCode.state,
|
||||||
|
zipCodeCtu: newZipCode.zipCodeCtu,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
this.$router.navigateWithSaving(
|
||||||
|
this.navigationScenarios.ZIP_CODE_CHANGED_RECAL_ACK,
|
||||||
|
this.pageName
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.resetMobileLocation();
|
this.resetMobileLocation();
|
||||||
|
|
||||||
getShopProviderData(newZipCode.zipCode, this.pageName).then((result) => {
|
getShopProviderData(newZipCode.zipCode, this.pageName).then((result) => {
|
||||||
|
|
@ -1752,6 +1803,32 @@ export default {
|
||||||
setSelectedDateToFirstAvailable() {
|
setSelectedDateToFirstAvailable() {
|
||||||
this.selectedDate = this.getFirstAvailableDate();
|
this.selectedDate = this.getFirstAvailableDate();
|
||||||
},
|
},
|
||||||
|
showRecalAcknowledgementModal() {
|
||||||
|
if (this.shouldShowRecalAckModal()) {
|
||||||
|
this.$refs.navbar.removeLoader();
|
||||||
|
this.$refs.recalAckModal.openModal();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.closeRecalAcknowledgementPopup();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
shouldShowRecalAckModal() {
|
||||||
|
// if any of the glass parts contain an item with the requiresRecalibration flag set to true
|
||||||
|
// and the order does not contain a recalibration part, show the recalibration acknowledgement modal
|
||||||
|
const order = this.$store.getters.order;
|
||||||
|
const containsRecalPart = containsRecalParts(order.lineItems);
|
||||||
|
const hasPartWithRecalRequirement = anyPartWithRequiresRecalFlag(order.lineItems);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!containsRecalPart &&
|
||||||
|
hasPartWithRecalRequirement &&
|
||||||
|
this.isRecalAcknowledgedForScheduling !== RECAL_ACK_YES
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
async showMobileFirstModal() {
|
async showMobileFirstModal() {
|
||||||
if (!this.selectedRouteCodeData?.routeCode) {
|
if (!this.selectedRouteCodeData?.routeCode) {
|
||||||
const pmMobileDays = experimentMixin.methods.getSettingValue(
|
const pmMobileDays = experimentMixin.methods.getSettingValue(
|
||||||
|
|
@ -1875,6 +1952,10 @@ export default {
|
||||||
this.updateTimeSlot(timeSlotObj);
|
this.updateTimeSlot(timeSlotObj);
|
||||||
this.forwardButtonAction();
|
this.forwardButtonAction();
|
||||||
},
|
},
|
||||||
|
updateRecalAcknowledgedAndNavigateForward(isAcknowledged) {
|
||||||
|
this.isRecalAcknowledgedForScheduling = isAcknowledged;
|
||||||
|
this.forwardButtonAction();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
appointmentTypeFromAppointmentTypeQuestion: {
|
appointmentTypeFromAppointmentTypeQuestion: {
|
||||||
|
|
@ -1920,7 +2001,7 @@ export default {
|
||||||
textBlock,
|
textBlock,
|
||||||
timeSlotQuestion,
|
timeSlotQuestion,
|
||||||
mobileFirstModal,
|
mobileFirstModal,
|
||||||
|
recalAckModal,
|
||||||
alert,
|
alert,
|
||||||
serviceZipModalQuestion,
|
serviceZipModalQuestion,
|
||||||
appointmentTypeQuestion,
|
appointmentTypeQuestion,
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ const navigationScenarios = {
|
||||||
|
|
||||||
// Schedule
|
// Schedule
|
||||||
CLICKED_CHANGE_LOCATION: "CLICKED_CHANGE_LOCATION",
|
CLICKED_CHANGE_LOCATION: "CLICKED_CHANGE_LOCATION",
|
||||||
|
ZIP_CODE_CHANGED_RECAL_ACK: "ZIP_CODE_CHANGED_RECAL_ACK",
|
||||||
|
|
||||||
// Payment
|
// Payment
|
||||||
CLICKED_INSURANCE: "CLICKED_INSURANCE",
|
CLICKED_INSURANCE: "CLICKED_INSURANCE",
|
||||||
|
|
|
||||||
|
|
@ -486,6 +486,10 @@ const routingTable = function () {
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOBILE_SERVICE,
|
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOBILE_SERVICE,
|
||||||
destinationPageData: routeData.MOBILE_DETAILS,
|
destinationPageData: routeData.MOBILE_DETAILS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.ZIP_CODE_CHANGED_RECAL_ACK,
|
||||||
|
destinationPageData: routeData.SERVICE_ZIP,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,7 @@ const getDefaultState = () => {
|
||||||
lockToken: null,
|
lockToken: null,
|
||||||
settledTenderAmount: 0,
|
settledTenderAmount: 0,
|
||||||
isRecalAckOptIn: false,
|
isRecalAckOptIn: false,
|
||||||
|
isRecalAcknowledgedForScheduling: "",
|
||||||
isMSRFeeApplicable: false,
|
isMSRFeeApplicable: false,
|
||||||
},
|
},
|
||||||
applicationUser: {
|
applicationUser: {
|
||||||
|
|
@ -343,6 +344,9 @@ export const mutations = {
|
||||||
updateIsRecalAckOptIn(state, isRecalAckOptIn) {
|
updateIsRecalAckOptIn(state, isRecalAckOptIn) {
|
||||||
state.order.isRecalAckOptIn = isRecalAckOptIn;
|
state.order.isRecalAckOptIn = isRecalAckOptIn;
|
||||||
},
|
},
|
||||||
|
updateIsRecalAcknowledgedForScheduling(state, isRecalAcknowledgedForScheduling) {
|
||||||
|
state.order.isRecalAcknowledgedForScheduling = isRecalAcknowledgedForScheduling;
|
||||||
|
},
|
||||||
updateIsOemGlassSelected(state, isOemGlassSelected) {
|
updateIsOemGlassSelected(state, isOemGlassSelected) {
|
||||||
state.order.damage.installOemGlass = isOemGlassSelected;
|
state.order.damage.installOemGlass = isOemGlassSelected;
|
||||||
},
|
},
|
||||||
|
|
@ -2965,6 +2969,13 @@ export const actions = {
|
||||||
context.commit(storeMutations.UPDATE_IS_RECAL_ACK_OPT_IN, isRecalAckOptIn);
|
context.commit(storeMutations.UPDATE_IS_RECAL_ACK_OPT_IN, isRecalAckOptIn);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
saveIsRecalAcknowledgedForScheduling(context, isRecalAcknowledgedForScheduling) {
|
||||||
|
context.commit(
|
||||||
|
storeMutations.UPDATE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING,
|
||||||
|
isRecalAcknowledgedForScheduling
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
saveIsOemGlassSelected(context, isOemGlassSelected) {
|
saveIsOemGlassSelected(context, isOemGlassSelected) {
|
||||||
context.commit(storeMutations.UPDATE_IS_OEM_GLASS_SELECTED, isOemGlassSelected);
|
context.commit(storeMutations.UPDATE_IS_OEM_GLASS_SELECTED, isOemGlassSelected);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ $red-600: #ac160b;
|
||||||
$red-700: #840900;
|
$red-700: #840900;
|
||||||
$red-800: #5b0600;
|
$red-800: #5b0600;
|
||||||
$red-900: #330300;
|
$red-900: #330300;
|
||||||
|
$red-1000: #a80019;
|
||||||
|
$red-1100: #791710;
|
||||||
|
|
||||||
// Greens
|
// Greens
|
||||||
$green-100: #e3f2ea;
|
$green-100: #e3f2ea;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue