Basic auto-complete function complete with standard html elements
This commit is contained in:
parent
36756df098
commit
45f048b906
6 changed files with 405 additions and 0 deletions
0
src/layouts/address-lookup/address-lookup.spec.js
Normal file
0
src/layouts/address-lookup/address-lookup.spec.js
Normal file
81
src/layouts/address-lookup/address-lookup.vue
Normal file
81
src/layouts/address-lookup/address-lookup.vue
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall">
|
||||
<funnelHeader ref="funnelHeader" />
|
||||
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage=false />
|
||||
<funnelSubHeader ref="funnelSubHeader" />
|
||||
<customerQuestions ref="customerQuestions" />
|
||||
<funnelFooter ref="funnelFooter" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
|
||||
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import store from "@/store";
|
||||
|
||||
|
||||
export default {
|
||||
name: "address-lookup",
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.$refs.funnelHeader.initializeComponent(
|
||||
resultMap.cmsContent.FunnelHeaderWidget
|
||||
);
|
||||
vm.$refs.vehicleBanner.initializeComponent(
|
||||
resultMap.cmsContent.VehicleBannerWidget
|
||||
);
|
||||
vm.$refs.funnelSubHeader.initializeComponent(
|
||||
resultMap.cmsContent.FunnelSubHeaderWidget
|
||||
);
|
||||
vm.$refs.funnelFooter.initializeComponent(
|
||||
resultMap.cmsContent.FunnelFooterWidget
|
||||
);
|
||||
});
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
selectedDamageLocations: [],
|
||||
driverSideOptionsData: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return store.getters.vehicle.carId !== null;
|
||||
},
|
||||
resetDependentState() {
|
||||
// Invokes
|
||||
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
funnelHeader,
|
||||
funnelFooter,
|
||||
vehicleBanner,
|
||||
funnelSubHeader,
|
||||
customerQuestions,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
<template>
|
||||
<form>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<label for="autocomplete">Street address</label>
|
||||
<input ref="autocomplete"
|
||||
id="autocomplete"
|
||||
placeholder="Search"
|
||||
class="form-control search-location"
|
||||
type="text"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form>
|
||||
<div v-show="showAddressFields" class="row my-4">
|
||||
<div class="col">
|
||||
<label for="city">City</label>
|
||||
<input ref="city"
|
||||
id="city"
|
||||
class="form-control"
|
||||
type="text"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form>
|
||||
<div v-show="showAddressFields" class="row my-4">
|
||||
<div class="col-6">
|
||||
<label for="state">State</label>
|
||||
<select ref="state"
|
||||
id="state"
|
||||
class="form-control">
|
||||
<option value="AL">Alabama</option>
|
||||
<option value="AK">Alaska</option>
|
||||
<option value="AZ">Arizona</option>
|
||||
<option value="AR">Arkansas</option>
|
||||
<option value="CA">California</option>
|
||||
<option value="CO">Colorado</option>
|
||||
<option value="CT">Connecticut</option>
|
||||
<option value="DE">Delaware</option>
|
||||
<option value="DC">District Of Columbia</option>
|
||||
<option value="FL">Florida</option>
|
||||
<option value="GA">Georgia</option>
|
||||
<option value="HI">Hawaii</option>
|
||||
<option value="ID">Idaho</option>
|
||||
<option value="IL">Illinois</option>
|
||||
<option value="IN">Indiana</option>
|
||||
<option value="IA">Iowa</option>
|
||||
<option value="KS">Kansas</option>
|
||||
<option value="KY">Kentucky</option>
|
||||
<option value="LA">Louisiana</option>
|
||||
<option value="ME">Maine</option>
|
||||
<option value="MD">Maryland</option>
|
||||
<option value="MA">Massachusetts</option>
|
||||
<option value="MI">Michigan</option>
|
||||
<option value="MN">Minnesota</option>
|
||||
<option value="MS">Mississippi</option>
|
||||
<option value="MO">Missouri</option>
|
||||
<option value="MT">Montana</option>
|
||||
<option value="NE">Nebraska</option>
|
||||
<option value="NV">Nevada</option>
|
||||
<option value="NH">New Hampshire</option>
|
||||
<option value="NJ">New Jersey</option>
|
||||
<option value="NM">New Mexico</option>
|
||||
<option value="NY">New York</option>
|
||||
<option value="NC">North Carolina</option>
|
||||
<option value="ND">North Dakota</option>
|
||||
<option value="OH">Ohio</option>
|
||||
<option value="OK">Oklahoma</option>
|
||||
<option value="OR">Oregon</option>
|
||||
<option value="PA">Pennsylvania</option>
|
||||
<option value="RI">Rhode Island</option>
|
||||
<option value="SC">South Carolina</option>
|
||||
<option value="SD">South Dakota</option>
|
||||
<option value="TN">Tennessee</option>
|
||||
<option value="TX">Texas</option>
|
||||
<option value="UT">Utah</option>
|
||||
<option value="VT">Vermont</option>
|
||||
<option value="VA">Virginia</option>
|
||||
<option value="WA">Washington</option>
|
||||
<option value="WV">West Virginia</option>
|
||||
<option value="WI">Wisconsin</option>
|
||||
<option value="WY">Wyoming</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label for="zip">Zip</label>
|
||||
<input ref="zip"
|
||||
id="zip"
|
||||
class="form-control"
|
||||
type="text"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<alert v-show="displayVerificationWarning"
|
||||
alertClass="alert-warning"
|
||||
alertHeadline="Please verify your address."
|
||||
alertCopy="We've selected the closest location match. Please revise as needed."
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<alert v-show="displayNoMatchWarning"
|
||||
alertClass="alert-warning"
|
||||
alertHeadline="Please verify your address."
|
||||
alertCopy="We were unable to find a location match. Please re-enter your street address."
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
//import store from "@/store";
|
||||
|
||||
export default ({
|
||||
name: "address-questions",
|
||||
data() {
|
||||
return {
|
||||
showAddressFields: false,
|
||||
displayVerificationWarning: false,
|
||||
displayNoMatchWarning: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
modelValue: Array,
|
||||
groupName: String,
|
||||
},
|
||||
methods: {
|
||||
initializeComponent(cmsContent, damageOptions){
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
|
||||
let addressField1 = document.getElementById("autocomplete");
|
||||
let self = this;
|
||||
|
||||
let apiKey = "AIzaSyDptGCkOPgN2uWJOy4ou4M33phRD4MAoJo"; // localhost:8080
|
||||
//let apiKey = "AIzaSyBji_2ApAj2vE_XNGyV-LaUEKrmuElpJ1w"; // Dev and above
|
||||
|
||||
this.$loadScript(`https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places`)
|
||||
.then(() => {
|
||||
// Script is loaded, initialize the autocomplete textbox
|
||||
const autocomplete = new window.google.maps.places.Autocomplete(
|
||||
addressField1,
|
||||
{
|
||||
componentRestrictions: { country: ["us"] },
|
||||
fields: ["address_components"],
|
||||
types: ["address"],
|
||||
}
|
||||
);
|
||||
|
||||
// Standard place_changed event handling
|
||||
autocomplete.addListener('place_changed', fillInAddress);
|
||||
|
||||
addressField1.onblur = function() {
|
||||
var hover = document.querySelector(".pac-container .pac-item:hover");
|
||||
|
||||
// if an item has been clicked, do nothing, otherwise get first solution and use Geocoder to get the place
|
||||
if (hover === null) {
|
||||
var item = document.querySelector(".pac-container .pac-item");
|
||||
if (item != null) {
|
||||
var firstResult = item.textContent;
|
||||
var 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;
|
||||
self.displayNoMatchWarning = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
let city = document.querySelector("#city");
|
||||
let state = document.querySelector("#state");
|
||||
let zip = document.querySelector("#zip");
|
||||
|
||||
city.value = "";
|
||||
state.value = "";
|
||||
zip.value = "";
|
||||
|
||||
self.displayVerificationWarning = false;
|
||||
self.displayNoMatchWarning = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
function fillInAddress(place) {
|
||||
if (!place) {
|
||||
place = autocomplete.getPlace();
|
||||
}
|
||||
|
||||
if (place && place.address_components) {
|
||||
let address1 = "";
|
||||
let city = document.querySelector("#city");
|
||||
let state = document.querySelector("#state");
|
||||
let zip = document.querySelector("#zip");
|
||||
self.showAddressFields = true;
|
||||
|
||||
for (const component of place.address_components) {
|
||||
const componentType = component.types[0];
|
||||
|
||||
switch (componentType) {
|
||||
case "street_number": {
|
||||
address1 = `${component.long_name} ${address1}`;
|
||||
break;
|
||||
}
|
||||
case "route": {
|
||||
address1 += component.short_name;
|
||||
break;
|
||||
}
|
||||
case "locality": {
|
||||
city.value = component.long_name;
|
||||
break;
|
||||
}
|
||||
case "administrative_area_level_1": {
|
||||
state.value = component.short_name;
|
||||
break;
|
||||
}
|
||||
case "postal_code": {
|
||||
zip.value = component.long_name;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
addressField1.value = address1;
|
||||
self.displayVerificationWarning = false;
|
||||
self.displayNoMatchWarning = false;
|
||||
}
|
||||
else {
|
||||
self.displayVerificationWarning = true;
|
||||
self.displayNoMatchWarning = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Failed to fetch script
|
||||
console.log("Unable to load Google Places API script");
|
||||
});
|
||||
},
|
||||
components: {
|
||||
alert,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
<addressQuestions />
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<label for="firstName">First name</label>
|
||||
<input ref="firstName"
|
||||
id="firstName"
|
||||
class="form-control"
|
||||
type="text"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<label for="lastName">Last name</label>
|
||||
<input ref="lastName"
|
||||
id="lastName"
|
||||
class="form-control"
|
||||
type="text"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<emailQuestion />
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import addressQuestions from "@/layouts/address-lookup/customer-questions/address-questions/address-questions";
|
||||
import emailQuestion from "@/layouts/address-lookup/customer-questions/email-question/email-question";
|
||||
|
||||
//import store from "@/store";
|
||||
|
||||
export default ({
|
||||
name: "customer-questions",
|
||||
data(){
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
props: {
|
||||
modelValue: Array,
|
||||
groupName: String,
|
||||
},
|
||||
methods: {
|
||||
initializeComponent(cmsContent, damageOptions){
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
components: {
|
||||
addressQuestions,
|
||||
emailQuestion,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<label for="email">Email address</label>
|
||||
<input ref="email"
|
||||
id="email"
|
||||
class="form-control"
|
||||
type="text"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -4,6 +4,7 @@ const fmgPageValues = {
|
|||
VEHICLE_MODEL: "vehicle-model",
|
||||
VEHICLE_STYLE: "vehicle-style",
|
||||
VEHICLE_DAMAGE: "vehicle-damage",
|
||||
ADDRESS_LOOKUP: "address-lookup",
|
||||
};
|
||||
|
||||
export { fmgPageValues };
|
||||
|
|
|
|||
Loading…
Reference in a new issue