DigitalConsumer.FixMyGlass/src/layouts/bailout/bailout.vue
2026-05-22 11:56:50 -04:00

274 lines
9.9 KiB
Vue

<template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
<div class="container ymm-return">
<div class="row">
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
<funnelSubHeader
class="mb-5"
:cmsWidgetName="getSubHeaderWidget"
:alignLeft="true" />
<textboxQuestion
isRequired
class="mb-4"
cmsWidgetName="FirstNameQuestionWidget"
v-model="firstName"
ref="firstName"
customInputId="firstName"
validationRules="first-name-required" />
<textboxQuestion
isRequired
class="mb-4"
cmsWidgetName="LastNameQuestionWidget"
v-model="lastName"
ref="lastName"
customInputId="lastName"
validationRules="last-name-required" />
<textboxQuestion
isRequired
class="mb-4"
cmsWidgetName="EmailQuestionWidget"
v-model="emailAddress"
inputId="email"
validationRules="email-address-required|email-address-format" />
<phoneNumberQuestion
isRequired
class="mb-4"
cmsWidgetName="PhoneNumberQuestionWidget"
v-model="phoneNumber"
validationRules="phone-number-required" />
<textboxQuestion
isRequired
v-if="!serviceZipCode"
class="mb-4"
cmsWidgetName="ServiceZipQuestionWidget"
v-model="serviceZipCode"
ref="serviceZip"
customInputId="serviceZip"
mask="#####"
validationRules="service-zip-required|service-zip-format" />
<alert
ref="alertInvalidZip"
v-if="displayInvalidZipAlert"
class="mb-4"
cmsWidgetName="AlertInvalidZipWidget"
alertClass="alert-danger"
v-bind:isDismissible="false" />
<checkboxQuestion
class="mb-5"
cmsWidgetName="TextMeQuestionWidget"
v-model="isSmsOptIn" />
<navbar
cmsWidgetName="FunnelFooterWidget"
ref="navbar"
:isForwardActionDisabled="!meta.valid"
@back-clicked="backButtonAction"
@ForwardClicked="forwardButtonAction" />
<textBlock
class="mb-5"
cmsWidgetName="DisclaimerCopyWidget"
typeStyle="caption" />
</div>
</div>
</div>
</Form>
</template>
<script>
import { Form, defineRule } from "vee-validate";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import navbar from "@/fmg-components/nav-bar/nav-bar";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import alert from "@/ux-components/alert/alert";
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
import phoneNumberQuestion from "@/digital-components/phone-number-question/phone-number-question";
import textBlock from "@/digital-components/text-block/text-block";
import checkboxQuestion from "@/digital-components/checkbox-question/checkbox-question";
import { routeData } from "@/router/constants/routes";
import { bailoutCodes } from "@/constants/bailout-codes";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
import { errorMessages } from "@/constants/error-messages";
import { required, regex } from "@/helpers/validation-rules";
// DEFINE VALIDATION RULES
defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED));
defineRule("last-name-required", required(errorMessages.LAST_NAME_REQUIRED));
defineRule("phone-number-required", required(errorMessages.PHONE_REQUIRED));
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
defineRule(
"email-address-format",
regex(
/^([a-zA-Z0-9_.+]+)@([a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.)+([a-zA-Z]{2,})$/,
errorMessages.EMAIL_ADDRESS_FORMAT
)
);
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
defineRule(
"service-zip-format",
regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT)
);
export default {
name: "bailout",
mixins: [],
data() {
return {
bailoutCode: this.getBailoutCodeFromStore(),
firstName: this.getFirstNameFromStore(),
lastName: this.getLastNameFromStore(),
emailAddress: this.getEmailAddressFromStore(),
phoneNumber: this.getPhoneNumberFromStore(),
serviceZipCode: this.getServiceZipFromStore(),
isSmsOptIn: this.getIsSmsOptInFromStore(),
displayInvalidZipAlert: false,
};
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle API calls in parallel before handling results.
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
// Hydrate page with results
next(async (vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
methods: {
getBailoutCodeFromStore() {
return store.getters.applicationUser.bailoutCode;
},
getFirstNameFromStore() {
return store.getters.order.customer.firstName;
},
getLastNameFromStore() {
return store.getters.order.customer.lastName;
},
getEmailAddressFromStore() {
return store.getters.order.customer.emailAddress;
},
getPhoneNumberFromStore() {
return store.getters.order.customer.phoneNumber;
},
getServiceZipFromStore() {
return store.getters.order.serviceLocation.zipCode;
},
getIsSmsOptInFromStore() {
return store.getters.order.customer.isSmsOptIn;
},
async backButtonAction() {
this.$router.go(-1);
},
async forwardButtonAction() {
this.displayInvalidZipAlert = false;
const validateZipResponse = this.dispatchStoreActionWithLogging(
this.storeActions.VALIDATE_ZIP,
{
zip: this.serviceZipCode,
},
this.pageName
);
const saveCustomerDetailsResponse = this.dispatchStoreAction(
this.storeActions.SAVE_CUSTOMER_DETAILS,
{
firstName: this.firstName,
lastName: this.lastName,
emailAddress: this.emailAddress,
phoneNumber: this.phoneNumber,
isSmsOptIn: this.isSmsOptIn,
},
false
);
const promiseResultMap = [
{
resultKey: "validateZipResponse",
promise: validateZipResponse,
},
{
resultKey: "saveCustomerDetailsResponse",
promise: saveCustomerDetailsResponse,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
const isZipValid = resultMap.validateZipResponse.isValid;
if (isZipValid) {
await this.dispatchStoreActionWithLogging(
this.storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
{
zipCode: this.serviceZipCode,
state: resultMap.validateZipResponse.state,
zipCodeCtu: resultMap.validateZipResponse.zipCodeCtu,
},
false
).then(() => {
this.$router.navigateWithPageData(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName,
{
bailoutCode: this.bailoutCode,
submit: true,
}
);
});
} else {
this.displayInvalidZipAlert = true;
return this.$refs.navbar.removeLoader();
}
},
arePagePrerequisitesValid() {
return this.getBailoutCodeFromStore() !== null;
},
},
computed: {
getSubHeaderWidget() {
switch (this.bailoutCode) {
case bailoutCodes.PART_NOT_FOUND:
return "PartsNotFoundSubHeaderWidget";
default:
return "FunnelSubHeaderWidget";
}
},
},
components: {
Form,
funnelHeader,
funnelSubHeader,
alert,
navbar,
textBlock,
phoneNumberQuestion,
checkboxQuestion,
textboxQuestion,
},
};
</script>