From 8746851f79e5eb1dbea1de2050818dd6f776f4a4 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Wed, 14 Jun 2023 14:51:22 -0400 Subject: [PATCH 1/7] WIP --- .../address-questions/address-questions.vue | 298 ++++++++---------- src/store/index.js | 15 +- 2 files changed, 146 insertions(+), 167 deletions(-) diff --git a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue index 9842d42c3..148baca8f 100644 --- a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue +++ b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue @@ -122,13 +122,16 @@ export default { }, data() { return { - showAddressFields: false, displayVerificationWarning: false, displayNoMatchWarning: false, alertHeadlineVerificationWarning: "", alertCopyVerificationWarning: "", alertHeadlineNoMatchWarning: "", alertCopyNoMatchWarning: "", + scriptLoaded: null, + addressField1: null, + autocomplete: null, + autocompleteListener: null, matchFound: null, // null = no attempted match, true = match was found, false = match was not found }; }, @@ -198,6 +201,14 @@ export default { this.$emit("update:modelValue", newValue); }, }, + showAddressFields: { + get: function() { + return this.addressModel.streetAddress && + this.addressModel.city && + this.addressModel.state && + this.addressModel.zipCode + } + }, showApartmentNumberOrBusinessNameField: { get: function () { return this.captureApartmentNumberOrBusinessName; @@ -205,182 +216,148 @@ export default { }, }, methods: { - setupAddressLookup() { - this.showAddressFields = false; - if ( - this.addressModel.streetAddress && - this.addressModel.city && - this.addressModel.state && - this.addressModel.zipCode - ) { - this.showAddressFields = true; - return; + initializeAutocomplete() { + this.addressField1 = document.getElementById("autocomplete"); + + this.autocomplete = new window.google.maps.places.Autocomplete(this.addressField1, { + componentRestrictions: { country: ["us"] }, + fields: ["address_components"], + types: ["geocode"], + }); + + // Standard place_changed event handling + this.autocompleteListener = window.google.maps.event.addListener( + this.autocomplete, + "place_changed", + this.fillInAddress + ); + + this.addressField1.addEventListener("focus", (e) => { + this.addressField1.setAttribute("autocomplete", "do-not-autofill"); + }); + + this.addressField1.addEventListener("keydown", (e) => { + 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. + this.autocomplete.dispatchEvent(event); + } else { + // Fill-in the address using first item in the list. + this.fillInAddressUsingFirstItem(); + } + } else { + return; + } + }); + }, + fillInAddress(place) { + if (!place) { + place = this.autocomplete.getPlace(); } - const addressField1 = document.getElementById("autocomplete"); - const self = this; + if (place && place.address_components) { + this.matchFound = true; - const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY; + const self = this; + this.$nextTick(function () { + self.showAddressFields = true; - this.$loadScript( - `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places&callback=Function.prototype` - ) - .then(() => { - // Script is loaded, initialize the autocomplete textbox - const autocomplete = new window.google.maps.places.Autocomplete(addressField1, { - componentRestrictions: { country: ["us"] }, - fields: ["address_components"], - types: ["geocode"], - }); + for (const component of place.address_components) { + const componentType = component.types[0]; - // Standard place_changed event handling - const autocompleteListener = window.google.maps.event.addListener( - autocomplete, - "place_changed", - fillInAddress - ); - - addressField1.addEventListener("focus", () => { - // Wrapping the addressField1 element in the Google Address Autocomplete object - // will cause "autocomplete='off'" which Chrome completely ignores. This event - // handler will set the value to something arbitrary so autofill doesn't work. - // https://stackoverflow.com/a/30976223 - addressField1.setAttribute("autocomplete", "do-not-autofill"); - - // Make place results box stick to the input on scroll - const streetAddressField = document.getElementById("streetAddressField"); - const autocompleteResultsContainer = - document.getElementsByClassName("pac-container")[0]; - if (autocompleteResultsContainer) { - streetAddressField.appendChild(autocompleteResultsContainer); - } - }); - - addressField1.addEventListener("keydown", (e) => { - 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. - autocomplete.dispatchEvent(event); - //fillInAddress(selectedItem.textContent); - } else { - // Fill-in the address using first item in the list. - fillInAddressUsingFirstItem(); + switch (componentType) { + case "street_number": { + self.addressModel.streetAddress = component.long_name; + break; + } + case "route": { + self.addressModel.streetAddress += + " " + component.short_name; + break; + } + case "locality": { + self.addressModel.city = component.long_name; + break; + } + case "administrative_area_level_1": { + self.addressModel.state = component.short_name; + break; + } + case "postal_code": { + self.addressModel.zipCode = component.long_name; + break; } - } else { - 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" - ); - - // 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(); - } - }); - - function fillInAddressUsingFirstItem() { - // Fill-in the address using first item in the list. - const item = document.querySelector(".pac-container .pac-item"); - if (item != null) { - const firstResult = item.textContent; - const geocoder = new window.google.maps.Geocoder(); - geocoder.geocode( - { - address: firstResult, - }, - function (results, status) { - if (status === window.google.maps.GeocoderStatus.OK) { - fillInAddress(results[0]); - self.displayVerificationWarning = true; - } - } - ); - } else { - self.matchFound = false; } } - function fillInAddress(place) { - if (!place) { - place = autocomplete.getPlace(); - } - - if (place && place.address_components) { - self.matchFound = true; - - self.$nextTick(function () { - self.showAddressFields = true; - - for (const component of place.address_components) { - const componentType = component.types[0]; - - switch (componentType) { - case "street_number": { - self.addressModel.streetAddress = component.long_name; - break; - } - case "route": { - self.addressModel.streetAddress += - " " + component.short_name; - break; - } - case "locality": { - self.addressModel.city = component.long_name; - break; - } - case "administrative_area_level_1": { - self.addressModel.state = component.short_name; - break; - } - case "postal_code": { - self.addressModel.zipCode = component.long_name; - break; - } - } - } - - // after showing the address fields, disable the address autocomplete - window.google.maps.event.removeListener(autocompleteListener); - window.google.maps.event.clearInstanceListeners(autocomplete); - addressField1.onchange = null; - const pacContainer = document.querySelector(".pac-container"); - if (pacContainer) { - pacContainer.remove(); - } - }); - } + // after showing the address fields, disable the address autocomplete + window.google.maps.event.removeListener(this.autocompleteListener); + window.google.maps.event.clearInstanceListeners(this.autocomplete); + this.addressField1.onchange = null; + const pacContainer = document.querySelector(".pac-container"); + if (pacContainer) { + pacContainer.remove(); } - }) - .catch(() => { - // Failed to fetch script - console.log("Unable to load Google Places API script"); }); + } + }, + fillInAddressUsingFirstItem() { + // Fill-in the address using first item in the list. + const item = document.querySelector(".pac-container .pac-item"); + if (item != null) { + const firstResult = item.textContent; + const geocoder = new window.google.maps.Geocoder(); + const self = this; + geocoder.geocode( + { + address: firstResult, + }, + function (results, status) { + if (status === window.google.maps.GeocoderStatus.OK) { + self.fillInAddress(results[0]); + self.displayVerificationWarning = true; + } + } + ); + } else { + this.matchFound = false; + } }, resetAlerts() { this.displayVerificationWarning = false; }, }, mounted() { - this.setupAddressLookup(); + // Load the Google Places Autocomplete script + const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY; + this.$loadScript( + `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places&callback=Function.prototype` + ).then(() => { + // When loaded trigger the setup + this.scriptLoaded = true; + }); + }, + beforeUpdate() { + // Make place results box stick to the input on scroll + const streetAddressField = document.getElementById("streetAddressField"); + const autocompleteResultsContainer = + document.getElementsByClassName("pac-container")[0]; + if (autocompleteResultsContainer) { + streetAddressField.appendChild(autocompleteResultsContainer); + } }, watch: { + scriptLoaded: { + handler() { + // After script is loaded, initialize the autocomplete textbox + this.initializeAutocomplete(); + }, + }, matchFound: { handler(newValue) { if (newValue === null) { @@ -414,11 +391,6 @@ export default { } }, }, - modelValue: { - handler() { - this.setupAddressLookup(); - }, - }, }, components: { textboxQuestion, diff --git a/src/store/index.js b/src/store/index.js index bd8ccffe7..15233a1cf 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1105,10 +1105,17 @@ export const actions = { "glassPieces" ); - return globalMethods.callHttpClient({ - method: endpoints.GetServiceabilityDetails.method, - endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&${lineItems}&${glassPieces}`, - }); + return Promise.resolve({ + "isGlassServiceableInshop": true, + "isRecalibrationServiceableInshop": true, + "isGlassServiceableMobile": true, + "isRecalibrationServiceableMobile": true + }) + + // return globalMethods.callHttpClient({ + // method: endpoints.GetServiceabilityDetails.method, + // endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&${lineItems}&${glassPieces}`, + // }); }, getProviders(context, { serviceZipCode }) { From 1a6db3df0f51aaaca700d06ea8663c747f1dd2d1 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Thu, 15 Jun 2023 08:18:32 -0400 Subject: [PATCH 2/7] WIP --- src/digital-components/modal/modal.vue | 2 + .../address-questions/address-questions.vue | 49 ++++++++++---- .../mobile-location-modal-questions.vue | 64 +++++++++++-------- src/store/index.js | 15 ++--- 4 files changed, 79 insertions(+), 51 deletions(-) diff --git a/src/digital-components/modal/modal.vue b/src/digital-components/modal/modal.vue index e1f3fb462..bdec465e2 100644 --- a/src/digital-components/modal/modal.vue +++ b/src/digital-components/modal/modal.vue @@ -90,10 +90,12 @@ export default { openModal() { const modal = Modal.getOrCreateInstance(document.getElementById(this.modalId)); modal.show(); + this.$emit("modalOpened", true); }, closeModal() { const modal = Modal.getInstance(document.getElementById(this.modalId)); modal.hide(); + this.$emit("modalOpened", false); }, }, computed: { diff --git a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue index 148baca8f..0c2598b4e 100644 --- a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue +++ b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue @@ -122,6 +122,7 @@ export default { }, data() { return { + componentKey: 0, displayVerificationWarning: false, displayNoMatchWarning: false, alertHeadlineVerificationWarning: "", @@ -202,12 +203,14 @@ export default { }, }, showAddressFields: { - get: function() { - return this.addressModel.streetAddress && - this.addressModel.city && - this.addressModel.state && - this.addressModel.zipCode - } + get: function () { + return ( + this.addressModel.streetAddress && + this.addressModel.city && + this.addressModel.state && + this.addressModel.zipCode + ); + }, }, showApartmentNumberOrBusinessNameField: { get: function () { @@ -218,14 +221,15 @@ export default { methods: { initializeAutocomplete() { this.addressField1 = document.getElementById("autocomplete"); - + + // initialize the Google Places Autocomplete this.autocomplete = new window.google.maps.places.Autocomplete(this.addressField1, { componentRestrictions: { country: ["us"] }, fields: ["address_components"], types: ["geocode"], }); - // Standard place_changed event handling + // Set up the Autocomplete place_changed event to call our method to fill in the address this.autocompleteListener = window.google.maps.event.addListener( this.autocomplete, "place_changed", @@ -233,16 +237,30 @@ export default { ); this.addressField1.addEventListener("focus", (e) => { + // Unfortunately this is the only place we can set the autocomplete attribute without the + // Google Places object resetting it to "off" which does nothing to prevent browser autofill this.addressField1.setAttribute("autocomplete", "do-not-autofill"); + + // Make place results box stick to the input on scroll + // Due to the different ways we're using this component it is necessary to do this here instead of ahead of time + const streetAddressField = document.getElementById("streetAddressField"); + const autocompleteResultsContainer = document.getElementsByClassName("pac-container")[0]; + if (autocompleteResultsContainer) { + streetAddressField.appendChild(autocompleteResultsContainer); + } }); this.addressField1.addEventListener("keydown", (e) => { const event = new Event("place_changed"); + // When either of the two enter keys or the tab key are pressed if (e.code === "Enter" || e.code === "NumpadEnter" || e.code === "Tab") { + // Grab the selected item const selectedItem = document.querySelector( ".pac-container .pac-item-selected" ); + + // If an item was selected then fill in the address with the selected item if (selectedItem !== null) { // Fill-in the address using selected item in the list. this.autocomplete.dispatchEvent(event); @@ -276,8 +294,7 @@ export default { break; } case "route": { - self.addressModel.streetAddress += - " " + component.short_name; + self.addressModel.streetAddress += " " + component.short_name; break; } case "locality": { @@ -331,8 +348,12 @@ export default { resetAlerts() { this.displayVerificationWarning = false; }, + forceRerender() { + this.componentKey.value += 1; + } }, mounted() { + console.log("mounted") // Load the Google Places Autocomplete script const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY; this.$loadScript( @@ -342,11 +363,13 @@ export default { this.scriptLoaded = true; }); }, - beforeUpdate() { + unmounted() { + console.log("unmounted") + }, + beforeUpdate() { // Make place results box stick to the input on scroll const streetAddressField = document.getElementById("streetAddressField"); - const autocompleteResultsContainer = - document.getElementsByClassName("pac-container")[0]; + const autocompleteResultsContainer = document.getElementsByClassName("pac-container")[0]; if (autocompleteResultsContainer) { streetAddressField.appendChild(autocompleteResultsContainer); } diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue index 0052c1368..dd4780928 100644 --- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue +++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue @@ -33,24 +33,28 @@ :footerButtonText="modalFooterText" :onModalOpenedCallback="onModalOpened" :onModalClosedCallback="onModalClosed" + @modalOpened="setModalOpened" @footer-button-event="setMobileLocation"> - - - - + + @@ -82,6 +86,8 @@ export default { return { internalModel: deepClone(this.modelValue), displayInvalidZipAlert: false, + addressQuestionsKey: 0, + modalOpened: false, }; }, setup(props) { @@ -195,6 +201,10 @@ export default { openModal() { this.$refs[this.modalName].openModal(); }, + setModalOpened(isOpened) { + this.modalOpened = isOpened; + console.log(this.modalOpened) + }, closeModal() { this.$refs[this.modalName].closeModal(); }, @@ -224,17 +234,17 @@ export default { this.$refs[this.modalName].resetButtonStyle(); }, resetValidation() { - this.$refs.addressQuestions.resetAlerts(); + //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, - }, - }); + // 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() { if ( diff --git a/src/store/index.js b/src/store/index.js index 15233a1cf..bd8ccffe7 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1105,17 +1105,10 @@ export const actions = { "glassPieces" ); - return Promise.resolve({ - "isGlassServiceableInshop": true, - "isRecalibrationServiceableInshop": true, - "isGlassServiceableMobile": true, - "isRecalibrationServiceableMobile": true - }) - - // return globalMethods.callHttpClient({ - // method: endpoints.GetServiceabilityDetails.method, - // endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&${lineItems}&${glassPieces}`, - // }); + return globalMethods.callHttpClient({ + method: endpoints.GetServiceabilityDetails.method, + endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&${lineItems}&${glassPieces}`, + }); }, getProviders(context, { serviceZipCode }) { From dc309e1dae06d36ed9a05e1b354262560c8ca0b7 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Mon, 19 Jun 2023 09:03:05 -0400 Subject: [PATCH 3/7] Fix mobile location auto-complete defect and defect 1328 --- src/digital-components/modal/modal.vue | 4 +- .../address-questions/address-questions.vue | 128 ++++++++++-------- .../appointment-type-question.vue | 9 +- .../mobile-location-modal-questions.vue | 65 ++------- 4 files changed, 91 insertions(+), 115 deletions(-) diff --git a/src/digital-components/modal/modal.vue b/src/digital-components/modal/modal.vue index bdec465e2..0004be47e 100644 --- a/src/digital-components/modal/modal.vue +++ b/src/digital-components/modal/modal.vue @@ -90,12 +90,12 @@ export default { openModal() { const modal = Modal.getOrCreateInstance(document.getElementById(this.modalId)); modal.show(); - this.$emit("modalOpened", true); + this.$emit("isModalOpened", true); }, closeModal() { const modal = Modal.getInstance(document.getElementById(this.modalId)); modal.hide(); - this.$emit("modalOpened", false); + this.$emit("isModalOpened", false); }, }, computed: { diff --git a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue index 0c2598b4e..22ccd3776 100644 --- a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue +++ b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue @@ -122,17 +122,15 @@ export default { }, data() { return { - componentKey: 0, displayVerificationWarning: false, displayNoMatchWarning: false, alertHeadlineVerificationWarning: "", alertCopyVerificationWarning: "", alertHeadlineNoMatchWarning: "", alertCopyNoMatchWarning: "", - scriptLoaded: null, - addressField1: null, autocomplete: null, autocompleteListener: null, + showAddressFields: false, matchFound: null, // null = no attempted match, true = match was found, false = match was not found }; }, @@ -202,27 +200,30 @@ export default { this.$emit("update:modelValue", newValue); }, }, - showAddressFields: { - get: function () { - return ( - this.addressModel.streetAddress && - this.addressModel.city && - this.addressModel.state && - this.addressModel.zipCode - ); - }, - }, showApartmentNumberOrBusinessNameField: { get: function () { return this.captureApartmentNumberOrBusinessName; }, }, + addressField1: { + get: function () { + return document.getElementById("autocomplete"); + }, + }, }, methods: { + loadGooglePlacesAutocompleteScript() { + // Load the Google Places Autocomplete script + const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY; + this.$loadScript( + `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places&callback=Function.prototype` + ).then(() => { + // When loaded trigger the setup + this.initializeAutocomplete(); + }); + }, initializeAutocomplete() { - this.addressField1 = document.getElementById("autocomplete"); - - // initialize the Google Places Autocomplete + // Initialize the Google Places Autocomplete this.autocomplete = new window.google.maps.places.Autocomplete(this.addressField1, { componentRestrictions: { country: ["us"] }, fields: ["address_components"], @@ -236,18 +237,21 @@ export default { this.fillInAddress ); + // When the Street Address textbox receives focus, + // append the search results list container to the bottom of the textbox + // and disable browser autofill this.addressField1.addEventListener("focus", (e) => { - // Unfortunately this is the only place we can set the autocomplete attribute without the - // Google Places object resetting it to "off" which does nothing to prevent browser autofill - this.addressField1.setAttribute("autocomplete", "do-not-autofill"); - // Make place results box stick to the input on scroll - // Due to the different ways we're using this component it is necessary to do this here instead of ahead of time const streetAddressField = document.getElementById("streetAddressField"); - const autocompleteResultsContainer = document.getElementsByClassName("pac-container")[0]; + const autocompleteResultsContainer = + document.getElementsByClassName("pac-container")[0]; if (autocompleteResultsContainer) { streetAddressField.appendChild(autocompleteResultsContainer); } + + // Unfortunately this is the only place we can set the autocomplete attribute without the + // Google Places object resetting it to "off" which does nothing to prevent browser autofill + this.addressField1.setAttribute("autocomplete", "do-not-autofill"); }); this.addressField1.addEventListener("keydown", (e) => { @@ -260,18 +264,36 @@ export default { ".pac-container .pac-item-selected" ); - // If an item was selected then fill in the address with the selected item if (selectedItem !== null) { - // Fill-in the address using selected item in the list. + // If an item was selected then fill in the address with the selected item + // by triggering the "place_changed" event of the Autocomplete object this.autocomplete.dispatchEvent(event); } else { - // Fill-in the address using first item in the list. + // Otherwise fill-in the address using first item from the list. this.fillInAddressUsingFirstItem(); } } else { return; } }); + + this.addressField1.addEventListener("change", () => { + // If a match has been previously attempted then do nothing + if (this.matchFound !== null) { + return; + } + + // 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. + this.fillInAddressUsingFirstItem(); + } + }); }, fillInAddress(place) { if (!place) { @@ -312,14 +334,8 @@ export default { } } - // after showing the address fields, disable the address autocomplete - window.google.maps.event.removeListener(this.autocompleteListener); - window.google.maps.event.clearInstanceListeners(this.autocomplete); - this.addressField1.onchange = null; - const pacContainer = document.querySelector(".pac-container"); - if (pacContainer) { - pacContainer.remove(); - } + // After filling in the address fields, disable the address autocomplete + this.unloadAutocomplete(); }); } }, @@ -348,39 +364,30 @@ export default { resetAlerts() { this.displayVerificationWarning = false; }, - forceRerender() { - this.componentKey.value += 1; + unloadAutocomplete() { + window.google.maps.event.removeListener(this.autocompleteListener); + window.google.maps.event.clearInstanceListeners(this.autocomplete); + this.addressField1.onchange = null; + + const pacContainer = document.querySelector(".pac-container"); + if (pacContainer) { + pacContainer.remove(); + } } }, mounted() { - console.log("mounted") - // Load the Google Places Autocomplete script - const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY; - this.$loadScript( - `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places&callback=Function.prototype` - ).then(() => { - // When loaded trigger the setup - this.scriptLoaded = true; - }); + // If we already have a full address, show it + this.showAddressFields = this.addressModel.streetAddress && + this.addressModel.city && + this.addressModel.state && + this.addressModel.zipCode; + + this.loadGooglePlacesAutocompleteScript(); }, unmounted() { - console.log("unmounted") - }, - beforeUpdate() { - // Make place results box stick to the input on scroll - const streetAddressField = document.getElementById("streetAddressField"); - const autocompleteResultsContainer = document.getElementsByClassName("pac-container")[0]; - if (autocompleteResultsContainer) { - streetAddressField.appendChild(autocompleteResultsContainer); - } + this.unloadAutocomplete(); }, watch: { - scriptLoaded: { - handler() { - // After script is loaded, initialize the autocomplete textbox - this.initializeAutocomplete(); - }, - }, matchFound: { handler(newValue) { if (newValue === null) { @@ -398,7 +405,7 @@ export default { this.addressModel.state = ""; this.addressModel.zipCode = ""; } - this.showAddressFields = true; + this.displayVerificationWarning = false; // Only deep watch the Address Model after a failed match @@ -421,6 +428,7 @@ export default { alert, }, }; + diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue index dd4780928..ca286ef65 100644 --- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue +++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue @@ -33,10 +33,10 @@ :footerButtonText="modalFooterText" :onModalOpenedCallback="onModalOpened" :onModalClosedCallback="onModalClosed" - @modalOpened="setModalOpened" + @isModalOpened="setModalStatus" @footer-button-event="setMobileLocation"> - - @@ -87,7 +86,7 @@ export default { internalModel: deepClone(this.modelValue), displayInvalidZipAlert: false, addressQuestionsKey: 0, - modalOpened: false, + isModalOpened: false, }; }, setup(props) { @@ -191,6 +190,9 @@ export default { modalFooterText() { return this.getCmsContent(this.modalWidgetName, "FooterText"); }, + modal() { + return this.$refs[this.modalName]; + }, addressModel: { get: function () { return this.modelValue.addressQuestions; @@ -199,52 +201,23 @@ export default { }, methods: { openModal() { - this.$refs[this.modalName].openModal(); - }, - setModalOpened(isOpened) { - this.modalOpened = isOpened; - console.log(this.modalOpened) - }, - closeModal() { - this.$refs[this.modalName].closeModal(); + this.modal.openModal(); }, onModalOpened() { this.internalModel = deepClone(this.modelValue); }, + setModalStatus(isOpened) { + this.isModalOpened = isOpened; + }, + closeModal() { + this.modal.closeModal(); + }, onModalClosed() { this.displayInvalidZipAlert = false; this.internalModel = deepClone(this.modelValue); - this.resetValidation(); - }, - resetComponent(updatedServiceZipCodeInfo) { - // Reset the validation form, setting the initial values - // for the state and zipCode to those that were entered - // on the service-zip-modal-question component - this.$refs[this.modalName].resetForm({ - values: { - autocomplete: updatedServiceZipCodeInfo.streetAddress, - city: updatedServiceZipCodeInfo.city, - state: updatedServiceZipCodeInfo.state, - zipCode: updatedServiceZipCodeInfo.zipCode, - isVehicleProtected: updatedServiceZipCodeInfo.isVehicleProtected, - }, - }); }, resetModalButtonStyle() { - this.$refs[this.modalName].resetButtonStyle(); - }, - 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, - // }, - // }); + this.modal.resetButtonStyle(); }, async setMobileLocation() { if ( @@ -294,14 +267,6 @@ export default { this.internalModel = deepClone(newValue); this.handleChange(newValue); - - this.resetComponent({ - streetAddress: newValue.addressQuestions.streetAddress, - city: newValue.addressQuestions.city, - state: newValue.addressQuestions.state, - zipCode: newValue.addressQuestions.zipCode, - isVehicleProtected: newValue.isVehicleProtected, - }); }, deep: true, }, From 902d2a10b4c0d2c222d9262ec343539418f30501 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Thu, 22 Jun 2023 09:17:52 -0400 Subject: [PATCH 4/7] Working on newly discovered defects related to address-questions show all field logic --- .../address-questions.spec.js | 24 ++++----- .../address-questions/address-questions.vue | 54 +++++++++++-------- .../license-plate-lookup.vue | 3 +- .../appointment-type-question.vue | 1 - src/layouts/vin-lookup/vin-lookup.vue | 6 +-- src/store/index.js | 21 ++++++-- 6 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.spec.js b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.spec.js index 5cade9ddb..26a81341a 100644 --- a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.spec.js +++ b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.spec.js @@ -7,7 +7,6 @@ import { mount, shallowMount } from "@vue/test-utils"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { storeMutations } from "@/constants/store-mutations"; import store from "@/store"; -import { createImportSpecifier } from "typescript"; let autocompleteElement; describe("address-questions.vue", () => { @@ -134,22 +133,19 @@ describe("address-questions.vue", () => { }); test("Should set this.showAddressFields to true when the model is prepopulated", async () => { - // Arrange - // Act - const newAddressModel = { - streetAddress: "foo", - city: "foo", - state: "foo", - zipCode: "55555", - }; - const wrapper = shallowMount(addressQuestions, { - propsData: { - modelValue: newAddressModel, + // Arrange / Act + const { wrapper } = setupMocks({ + props: { + modelValue: { + streetAddress: "foo", + city: "foo", + state: "foo", + zipCode: "55555", + }, }, }); - // Act - wrapper.vm.setupAddressLookup(); + await wrapper.vm.$nextTick(); // Assert expect(wrapper.vm.showAddressFields).toBe(true); diff --git a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue index 22ccd3776..66cef8389 100644 --- a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue +++ b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue @@ -237,9 +237,9 @@ export default { this.fillInAddress ); - // When the Street Address textbox receives focus, - // append the search results list container to the bottom of the textbox - // and disable browser autofill + // When the Street Address textbox receives focus, + // append the search results list container to the bottom of the textbox + // and disable browser autofill this.addressField1.addEventListener("focus", (e) => { // Make place results box stick to the input on scroll const streetAddressField = document.getElementById("streetAddressField"); @@ -284,9 +284,7 @@ export default { } // Get the address that the user clicked on (if any) - const clickedAddress = document.querySelector( - ".pac-container .pac-item:hover" - ); + 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) { @@ -365,24 +363,39 @@ export default { this.displayVerificationWarning = false; }, unloadAutocomplete() { - window.google.maps.event.removeListener(this.autocompleteListener); - window.google.maps.event.clearInstanceListeners(this.autocomplete); - this.addressField1.onchange = null; + if (this.autocompleteListener && this.autocomplete) { + window.google.maps.event.removeListener(this.autocompleteListener); + this.autocompleteListener = null; - const pacContainer = document.querySelector(".pac-container"); - if (pacContainer) { - pacContainer.remove(); + window.google.maps.event.clearInstanceListeners(this.autocomplete); + this.autocomplete = null; + + this.addressField1.onchange = null; + + const pacContainer = document.querySelector(".pac-container"); + if (pacContainer) { + pacContainer.remove(); + } } - } + }, }, mounted() { // If we already have a full address, show it - this.showAddressFields = this.addressModel.streetAddress && - this.addressModel.city && - this.addressModel.state && - this.addressModel.zipCode; - - this.loadGooglePlacesAutocompleteScript(); + console.log(this.showAddressFields); + debugger; // eslint-disable-line no-debugger + console.log(`this.addressModel.streetAddress ${this.addressModel.streetAddress}`); + console.log(`this.addressModel.city ${this.addressModel.city}`); + console.log(`this.addressModel.state ${this.addressModel.state}`); + console.log(`this.addressModel.zipCode ${this.addressModel.zipCode}`); + this.showAddressFields = + this.addressModel.streetAddress !== "" && + this.addressModel.city !== "" && + this.addressModel.state !== "" && + this.addressModel.zipCode !== ""; + console.log(this.showAddressFields); + if (!this.showAddressFields) { + this.loadGooglePlacesAutocompleteScript(); + } }, unmounted() { this.unloadAutocomplete(); @@ -405,7 +418,7 @@ export default { this.addressModel.state = ""; this.addressModel.zipCode = ""; } - + this.displayVerificationWarning = false; // Only deep watch the Address Model after a failed match @@ -428,7 +441,6 @@ export default { alert, }, }; -