Add map and some finishing touches to change location modal

This commit is contained in:
Alex Humphries 2026-01-09 17:20:56 -05:00
parent bcc156ec29
commit f3f99457f2
4 changed files with 78 additions and 24 deletions

View file

@ -163,7 +163,7 @@ export default {
&.dropdown-compact {
display: flex;
align-items: center;
justify-content: end;
justify-content: flex-end;
margin-bottom: 1.25rem;
.form-label {
color: $darker-gray;

View file

@ -107,9 +107,11 @@ export default {
async getBoundsFromAddress(address) {
await this.setGeocoder();
const result = await this.geocoder.geocode({ address });
return result?.results?.length > 0
? result.results[0].geometry?.bounds
: null;
if (result?.results?.length > 0) {
return result.results[0].geometry?.bounds ?? null;
} else {
return null;
}
},
async createMapWithMarkersForAddresses(markers) {
const markerPositions = await this.getLocationsFromAddresses(markers);
@ -117,9 +119,12 @@ export default {
const map = await this.getMap(zipBounds?.getCenter());
await this.addMarkersToMap(map, markerPositions);
let positionsToDisplay = markerPositions.map((marker) => marker.position);
if(zipBounds) {
positionsToDisplay.push(zipBounds.getNorthEast());
positionsToDisplay.push(zipBounds.getSouthWest());
}
const positionsToDisplay = markerPositions.map((marker) => marker.position)
.concat(zipBounds?.getNorthEast(), zipBounds?.getSouthWest());
const bounds = this.getBounds(positionsToDisplay);
map.fitBounds(bounds);
}

View file

@ -42,12 +42,8 @@ export default {
methods: {
updateModelValue() {
this.$emit('update:modelValue', this.internalZipcode);
this.internalZipcode = '';
},
},
watch: {
modelValue(newValue) {
this.internalZipcode = newValue;
}
}
};
</script>

View file

@ -19,9 +19,9 @@
<span class="shop-name">{{ displayedShopName }}</span>
<span class="shop-distance">{{ modelValue.distanceInMiles?.toFixed(2) }} mi</span>
</div>
<div class="address-line">{{ toTitleCase(modelValue.address?.streetAddress) }}</div>
<div class="address-line">{{ getProviderAddress(modelValue) }}</div>
<div class="address-line">
{{ toTitleCase(modelValue.address?.city) }}, {{ modelValue.address?.state }} {{ modelValue.address?.zipCode }}
{{ getProviderCityZipState(modelValue) }}
</div>
</div>
<buttonMain
@ -36,6 +36,11 @@
:footerButtonText="modalFooterText"
:modalPosition="modalPositions.center"
@footerButtonEvent="updateSelectedProvider">
<googleMap
id="map"
class="mb-4"
:markers="providerAddresses"
:zipCode="internalZipcode" />
<dropdownQuestion
inputId="searchRadiusDropdown"
ref="searchRadiusQuestion"
@ -59,6 +64,7 @@
{{ serviceZipPrompt }}
</span>
<serviceZipQuestion
v-if="renderServiceZip"
ref="serviceZipCodeQuestion"
v-model="internalZipcode"
customInputId="serviceZipCode"
@ -84,11 +90,12 @@ import serviceZipQuestion from '@/layouts/service-location/service-zip-question/
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
import googleMap from '@/iss-components/google-map/google-map.vue';
// Supporting files
import baseMixin from '@/mixins/base-mixin.js';
import { toTitleCase } from '@/helpers/text-helper.js';
import { markRaw, nextTick } from 'vue';
import { markRaw } from 'vue';
import { getServiceabilityDetails, getZipCodeData,getAvailabilityRating } from '@/helpers/service-location-helper';
import { useMainStore } from '@/store';
import widgetFields from '@/constants/cms-widget-fields';
@ -103,7 +110,8 @@ export default {
modal,
serviceZipQuestion,
buttonQuestion,
dropdownQuestion
dropdownQuestion,
googleMap
},
mixins: [baseMixin],
props: {
@ -116,7 +124,7 @@ export default {
validationRules: String,
isDisplayed: Boolean,
modalWidgetName: String,
selectedAppointmentType: String
selectedAppointmentType: String,
},
data() {
return {
@ -132,7 +140,8 @@ export default {
searchRadiusInMiles: 100,
nearbyShops: [],
modalPositions,
dropdownVariants
dropdownVariants,
renderServiceZip: true
};
},
emits: ['update:modelValue'],
@ -179,16 +188,13 @@ export default {
},
nearbyShopsData() {
return this.nearbyShops.map((shopProvider) => {
const streetAddress = toTitleCase(shopProvider.address.streetAddress);
const city = toTitleCase(shopProvider.address.city);
const { state } = shopProvider.address;
const { zipCode } = shopProvider.address;
const distanceInMiles = shopProvider.distanceInMiles.toFixed(2);
return {
buttonLabel: city,
buttonLabelSubCopy: `${distanceInMiles} mi`,
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
buttonBodyCopy: this.getFullProviderAddress(shopProvider),
value: shopProvider.providerNumber
};
});
@ -200,11 +206,18 @@ export default {
optionsObj[option.Name] = option.Text;
});
return optionsObj;
}
},
providerAddresses() {
return this.nearbyShops?.map((provider) => ({
title: toTitleCase(provider.companyName),
fullAddress: this.getFullProviderAddress(provider),
addressLines: [this.getProviderAddress(provider), this.getProviderCityZipState(provider)]
})) ?? [];
},
},
watch: {
internalZipcode() {
this.refreshShops();
async internalZipcode() {
await this.resetsOnZipInput();
},
async searchRadiusInMiles() {
this.nearbyShops = await this.getNearbyShops(this.searchRadiusInMiles);
@ -230,6 +243,7 @@ export default {
this.resetsOnZipInput().then(() => {
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
});
this.forceServiceZipRerender();
},
onModalClosed() {
this.internalZipcode = this.serviceZipcode;
@ -249,6 +263,42 @@ export default {
async getNearbyShops(radiusInMiles) {
const result = await useMainStore().getProviders(this.internalZipcode, radiusInMiles);
return result.data.shopProviders;
},
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) {
return toTitleCase(provider?.address?.streetAddress);
},
getProviderCityZipState(provider) {
const city = toTitleCase(provider?.address?.city);
const state = provider?.address?.state ?? '';
const zipCode = provider?.address?.zipCode ?? '';
let addressLine2 = '';
if (city) {
addressLine2 += city;
if (state || zipCode) {
addressLine2 += state ? ', ' : ' ';
}
}
if (state) {
addressLine2 += state;
addressLine2 += zipCode ? ' ' : '';
}
if (zipCode) {
addressLine2 += zipCode;
}
return addressLine2;
},
forceServiceZipRerender() {
this.renderServiceZip = false;
this.$nextTick(() => {
this.renderServiceZip = true;
});
}
}
};
@ -283,5 +333,8 @@ export default {
color: $black;
font-weight: 600;
}
:deep(#map) {
height: 27rem;
}
}
</style>