SSR-776 Make Google Maps pins clickable

This commit is contained in:
Josh Dassinger 2024-08-29 14:02:02 -05:00
parent 31da5e40f8
commit 4aa6c4ed64
2 changed files with 81 additions and 31 deletions

View file

@ -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);
} }
} }
}; };

View file

@ -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;