SSR-776 Make Google Maps pins clickable
This commit is contained in:
parent
31da5e40f8
commit
4aa6c4ed64
2 changed files with 81 additions and 31 deletions
|
|
@ -8,13 +8,14 @@
|
||||||
export default {
|
export default {
|
||||||
name: 'google-map',
|
name: 'google-map',
|
||||||
props: {
|
props: {
|
||||||
addresses: Array,
|
providers: Array,
|
||||||
zipCode: String
|
zipCode: String
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
country: 'USA',
|
country: 'USA',
|
||||||
geocoder: null
|
geocoder: null,
|
||||||
|
infoWindow: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -23,12 +24,12 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
async addresses(newAddresses) {
|
async providers(newProviders) {
|
||||||
this.createMapWithMarkersForAddresses(newAddresses);
|
this.createMapWithMarkersForAddresses(newProviders);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
this.createMapWithMarkersForAddresses(this.addresses);
|
this.createMapWithMarkersForAddresses(this.providers);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getMap(center) {
|
async getMap(center) {
|
||||||
|
|
@ -50,20 +51,60 @@ export default {
|
||||||
this.geocoder = new Geocoder();
|
this.geocoder = new Geocoder();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async addMarkersToMap(map, positions) {
|
async addMarkersToMap(map, providers) {
|
||||||
const { AdvancedMarkerElement } = await window.google.maps.importLibrary('marker');
|
const { AdvancedMarkerElement, PinElement } = await window.google.maps.importLibrary('marker');
|
||||||
positions?.forEach((position) => new AdvancedMarkerElement({ map, position }));
|
providers?.forEach((provider, index) => {
|
||||||
|
const pin = new PinElement({
|
||||||
|
glyph: String.fromCharCode('A'.charCodeAt(0) + index),
|
||||||
|
glyphColor: '#000000',
|
||||||
|
borderColor: '#000000'
|
||||||
|
});
|
||||||
|
const marker = new AdvancedMarkerElement({
|
||||||
|
map,
|
||||||
|
position: provider.position,
|
||||||
|
title: provider.companyName,
|
||||||
|
content: pin.element
|
||||||
|
});
|
||||||
|
this.createMarkerInfoWindows(marker, provider);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
async getLocationsFromAddresses(addresses) {
|
createMarkerInfoWindows(marker, provider) {
|
||||||
|
const directionsUrl = this.createGetDirectionsUrl(provider);
|
||||||
|
const content = `<div>
|
||||||
|
<span style="color: black; font-weight:bold"> ${provider.companyName} </span>
|
||||||
|
<br /> ${provider.addressLine1}
|
||||||
|
<br /> ${provider.addressLine2}
|
||||||
|
<br /> <a href="${directionsUrl}" target="_blank">Get directions</a>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
const infoWindow = new window.google.maps.InfoWindow({
|
||||||
|
content
|
||||||
|
});
|
||||||
|
|
||||||
|
marker.addListener('click', () => {
|
||||||
|
this.infoWindow?.close();
|
||||||
|
this.infoWindow = infoWindow;
|
||||||
|
infoWindow.open(marker.map, marker);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
createGetDirectionsUrl(provider) {
|
||||||
|
return `https://maps.google.com/maps?saddr=&daddr=${encodeURIComponent(provider.fullAddress)}`;
|
||||||
|
},
|
||||||
|
async getLocationsFromAddresses(providers) {
|
||||||
await this.setGeocoder();
|
await this.setGeocoder();
|
||||||
|
|
||||||
const geocodeShopAddressPromises = addresses?.map((address) => this.geocoder.geocode({ address })) ?? [];
|
const geocodeShopAddressPromises = providers?.map((provider) => this.geocoder.geocode({ address: provider.fullAddress })) ?? [];
|
||||||
const geocodeShopAddressResults = await Promise.all(geocodeShopAddressPromises);
|
const geocodeShopAddressResults = await Promise.all(geocodeShopAddressPromises);
|
||||||
return geocodeShopAddressResults.map((result) =>
|
|
||||||
(result?.results?.length > 0
|
return providers.map((provider, index) => {
|
||||||
? result.results[0].geometry?.location
|
const { results } = geocodeShopAddressResults[index];
|
||||||
: null))
|
let position = null;
|
||||||
.filter((loc) => loc != null);
|
if (results && results.length > 0) {
|
||||||
|
position = results[0].geometry?.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...provider, position };
|
||||||
|
}).filter((provider) => provider.position != null);
|
||||||
},
|
},
|
||||||
async getBoundsFromAddress(address) {
|
async getBoundsFromAddress(address) {
|
||||||
await this.setGeocoder();
|
await this.setGeocoder();
|
||||||
|
|
@ -72,16 +113,17 @@ export default {
|
||||||
? result.results[0].geometry?.bounds
|
? result.results[0].geometry?.bounds
|
||||||
: null;
|
: null;
|
||||||
},
|
},
|
||||||
async createMapWithMarkersForAddresses(addresses) {
|
async createMapWithMarkersForAddresses(providers) {
|
||||||
const shopPositions = await this.getLocationsFromAddresses(addresses);
|
const providerPositions = await this.getLocationsFromAddresses(providers);
|
||||||
const zipBounds = await this.getBoundsFromAddress(this.zipCodeAddress);
|
const zipBounds = await this.getBoundsFromAddress(this.zipCodeAddress);
|
||||||
const map = await this.getMap(zipBounds?.getCenter());
|
const map = await this.getMap(zipBounds.getCenter());
|
||||||
|
|
||||||
await this.addMarkersToMap(map, shopPositions);
|
await this.addMarkersToMap(map, providerPositions);
|
||||||
|
|
||||||
const positionsToDisplay = shopPositions.concat(zipBounds?.getNorthEast(), zipBounds?.getSouthWest());
|
const positionsToDisplay = providerPositions.map((provider) => provider.position)
|
||||||
|
.concat(zipBounds?.getNorthEast(), zipBounds?.getSouthWest());
|
||||||
const bounds = this.getBounds(positionsToDisplay);
|
const bounds = this.getBounds(positionsToDisplay);
|
||||||
map?.fitBounds(bounds);
|
map.fitBounds(bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
<googleMap
|
<googleMap
|
||||||
id="map"
|
id="map"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
:addresses="providerAddresses"
|
:providers="providerAddresses"
|
||||||
:zipCode="mapZipCode" />
|
:zipCode="mapZipCode" />
|
||||||
<Form
|
<Form
|
||||||
id="providerSelectionForm"
|
id="providerSelectionForm"
|
||||||
|
|
@ -281,10 +281,12 @@ export default {
|
||||||
)?.replaceAll('{custom:radiusInMiles}', this.radiusInMiles);
|
)?.replaceAll('{custom:radiusInMiles}', this.radiusInMiles);
|
||||||
},
|
},
|
||||||
providerAddresses() {
|
providerAddresses() {
|
||||||
return (
|
return this.providers?.map((provider) => ({
|
||||||
this.providers?.map((provider) =>
|
...provider,
|
||||||
this.getProviderAddress(provider)) ?? []
|
fullAddress: this.getFullProviderAddress(provider),
|
||||||
);
|
addressLine1: this.getProviderAddress(provider),
|
||||||
|
addressLine2: this.getProviderCityZipState(provider)
|
||||||
|
})) ?? [];
|
||||||
},
|
},
|
||||||
providerButtonData() {
|
providerButtonData() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -350,7 +352,17 @@ export default {
|
||||||
this.providers = providers;
|
this.providers = providers;
|
||||||
this.selectedProviderNumber = providerNumber;
|
this.selectedProviderNumber = providerNumber;
|
||||||
},
|
},
|
||||||
|
getFullProviderAddress(provider) {
|
||||||
|
const addressLine1 = this.getProviderAddress(provider);
|
||||||
|
const addressLine2 = this.getProviderCityZipState(provider);
|
||||||
|
const joinString =
|
||||||
|
addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : '';
|
||||||
|
return [addressLine1, addressLine2].join(joinString);
|
||||||
|
},
|
||||||
getProviderAddress(provider) {
|
getProviderAddress(provider) {
|
||||||
|
return toTitleCase(provider?.address?.streetAddress);
|
||||||
|
},
|
||||||
|
getProviderCityZipState(provider) {
|
||||||
const city = toTitleCase(provider?.address?.city);
|
const city = toTitleCase(provider?.address?.city);
|
||||||
const state = provider?.address?.state ?? '';
|
const state = provider?.address?.state ?? '';
|
||||||
const zipCode = provider?.address?.zipCode ?? '';
|
const zipCode = provider?.address?.zipCode ?? '';
|
||||||
|
|
@ -368,11 +380,7 @@ export default {
|
||||||
if (zipCode) {
|
if (zipCode) {
|
||||||
addressLine2 += zipCode;
|
addressLine2 += zipCode;
|
||||||
}
|
}
|
||||||
|
return addressLine2;
|
||||||
const addressLine1 = toTitleCase(provider?.address?.streetAddress);
|
|
||||||
const joinString =
|
|
||||||
addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : '';
|
|
||||||
return [addressLine1, addressLine2].join(joinString);
|
|
||||||
},
|
},
|
||||||
async getProviderButtonData() {
|
async getProviderButtonData() {
|
||||||
this.reloadingProviders = true;
|
this.reloadingProviders = true;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue