Integrated mobile location questions as a field in the page level validation
This commit is contained in:
parent
504d3d1c97
commit
2e13b84a62
3 changed files with 80 additions and 23 deletions
|
|
@ -44,6 +44,7 @@
|
|||
import modalButtonMain from "@/digital-components/modal/ux-components/modal-button-main/modal-button-main";
|
||||
import { Modal } from "bootstrap";
|
||||
import { useForm } from "vee-validate";
|
||||
import { computed, provide, inject, ref } from "vue";
|
||||
|
||||
export default {
|
||||
name: "modal",
|
||||
|
|
@ -59,7 +60,6 @@ export default {
|
|||
},
|
||||
setup() {
|
||||
const modalId = `modal-${crypto.randomUUID()}`;
|
||||
|
||||
const { meta, validate, resetForm } = useForm();
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="mobile-location-questions">
|
||||
<div class="text-center">
|
||||
<div class="text-center" :id="componentId">
|
||||
<label
|
||||
for="mobileLocationLinkPromptId"
|
||||
:aria-label="mobileLocationLinkPromptText"
|
||||
|
|
@ -21,6 +21,11 @@
|
|||
:customText="mobileFeeText"
|
||||
cmsWidgetName="MobileFeeDisclaimerWidget"
|
||||
typeStyle="caption" />
|
||||
<div v-show="errorMessage" class="row my-1 form-test-error">
|
||||
<span class="d-inline-flex small mt-0 center-error-message" role="alert">
|
||||
{{ errorMessage }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<modal
|
||||
:ref="modalName"
|
||||
|
|
@ -61,12 +66,29 @@ import vehicleProtectedQuestion from "@/layouts/service-location/mobile-location
|
|||
|
||||
// Helpers
|
||||
import { deepClone } from "@/layouts/service-location/helpers/object-cloning-helper/object-cloning-helper";
|
||||
|
||||
import {
|
||||
getPricedMobileFeePart,
|
||||
getServiceabilityDetails,
|
||||
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||
|
||||
// Validation
|
||||
import { useField } from "vee-validate";
|
||||
import { defineRule } from "vee-validate";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
|
||||
defineRule("mobile-location-required", (value) => {
|
||||
if (
|
||||
value.addressQuestions.streetAddress == "" ||
|
||||
value.addressQuestions.city == "" ||
|
||||
value.addressQuestions.state == "" ||
|
||||
value.addressQuestions.zipCode == "" ||
|
||||
value.isVehicleProtected == null
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
export default {
|
||||
name: "mobile-location-modal-questions",
|
||||
emits: ["update:modelValue", "updated-mobile-fee-part", "updated-contains-military-base"],
|
||||
|
|
@ -76,6 +98,35 @@ export default {
|
|||
displayInvalidZipAlert: false,
|
||||
};
|
||||
},
|
||||
setup(props) {
|
||||
const componentId = !props.customComponentId
|
||||
? `component-${crypto.randomUUID()}`
|
||||
: props.customComponentId;
|
||||
|
||||
// Integrate this component as a single field with an object for it's value into the page level validation
|
||||
const modelValue = deepClone(props).modelValue;
|
||||
const initialValue = modelValue;
|
||||
|
||||
const fieldOptions = {
|
||||
value: modelValue,
|
||||
initialValue: initialValue,
|
||||
};
|
||||
|
||||
const { errorMessage, handleChange, meta, validate, errors } = useField(
|
||||
componentId,
|
||||
props.validationRules,
|
||||
fieldOptions
|
||||
);
|
||||
|
||||
return {
|
||||
componentId,
|
||||
errorMessage,
|
||||
handleChange,
|
||||
validate,
|
||||
meta,
|
||||
errors,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
|
|
@ -98,6 +149,8 @@ export default {
|
|||
modalWidgetName: String,
|
||||
alertNonServiceableZipWidgetName: String,
|
||||
alertInvalidZipWidgetName: String,
|
||||
customComponentId: String,
|
||||
validationRules: String,
|
||||
},
|
||||
computed: {
|
||||
mobileLocationLinkPromptText() {
|
||||
|
|
@ -161,7 +214,7 @@ export default {
|
|||
},
|
||||
onModalClosed() {
|
||||
this.internalModel = deepClone(this.modelValue);
|
||||
this.resetAlerts();
|
||||
this.resetValidation();
|
||||
},
|
||||
resetComponent(updatedServiceZipCodeInfo) {
|
||||
// Reset the validation form, setting the initial values
|
||||
|
|
@ -180,8 +233,18 @@ export default {
|
|||
resetModalButtonStyle() {
|
||||
this.$refs[this.modalName].resetButtonStyle();
|
||||
},
|
||||
resetAlerts() {
|
||||
resetValidation() {
|
||||
this.$refs.addressQuestions.resetAlerts();
|
||||
|
||||
this.$refs[this.modalName].resetForm({
|
||||
values: {
|
||||
autocomplete: this.internalModel.addressQuestions.streetAddress,
|
||||
city: this.internalModel.addressQuestions.city,
|
||||
state: this.internalModel.addressQuestions.state,
|
||||
zipCode: this.internalModel.addressQuestions.zipCode,
|
||||
isVehicleProtected: this.internalModel.isVehicleProtected,
|
||||
},
|
||||
});
|
||||
},
|
||||
async setMobileLocation() {
|
||||
// Validate the Zip Code
|
||||
|
|
@ -217,6 +280,8 @@ export default {
|
|||
handler(newValue) {
|
||||
this.internalModel = deepClone(newValue);
|
||||
|
||||
this.handleChange(newValue);
|
||||
|
||||
this.resetComponent({
|
||||
streetAddress: newValue.addressQuestions.streetAddress,
|
||||
city: newValue.addressQuestions.city,
|
||||
|
|
@ -240,6 +305,12 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.mobile-location-questions {
|
||||
.center-error-message {
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
.update-zip-text-link::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
|
|
|
|||
|
|
@ -40,22 +40,17 @@
|
|||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||
validationRules="option-required" />
|
||||
<mobileLocationModalQuestions
|
||||
v-show="selectedAppointmentType === 'Mobile'"
|
||||
customComponentId="mobileLocationQuestions"
|
||||
v-if="selectedAppointmentType === 'Mobile'"
|
||||
v-model="mobileLocationQuestions"
|
||||
:mobileFeePart="mobileFeePart"
|
||||
@updated-mobile-fee-part="setMobileFeePart"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
@updated-contains-military-base="setContainsMilitaryBase"
|
||||
validationRules="mobile-location-required"
|
||||
ref="mobileLocationModalQuestions"
|
||||
linkWidgetName="MobileLocationLinkWidget"
|
||||
modalWidgetName="MobileLocationModalWidget" />
|
||||
<textboxQuestion
|
||||
v-show="selectedAppointmentType === 'Mobile'"
|
||||
ref="mobileLocationQuestionsError"
|
||||
v-model="mobileLocationValidationField"
|
||||
validationRules="mobile-location-required"
|
||||
hideInput
|
||||
centerErrorMessage />
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
ref="funnelFooter"
|
||||
|
|
@ -76,8 +71,7 @@ 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 loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
||||
import { Form } from "vee-validate";
|
||||
|
||||
// Supporting files
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
|
|
@ -90,10 +84,6 @@ import {
|
|||
getServiceabilityDetails,
|
||||
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||
import store from "@/store";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
|
||||
defineRule("mobile-location-required", required(errorMessages.MOBILE_LOCATION_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: "service-location",
|
||||
|
|
@ -112,7 +102,6 @@ export default {
|
|||
mobileFeePart: null,
|
||||
zipContainsMilitaryBase: false,
|
||||
selectedAppointmentType: null,
|
||||
mobileLocationValidationField: null,
|
||||
};
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -198,8 +187,6 @@ export default {
|
|||
this.zipCode = newValue.addressQuestions.zipCode;
|
||||
this.isVehicleProtected = newValue.isVehicleProtected;
|
||||
|
||||
this.mobileLocationValidationField = "isValid";
|
||||
|
||||
if (
|
||||
newValue.zipCode !== this.zipCode &&
|
||||
!this.selectedAppointmentType == "Mobile"
|
||||
|
|
@ -305,7 +292,6 @@ export default {
|
|||
funnelSubHeader,
|
||||
Form,
|
||||
loadingModal,
|
||||
textboxQuestion,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue