Merge branch 'feature/CSR-1012' into feature/CSR-1088
This commit is contained in:
commit
d9cb7d7936
4 changed files with 241 additions and 6 deletions
|
|
@ -2,7 +2,7 @@
|
|||
<!-- Modal -->
|
||||
<div
|
||||
class="modal fade modal-component"
|
||||
v-on="{ 'hidden.bs.modal': resetButtonStyle }"
|
||||
v-on="{ 'hidden.bs.modal': resetButtonStyle, 'shown.bs.modal': onShownCallback }"
|
||||
:id="cmsWidgetName"
|
||||
tabindex="-1"
|
||||
aria-labelledby="ModalComponentLabel"
|
||||
|
|
@ -11,12 +11,13 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
ref="modalXButton"
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body ps-4 pe-4 pt-5 pb-4">
|
||||
<div class="modal-body ps-4 pe-4 pt-5 pb-4" v-if="showModalBody">
|
||||
<img :src="ModalImage" class="mw-100 d-flex mx-auto mb-4" alt="" />
|
||||
<h5 class="mb-4" v-html="ModalHeadline"></h5>
|
||||
<p class="fw-bold mb-2 subheader-text" v-html="ModalSubheadertext"></p>
|
||||
|
|
@ -26,6 +27,7 @@
|
|||
v-if="ModalSubBodyText"
|
||||
v-html="ModalSubBodyText"></p>
|
||||
</div>
|
||||
<slot></slot>
|
||||
<div class="modal-footer px-5 py-4">
|
||||
<buttonMain
|
||||
isPrimary
|
||||
|
|
@ -33,8 +35,7 @@
|
|||
ref="buttonMain"
|
||||
suppressLoader
|
||||
:buttonText="ModalCloseButtonText"
|
||||
@click-event="buttonClick"
|
||||
data-bs-dismiss="modal" />
|
||||
@click-event="footerButtonClick" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -48,6 +49,15 @@ export default {
|
|||
name: "modal",
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
onShownCallback: {
|
||||
type: Function,
|
||||
},
|
||||
|
||||
footerButtonCallback: {
|
||||
type: Function,
|
||||
// return true to close modal
|
||||
// if undefined, footer button closes modal
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
ModalHeadline() {
|
||||
|
|
@ -68,11 +78,26 @@ export default {
|
|||
ModalCloseButtonText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "FooterText");
|
||||
},
|
||||
showModalBody() {
|
||||
return this.ModalBodyText;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resetButtonStyle() {
|
||||
this.$refs.buttonMain.resetButtonStyle();
|
||||
},
|
||||
closeModal() {
|
||||
this.$refs.modalXButton.click();
|
||||
},
|
||||
async footerButtonClick() {
|
||||
if (this.footerButtonCallback) {
|
||||
if (await this.footerButtonCallback()) {
|
||||
this.closeModal();
|
||||
}
|
||||
} else {
|
||||
this.closeModal();
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
buttonMain,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,12 @@ fmg
|
|||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<serviceZipModalQuestion
|
||||
cmsWidgetName="ServiceZipModalWidget"
|
||||
modalWidgetName="ZipModalWidget"
|
||||
textboxQuestionWidgetName="ServiceZipQuestionWidget"
|
||||
alertNonServiceableZipWidgetName="AlertNonServiceableZipWidget"
|
||||
alertInvalidZipWidgetName="AlertInvalidZipWidget" />
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
|
|
@ -15,12 +21,13 @@ fmg
|
|||
|
||||
<script>
|
||||
// Components
|
||||
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question";
|
||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||
import { Form } from "vee-validate";
|
||||
|
||||
// Supporting files
|
||||
//Supporting Files
|
||||
import { Form } from "vee-validate";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
|
||||
|
|
@ -57,6 +64,7 @@ export default {
|
|||
forwardButtonAction() {},
|
||||
},
|
||||
components: {
|
||||
serviceZipModalQuestion,
|
||||
funnelHeader,
|
||||
funnelFooter,
|
||||
funnelSubHeader,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
describe("service-zip-modal-question.vue", () => {
|
||||
test.todo("test this");
|
||||
});
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
<template>
|
||||
<div class="text-center">
|
||||
<label
|
||||
:for="serviceZipCodeInput"
|
||||
:aria-label="questionText"
|
||||
class="form-label fw-bold w-100 ps-4 pe-4 pt-4"
|
||||
:class="[questionAlignment === 'center' ? 'text-center w-100 mb-5' : '']"
|
||||
v-html="questionText"></label>
|
||||
<div class="update-zip-text-link">
|
||||
<textLink
|
||||
linkType="text"
|
||||
:text="this.serviceZipDisplayText"
|
||||
href="#!"
|
||||
data-bs-toggle="modal"
|
||||
:data-bs-target="getModalId"
|
||||
aria-label="Modal window" />
|
||||
</div>
|
||||
</div>
|
||||
<modal
|
||||
ref="zipCodeInputModal"
|
||||
:cmsWidgetName="this.modalWidgetName"
|
||||
:onShownCallback="onModalOpen"
|
||||
:footerButtonCallback="setZip">
|
||||
<div class="ps-4 pe-4 pb-4">
|
||||
<textboxQuestion
|
||||
ref="zipInputTextQuestion"
|
||||
:cmsWidgetName="this.textboxQuestionWidgetName"
|
||||
v-model="serviceZipCodeInput"
|
||||
inputId="serviceZipCodeInput"
|
||||
questionAlignment="center"
|
||||
mask="#####"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
validationRules="zip-required|zip-format" />
|
||||
<alert
|
||||
ref="alertInvalidZip"
|
||||
v-if="displayInvalidZipAlert"
|
||||
class="my-4"
|
||||
:cmsWidgetName="this.alertInvalidZipWidgetName"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false" />
|
||||
<alert
|
||||
ref="alertNonServiceableZip"
|
||||
v-if="displayNonServiceableZipAlert"
|
||||
class="my-4"
|
||||
:cmsWidgetName="this.alertNonServiceableZipWidgetName"
|
||||
:manualHeadline="AlertNonServiceableZipHeader"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false" />
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import textLink from "@/ux-components/text-link/text-link";
|
||||
import modal from "@/digital-components/modal/modal";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
||||
|
||||
//Supporting Files
|
||||
import { defineRule } from "vee-validate";
|
||||
import { required, regex } from "@/helpers/validation-rules";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { isNoUnitNumericStyleProp } from "@vue/shared";
|
||||
|
||||
// Define Validation Rules
|
||||
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
|
||||
|
||||
export default {
|
||||
name: "service-zip-modal-question",
|
||||
data() {
|
||||
return {
|
||||
serviceZip: this.getZipFromStore(),
|
||||
serviceZipState: this.getZipStateFromStore(),
|
||||
serviceZipCodeInput: this.getZipFromStore(),
|
||||
displayInvalidZipAlert: false,
|
||||
displayNonServiceableZipAlert: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
modalWidgetName: String,
|
||||
textboxQuestionWidgetName: String,
|
||||
alertNonServiceableZipWidgetName: String,
|
||||
alertInvalidZipWidgetName: String,
|
||||
},
|
||||
methods: {
|
||||
getZipFromStore() {
|
||||
return this.$store.getters.order.serviceLocation.zipCode;
|
||||
},
|
||||
|
||||
getZipStateFromStore() {
|
||||
return this.$store.getters.order.serviceLocation.state;
|
||||
},
|
||||
|
||||
resetAlerts() {
|
||||
this.displayInvalidZipAlert = false;
|
||||
this.displayNonServiceableZipAlert = false;
|
||||
},
|
||||
|
||||
resetsOnZipInput() {
|
||||
this.resetAlerts();
|
||||
this.$refs.zipCodeInputModal.resetButtonStyle();
|
||||
},
|
||||
|
||||
focusOnZipInput() {
|
||||
this.$nextTick(() => {
|
||||
const input = this.$refs.zipInputTextQuestion.$refs.serviceZipCodeInput;
|
||||
input.focus();
|
||||
});
|
||||
},
|
||||
|
||||
onModalOpen() {
|
||||
this.serviceZipCodeInput = this.serviceZip;
|
||||
this.resetsOnZipInput();
|
||||
this.focusOnZipInput();
|
||||
},
|
||||
|
||||
async setZip() {
|
||||
this.resetAlerts();
|
||||
|
||||
const zipLength = 5;
|
||||
if (!this.serviceZipCodeInput || this.serviceZipCodeInput.length < zipLength) {
|
||||
// prevent reading 1111 as 01111
|
||||
return false;
|
||||
}
|
||||
|
||||
const zipCodeData = await this.getZipCodeData(this.serviceZipCodeInput);
|
||||
|
||||
if (!zipCodeData.isValid) {
|
||||
this.displayInvalidZipAlert = true;
|
||||
} else if (!zipCodeData.isServiceable) {
|
||||
this.displayNonServiceableZipAlert = true;
|
||||
} else {
|
||||
this.serviceZip = this.serviceZipCodeInput;
|
||||
this.serviceZipState = zipCodeData.state;
|
||||
|
||||
// close modal
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
getModalId() {
|
||||
return "#" + this.modalWidgetName;
|
||||
},
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
|
||||
},
|
||||
serviceZipDisplayText() {
|
||||
if (this.serviceZip && this.serviceZip != 0) {
|
||||
return this.serviceZipState + ", " + this.serviceZip;
|
||||
}
|
||||
return this.getCmsContent(this.cmsWidgetName, "FooterText");
|
||||
},
|
||||
AlertNonServiceableZipHeader() {
|
||||
const zipCode = this.serviceZipCodeInput;
|
||||
const text = this.getCmsContent(
|
||||
"AlertNonServiceableZipWidget",
|
||||
"HeadlineText"
|
||||
).replaceAll("{custom:serviceZipCodeInput}", zipCode);
|
||||
return text;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$watch(
|
||||
() => {
|
||||
return this.$refs.zipInputTextQuestion.value;
|
||||
},
|
||||
(val) => {
|
||||
this.resetsOnZipInput();
|
||||
}
|
||||
);
|
||||
},
|
||||
components: {
|
||||
textLink,
|
||||
modal,
|
||||
alert,
|
||||
textboxQuestion,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.update-zip-text-link::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 13px;
|
||||
height: 16px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 13 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.49635 1.00142e-07C5.64734 -0.000153295 4.80722 0.175918 4.0274 0.517444C3.24757 0.858969 2.54443 1.35877 1.96099 1.98626C0.765713 3.27588 0.0999756 4.98141 0.0999756 6.75394C0.0999756 8.52646 0.765713 10.232 1.96099 11.5216L5.98324 15.777C6.04954 15.8475 6.12918 15.9036 6.21736 15.9419C6.30555 15.9802 6.40045 16 6.49635 16C6.59225 16 6.68716 15.9802 6.77534 15.9419C6.86353 15.9036 6.94317 15.8475 7.00946 15.777L11.0317 11.52C12.2391 10.2383 12.909 8.52914 12.8999 6.75394C12.9094 4.97818 12.2394 3.26832 11.0317 1.98626C10.4481 1.35899 9.74493 0.859347 8.96514 0.517839C8.18535 0.176331 7.34532 0.000130509 6.49635 1.00142e-07V1.00142e-07ZM6.49635 9.13131C6.02507 9.13131 5.56437 8.98913 5.17251 8.72275C4.78065 8.45637 4.47524 8.07776 4.29488 7.63479C4.11453 7.19181 4.06734 6.70438 4.15928 6.23412C4.25123 5.76387 4.47817 5.33191 4.81142 4.99287C5.14467 4.65384 5.56925 4.42295 6.03148 4.32941C6.49371 4.23587 6.97282 4.28388 7.40823 4.46736C7.84364 4.65085 8.21579 4.96157 8.47762 5.36023C8.73945 5.7589 8.87921 6.2276 8.87921 6.70707C8.87921 7.34974 8.62837 7.96611 8.18185 8.4207C7.73532 8.87528 7.12964 9.13088 6.49794 9.13131H6.49635Z' fill='%231574A1'/%3E%3C/svg%3E%0A");
|
||||
background-size: contain;
|
||||
vertical-align: middle;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in a new issue