Merge branch 'feature/CSR-1088' into feature/CSR-1012
This commit is contained in:
commit
7d87ff3240
5 changed files with 355 additions and 20 deletions
|
|
@ -59,6 +59,80 @@ describe("address-questions.vue", () => {
|
|||
expect(zipCode.exists()).toBe(true);
|
||||
});
|
||||
|
||||
test("Should render apartmentNumberOrBusinessName textbox-question when captureApartmentNumberOrBusinessName = true", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({
|
||||
props: {
|
||||
modelValue: {
|
||||
streetAddress: "",
|
||||
apartmentNumberOrBusinessName: "",
|
||||
city: "",
|
||||
state: "",
|
||||
zipCode: "",
|
||||
},
|
||||
captureApartmentNumberOrBusinessName: true,
|
||||
},
|
||||
});
|
||||
|
||||
await wrapper.setData({
|
||||
showAddressFields: true,
|
||||
});
|
||||
|
||||
// Act
|
||||
const streetAddress = wrapper.findComponent({ ref: "autocomplete" });
|
||||
const apartmentNumberOrBusinessName = wrapper.findComponent({
|
||||
ref: "apartmentNumberOrBusinessName",
|
||||
});
|
||||
const city = wrapper.findComponent({ ref: "city" });
|
||||
const state = wrapper.findComponent({ ref: "state" });
|
||||
const zipCode = wrapper.findComponent({ ref: "zipCode" });
|
||||
|
||||
// Assert
|
||||
expect(streetAddress.exists()).toBe(true);
|
||||
expect(apartmentNumberOrBusinessName.exists()).toBe(true);
|
||||
expect(apartmentNumberOrBusinessName.isVisible()).toBe(true);
|
||||
expect(city.exists()).toBe(true);
|
||||
expect(state.exists()).toBe(true);
|
||||
expect(zipCode.exists()).toBe(true);
|
||||
});
|
||||
|
||||
test("Should *not* render apartmentNumberOrBusinessName textbox-question when captureApartmentNumberOrBusinessName = false", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({
|
||||
props: {
|
||||
modelValue: {
|
||||
streetAddress: "",
|
||||
apartmentNumberOrBusinessName: "",
|
||||
city: "",
|
||||
state: "",
|
||||
zipCode: "",
|
||||
},
|
||||
captureApartmentNumberOrBusinessName: false,
|
||||
},
|
||||
});
|
||||
|
||||
await wrapper.setData({
|
||||
showAddressFields: true,
|
||||
});
|
||||
|
||||
// Act
|
||||
const streetAddress = wrapper.findComponent({ ref: "autocomplete" });
|
||||
const apartmentNumberOrBusinessName = wrapper.findComponent({
|
||||
ref: "apartmentNumberOrBusinessName",
|
||||
});
|
||||
const city = wrapper.findComponent({ ref: "city" });
|
||||
const state = wrapper.findComponent({ ref: "state" });
|
||||
const zipCode = wrapper.findComponent({ ref: "zipCode" });
|
||||
|
||||
// Assert
|
||||
expect(streetAddress.exists()).toBe(true);
|
||||
expect(apartmentNumberOrBusinessName.exists()).toBe(true);
|
||||
expect(apartmentNumberOrBusinessName.isVisible()).toBe(false);
|
||||
expect(city.exists()).toBe(true);
|
||||
expect(state.exists()).toBe(true);
|
||||
expect(zipCode.exists()).toBe(true);
|
||||
});
|
||||
|
||||
test("Should set this.showAddressFields to true when the model is prepopulated", async () => {
|
||||
// Arrange
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -16,6 +16,21 @@
|
|||
@keydown.enter.prevent />
|
||||
</div>
|
||||
</div>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div
|
||||
class="row mb-4"
|
||||
v-show="showAddressFields && showApartmentNumberOrBusinessNameField"
|
||||
aria-live="polite">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="ApartmentNumberOrBusinessNameQuestionWidget"
|
||||
v-model="addressModel.apartmentNumberOrBusinessName"
|
||||
ref="apartmentNumberOrBusinessName"
|
||||
inputId="639b0aaa35f64609ad6995f86a74322b"
|
||||
disableAutoFill />
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="row mb-4" v-show="showAddressFields" aria-live="polite">
|
||||
<div class="col">
|
||||
|
|
@ -78,7 +93,6 @@ import { applicationConfig } from "@/constants/application-config.js";
|
|||
import { defineRule } from "vee-validate";
|
||||
import { required, regex } from "@/helpers/validation-rules";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { fill } from "lodash";
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule("street-address-required", required(errorMessages.STREET_ADDRESS_REQUIRED));
|
||||
|
|
@ -95,12 +109,17 @@ export default {
|
|||
type: Object,
|
||||
default: () => ({
|
||||
streetAddress: "",
|
||||
apartmentNumberOrBusinessName: "",
|
||||
city: "",
|
||||
state: "",
|
||||
zipCode: "",
|
||||
}),
|
||||
},
|
||||
validationRules: String,
|
||||
captureApartmentNumberOrBusinessName: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -180,6 +199,11 @@ export default {
|
|||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
},
|
||||
showApartmentNumberOrBusinessNameField: {
|
||||
get: function () {
|
||||
return this.captureApartmentNumberOrBusinessName;
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setupAddressLookup() {
|
||||
|
|
@ -233,13 +257,17 @@ export default {
|
|||
});
|
||||
|
||||
addressField1.addEventListener("keydown", (e) => {
|
||||
if (e.code === "Enter" || e.code === "NumpadEnter") {
|
||||
const autocomplete = document.getElementById("autocomplete");
|
||||
const event = new Event("place_changed");
|
||||
|
||||
if (e.code === "Enter" || e.code === "NumpadEnter" || e.code === "Tab") {
|
||||
const selectedItem = document.querySelector(
|
||||
".pac-container .pac-item-selected"
|
||||
);
|
||||
if (selectedItem !== null) {
|
||||
// Fill-in the address using selected item in the list.
|
||||
fillInAddress(selectedItem);
|
||||
autocomplete.dispatchEvent(event);
|
||||
//fillInAddress(selectedItem.textContent);
|
||||
} else {
|
||||
// Fill-in the address using first item in the list.
|
||||
fillInAddressUsingFirstItem();
|
||||
|
|
@ -249,23 +277,25 @@ export default {
|
|||
}
|
||||
});
|
||||
|
||||
addressField1.addEventListener("change", () => {
|
||||
// If a match has been previously attempted then do nothing
|
||||
if (self.matchFound !== null) {
|
||||
return;
|
||||
}
|
||||
// addressField1.addEventListener("change", () => {
|
||||
// // If a match has been previously attempted then do nothing
|
||||
// if (self.matchFound !== null) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Get the address that the user clicked on (if any)
|
||||
const clickedAddress = document.querySelector(
|
||||
".pac-container .pac-item:hover"
|
||||
);
|
||||
// // Get the address that the user clicked on (if any)
|
||||
// const clickedAddress = document.querySelector(
|
||||
// ".pac-container .pac-item:hover"
|
||||
// );
|
||||
|
||||
// If the Street Address field changed without clicking (i.e. by pressing Tab, or clicking outside the field)
|
||||
if (clickedAddress === null) {
|
||||
// Fill-in the address using first item in the list.
|
||||
fillInAddressUsingFirstItem();
|
||||
}
|
||||
});
|
||||
// // If the Street Address field changed without clicking (i.e. by pressing Tab, or clicking outside the field)
|
||||
// if (clickedAddress === null) {
|
||||
// // Fill-in the address using first item in the list.
|
||||
// fillInAddressUsingFirstItem();
|
||||
// }
|
||||
|
||||
// console.log("change");
|
||||
// });
|
||||
|
||||
function fillInAddressUsingFirstItem() {
|
||||
// Fill-in the address using first item in the list.
|
||||
|
|
@ -290,6 +320,7 @@ export default {
|
|||
}
|
||||
|
||||
function fillInAddress(place) {
|
||||
console.log("fillInAddress");
|
||||
if (!place) {
|
||||
place = autocomplete.getPlace();
|
||||
}
|
||||
|
|
@ -297,8 +328,11 @@ export default {
|
|||
if (place && place.address_components) {
|
||||
self.matchFound = true;
|
||||
|
||||
self.addressModel.streetAddress = "";
|
||||
self.$nextTick(function () {
|
||||
//self.addressModel.streetAddress = "";
|
||||
|
||||
//self.$nextTick();
|
||||
|
||||
self.showAddressFields = true;
|
||||
|
||||
for (const component of place.address_components) {
|
||||
|
|
@ -382,6 +416,11 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
"addressModel.streetAddress": {
|
||||
handler(newValue, oldValue) {
|
||||
console.log(`I got changed from ${oldValue} to ${newValue}`);
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
textboxQuestion,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,152 @@
|
|||
<template>
|
||||
<div class="text-center">
|
||||
<label
|
||||
:for="displayModalLink"
|
||||
: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-mobile-location-text-link">
|
||||
<textLink
|
||||
id="displayModalLink"
|
||||
linkType="text"
|
||||
:text="this.mobileLocationDisplayText"
|
||||
href="#!"
|
||||
@click-event="openModal"
|
||||
:data-bs-target="getModalId"
|
||||
aria-label="Modal window" />
|
||||
</div>
|
||||
</div>
|
||||
<modal
|
||||
ref="mobileServiceModal"
|
||||
:cmsWidgetName="this.modalWidgetName"
|
||||
:onModalOpenedCallback="onModalOpened"
|
||||
:footerButtonCallback="saveMobileLocationData">
|
||||
<div class="modal-body ps-5 pe-5 pt-5 pb-4">
|
||||
<addressQuestions
|
||||
ref="addressQuestions"
|
||||
v-model="mobileQuestionModel.addressQuestions"
|
||||
captureApartmentNumberOrBusinessName="true" />
|
||||
<vehicleProtectedQuestion v-model="mobileQuestionModel.selectedValue"/>
|
||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import textLink from "@/ux-components/text-link/text-link";
|
||||
import modal from "@/digital-components/modal/modal";
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
||||
import addressQuestions from "@/layouts/address-lookup/customer-questions/address-questions/address-questions";
|
||||
import vehicleProtectedQuestion from "@/layouts/service-location/mobile-location-modal-questions/vehicle-protected-question/vehicle-protected-question";
|
||||
import textBlock from "@/digital-components/text-block/text-block";
|
||||
|
||||
// Supporting Files
|
||||
import { defineRule } from "vee-validate";
|
||||
import { required, regex } from "@/helpers/validation-rules";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import TextBlock from '../../../digital-components/text-block/text-block.vue';
|
||||
|
||||
// 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: "mobile-location-modal-questions",
|
||||
emits: ["update:modelValue"], // The component emits an event
|
||||
data() {
|
||||
return {
|
||||
isVehicleProtectedAnswers: [],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
addressQuestions: {
|
||||
streetAddress: "",
|
||||
apartmentNumberOrBusinessName: "",
|
||||
city: "",
|
||||
state: "",
|
||||
zipCode: "",
|
||||
},
|
||||
isZipServiceableMobile: Boolean,
|
||||
isZipServiceableInShop: Boolean,
|
||||
isVehicleProtected: Boolean,
|
||||
}),
|
||||
},
|
||||
cmsWidgetName: String,
|
||||
modalWidgetName: String,
|
||||
textboxQuestionWidgetName: String,
|
||||
alertNonServiceableZipWidgetName: String,
|
||||
alertInvalidZipWidgetName: String,
|
||||
},
|
||||
methods: {
|
||||
loadInitialData() {
|
||||
return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_YEARS, {});
|
||||
},
|
||||
initializeComponent(initialData) {
|
||||
this.isVehicleProtectedAnswers = initialData;
|
||||
},
|
||||
openModal() {
|
||||
this.$refs.mobileServiceModal.openModal();
|
||||
},
|
||||
closeModal() {
|
||||
this.$refs.mobileServiceModal.closeModal();
|
||||
},
|
||||
focusOnZipInput() {
|
||||
this.$nextTick(() => {
|
||||
console.log(this.$refs);
|
||||
const input = this.$refs.streetAddressField;
|
||||
input.focus();
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
getModalId() {
|
||||
return "#" + this.modalWidgetName;
|
||||
},
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
|
||||
},
|
||||
mobileLocationDisplayText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "FooterText");
|
||||
},
|
||||
mobileQuestionModel: {
|
||||
get: function () {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {},
|
||||
components: {
|
||||
textLink,
|
||||
modal,
|
||||
addressQuestions,
|
||||
vehicleProtectedQuestion,
|
||||
textBlock
|
||||
},
|
||||
};
|
||||
</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>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<template>
|
||||
<buttonQuestion
|
||||
class="radioQuestion"
|
||||
:questionText="questionText"
|
||||
:answers="answers"
|
||||
groupName="isVehicleProtected"
|
||||
textPosition="text-center"
|
||||
v-model="selectedValue"
|
||||
isRequired />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||
// Supporting files
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
export default {
|
||||
name: "vehicle-protected-question",
|
||||
data() {
|
||||
return {
|
||||
answers: [ "Yes", "No" ],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
modelValue: String,
|
||||
cmsWidgetName: String,
|
||||
},
|
||||
components: {
|
||||
buttonQuestion,
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
|
||||
},
|
||||
selectedValue: {
|
||||
get: function () {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
loadInitialData() {
|
||||
return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_YEARS, {});
|
||||
},
|
||||
initializeComponent(initialData) {
|
||||
this.years = initialData;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -9,6 +9,11 @@ fmg
|
|||
textboxQuestionWidgetName="ServiceZipQuestionWidget"
|
||||
alertNonServiceableZipWidgetName="AlertNonServiceableZipWidget"
|
||||
alertInvalidZipWidgetName="AlertInvalidZipWidget" />
|
||||
<mobileLocationModalQuestions
|
||||
v-model="mobileLocationQuestion"
|
||||
cmsWidgetName="MobileLocationModalWidget"
|
||||
modalWidgetName="LocationModalWidget"
|
||||
textboxQuestionWidgetName="MobileLocationQuestionWidget" />
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
|
|
@ -21,6 +26,7 @@ fmg
|
|||
<script>
|
||||
// Components
|
||||
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question";
|
||||
import mobileLocationModalQuestions from "@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions";
|
||||
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";
|
||||
|
|
@ -33,7 +39,17 @@ import { settleAllPromises } from "@/helpers/layout-helper";
|
|||
export default {
|
||||
name: "service-location",
|
||||
data() {
|
||||
return {};
|
||||
return {
|
||||
mobileLocationQuestion: {
|
||||
addressQuestions: {
|
||||
streetAddress: "",
|
||||
apartmentNumberOrBusinessName: "",
|
||||
city: "",
|
||||
state: "",
|
||||
zipCode: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
|
@ -64,6 +80,7 @@ export default {
|
|||
},
|
||||
components: {
|
||||
serviceZipModalQuestion,
|
||||
mobileLocationModalQuestions,
|
||||
funnelHeader,
|
||||
funnelFooter,
|
||||
funnelSubHeader,
|
||||
|
|
|
|||
Loading…
Reference in a new issue