<template lang="pug">
Multiselect(
ref="multiselect"
v-model="selected"
label="name"
track-by="id"
:placeholder="$t(placeholder)"
open-direction="bottom"
:options="optionsItems"
:multiple="false"
searchable
:loading="isLoading"
:clear-on-select="false"
:close-on-select="true"
:selectLabel="$t('geocoding.routing.client_zone_select.select_hint')"
:deselectLabel="$t('geocoding.routing.client_zone_select.deselect_hint')"
:selectedLabel="$t('geocoding.routing.client_zone_select.selected')"
v-bind="options"
)
template(v-slot:singleLabel="slotProps")
span {{selected.formatted||selected.formattedError||'...'}}
template(slot="noResult")
span {{$t('geocoding.routing.client_zone_select.no_results')}}
template(slot="noOptions")
span {{$t('geocoding.routing.client_zone_select.no_options')}}
</template>
<script>
import Multiselect from 'vue-multiselect'
import {
normalizeApiAddressResponse,
getFormattedAddressAlt,
} from '@/utils/address.js'
/**
* @description Allow selecting an address from a client zone (Address will be reversed from zone lat/lng)
* @requires i18n
* @requires Vuex (zones store)
* @requires address.js (utils)
* @requires Multiselect (third-party package)
* @namespace components
* @category components
* @subcategory shared/geocoding
* @module ClientZonesSelect
**/
export default {
components: {
Multiselect,
},
props: {
placeholder: {
type: String,
default: 'Tapez pour rechercher',
},
extraOptions: {
type: Object,
default: () => ({}),
},
},
data() {
return {
selected: null,
selectedReversed: {},
isLoading: false,
options: {
optionsLimit: 100,
...this.extraOptions,
},
}
},
computed: {
optionsItems() {
return this.$store.getters['zones/allClientZones'].map((item) => ({
id: item.id,
name: item.name,
lat:
!!item.access_lat && !!item.access_lng ? item.access_lat : item.lat,
lng:
!!item.access_lat && !!item.access_lng ? item.access_lng : item.lng,
}))
},
},
watch: {
selected: {
async handler() {
if (this.selected && Object.keys(this.selected).length > 0) {
this.computeSelectedFormattedFieldIfMissing()
} else {
this.$emit('input', {})
}
},
deep: true,
},
},
created() {
this.$store.dispatch('zones/syncClientZones', {
force: true,
})
},
methods: {
/**
* Will computed address reversing lat/lng
* @todo If access lat/lng gives nothing, try with zone center lat/lng
*/
async computeSelectedFormattedFieldIfMissing() {
if (!this.selected.formatted) {
this.$emit('input', {
...this.selected, //Select asap (UX++)
})
let response = (this.selectedReversed =
await this.$geocoding.reverseGeocoding(this.selected))
let formatted = (this.selected.formatted = getFormattedAddressAlt(
normalizeApiAddressResponse(response)
))
this.$set(this.selected, 'formatted', formatted)
if (!formatted) {
this.$set(
this.selected,
'formattedError',
this.$t(
'geocoding.routing.client_zone_select.reverse_address_fail',
{
zoneName: this.selected.name,
}
)
//`L'adresse n'a pas pu être récupérée (${this.selected.name})`
)
}
this.$emit('input', {
...this.selected,
formatted,
})
this.$refs.multiselect.$forceUpdate()
} else {
this.$emit('input', {
...this.selected,
})
}
},
},
}
</script>
Source