Add map and some finishing touches to change location modal
This commit is contained in:
parent
bcc156ec29
commit
f3f99457f2
4 changed files with 78 additions and 24 deletions
|
|
@ -163,7 +163,7 @@ export default {
|
||||||
&.dropdown-compact {
|
&.dropdown-compact {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: end;
|
justify-content: flex-end;
|
||||||
margin-bottom: 1.25rem;
|
margin-bottom: 1.25rem;
|
||||||
.form-label {
|
.form-label {
|
||||||
color: $darker-gray;
|
color: $darker-gray;
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,11 @@ export default {
|
||||||
async getBoundsFromAddress(address) {
|
async getBoundsFromAddress(address) {
|
||||||
await this.setGeocoder();
|
await this.setGeocoder();
|
||||||
const result = await this.geocoder.geocode({ address });
|
const result = await this.geocoder.geocode({ address });
|
||||||
return result?.results?.length > 0
|
if (result?.results?.length > 0) {
|
||||||
? result.results[0].geometry?.bounds
|
return result.results[0].geometry?.bounds ?? null;
|
||||||
: null;
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async createMapWithMarkersForAddresses(markers) {
|
async createMapWithMarkersForAddresses(markers) {
|
||||||
const markerPositions = await this.getLocationsFromAddresses(markers);
|
const markerPositions = await this.getLocationsFromAddresses(markers);
|
||||||
|
|
@ -117,9 +119,12 @@ export default {
|
||||||
const map = await this.getMap(zipBounds?.getCenter());
|
const map = await this.getMap(zipBounds?.getCenter());
|
||||||
|
|
||||||
await this.addMarkersToMap(map, markerPositions);
|
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);
|
const bounds = this.getBounds(positionsToDisplay);
|
||||||
map.fitBounds(bounds);
|
map.fitBounds(bounds);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,8 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
updateModelValue() {
|
updateModelValue() {
|
||||||
this.$emit('update:modelValue', this.internalZipcode);
|
this.$emit('update:modelValue', this.internalZipcode);
|
||||||
|
this.internalZipcode = '';
|
||||||
},
|
},
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
modelValue(newValue) {
|
|
||||||
this.internalZipcode = newValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@
|
||||||
<span class="shop-name">{{ displayedShopName }}</span>
|
<span class="shop-name">{{ displayedShopName }}</span>
|
||||||
<span class="shop-distance">{{ modelValue.distanceInMiles?.toFixed(2) }} mi</span>
|
<span class="shop-distance">{{ modelValue.distanceInMiles?.toFixed(2) }} mi</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="address-line">{{ toTitleCase(modelValue.address?.streetAddress) }}</div>
|
<div class="address-line">{{ getProviderAddress(modelValue) }}</div>
|
||||||
<div class="address-line">
|
<div class="address-line">
|
||||||
{{ toTitleCase(modelValue.address?.city) }}, {{ modelValue.address?.state }} {{ modelValue.address?.zipCode }}
|
{{ getProviderCityZipState(modelValue) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<buttonMain
|
<buttonMain
|
||||||
|
|
@ -36,6 +36,11 @@
|
||||||
:footerButtonText="modalFooterText"
|
:footerButtonText="modalFooterText"
|
||||||
:modalPosition="modalPositions.center"
|
:modalPosition="modalPositions.center"
|
||||||
@footerButtonEvent="updateSelectedProvider">
|
@footerButtonEvent="updateSelectedProvider">
|
||||||
|
<googleMap
|
||||||
|
id="map"
|
||||||
|
class="mb-4"
|
||||||
|
:markers="providerAddresses"
|
||||||
|
:zipCode="internalZipcode" />
|
||||||
<dropdownQuestion
|
<dropdownQuestion
|
||||||
inputId="searchRadiusDropdown"
|
inputId="searchRadiusDropdown"
|
||||||
ref="searchRadiusQuestion"
|
ref="searchRadiusQuestion"
|
||||||
|
|
@ -59,6 +64,7 @@
|
||||||
{{ serviceZipPrompt }}
|
{{ serviceZipPrompt }}
|
||||||
</span>
|
</span>
|
||||||
<serviceZipQuestion
|
<serviceZipQuestion
|
||||||
|
v-if="renderServiceZip"
|
||||||
ref="serviceZipCodeQuestion"
|
ref="serviceZipCodeQuestion"
|
||||||
v-model="internalZipcode"
|
v-model="internalZipcode"
|
||||||
customInputId="serviceZipCode"
|
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 buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||||
|
import googleMap from '@/iss-components/google-map/google-map.vue';
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import baseMixin from '@/mixins/base-mixin.js';
|
import baseMixin from '@/mixins/base-mixin.js';
|
||||||
import { toTitleCase } from '@/helpers/text-helper.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 { getServiceabilityDetails, getZipCodeData,getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import widgetFields from '@/constants/cms-widget-fields';
|
import widgetFields from '@/constants/cms-widget-fields';
|
||||||
|
|
@ -103,7 +110,8 @@ export default {
|
||||||
modal,
|
modal,
|
||||||
serviceZipQuestion,
|
serviceZipQuestion,
|
||||||
buttonQuestion,
|
buttonQuestion,
|
||||||
dropdownQuestion
|
dropdownQuestion,
|
||||||
|
googleMap
|
||||||
},
|
},
|
||||||
mixins: [baseMixin],
|
mixins: [baseMixin],
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -116,7 +124,7 @@ export default {
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
isDisplayed: Boolean,
|
isDisplayed: Boolean,
|
||||||
modalWidgetName: String,
|
modalWidgetName: String,
|
||||||
selectedAppointmentType: String
|
selectedAppointmentType: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -132,7 +140,8 @@ export default {
|
||||||
searchRadiusInMiles: 100,
|
searchRadiusInMiles: 100,
|
||||||
nearbyShops: [],
|
nearbyShops: [],
|
||||||
modalPositions,
|
modalPositions,
|
||||||
dropdownVariants
|
dropdownVariants,
|
||||||
|
renderServiceZip: true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
|
|
@ -179,16 +188,13 @@ export default {
|
||||||
},
|
},
|
||||||
nearbyShopsData() {
|
nearbyShopsData() {
|
||||||
return this.nearbyShops.map((shopProvider) => {
|
return this.nearbyShops.map((shopProvider) => {
|
||||||
const streetAddress = toTitleCase(shopProvider.address.streetAddress);
|
|
||||||
const city = toTitleCase(shopProvider.address.city);
|
const city = toTitleCase(shopProvider.address.city);
|
||||||
const { state } = shopProvider.address;
|
|
||||||
const { zipCode } = shopProvider.address;
|
|
||||||
const distanceInMiles = shopProvider.distanceInMiles.toFixed(2);
|
const distanceInMiles = shopProvider.distanceInMiles.toFixed(2);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
buttonLabel: city,
|
buttonLabel: city,
|
||||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||||
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
|
buttonBodyCopy: this.getFullProviderAddress(shopProvider),
|
||||||
value: shopProvider.providerNumber
|
value: shopProvider.providerNumber
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -200,11 +206,18 @@ export default {
|
||||||
optionsObj[option.Name] = option.Text;
|
optionsObj[option.Name] = option.Text;
|
||||||
});
|
});
|
||||||
return optionsObj;
|
return optionsObj;
|
||||||
}
|
},
|
||||||
|
providerAddresses() {
|
||||||
|
return this.nearbyShops?.map((provider) => ({
|
||||||
|
title: toTitleCase(provider.companyName),
|
||||||
|
fullAddress: this.getFullProviderAddress(provider),
|
||||||
|
addressLines: [this.getProviderAddress(provider), this.getProviderCityZipState(provider)]
|
||||||
|
})) ?? [];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
internalZipcode() {
|
async internalZipcode() {
|
||||||
this.refreshShops();
|
await this.resetsOnZipInput();
|
||||||
},
|
},
|
||||||
async searchRadiusInMiles() {
|
async searchRadiusInMiles() {
|
||||||
this.nearbyShops = await this.getNearbyShops(this.searchRadiusInMiles);
|
this.nearbyShops = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||||
|
|
@ -230,6 +243,7 @@ export default {
|
||||||
this.resetsOnZipInput().then(() => {
|
this.resetsOnZipInput().then(() => {
|
||||||
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
||||||
});
|
});
|
||||||
|
this.forceServiceZipRerender();
|
||||||
},
|
},
|
||||||
onModalClosed() {
|
onModalClosed() {
|
||||||
this.internalZipcode = this.serviceZipcode;
|
this.internalZipcode = this.serviceZipcode;
|
||||||
|
|
@ -249,6 +263,42 @@ export default {
|
||||||
async getNearbyShops(radiusInMiles) {
|
async getNearbyShops(radiusInMiles) {
|
||||||
const result = await useMainStore().getProviders(this.internalZipcode, radiusInMiles);
|
const result = await useMainStore().getProviders(this.internalZipcode, radiusInMiles);
|
||||||
return result.data.shopProviders;
|
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;
|
color: $black;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
:deep(#map) {
|
||||||
|
height: 27rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue