2020-07-31 17:52:26 +02:00
|
|
|
<template>
|
2021-10-10 16:25:50 +02:00
|
|
|
<div class="address-autocomplete columns is-desktop">
|
|
|
|
<div class="column">
|
|
|
|
<b-field
|
|
|
|
:label-for="id"
|
2020-07-31 17:52:26 +02:00
|
|
|
expanded
|
2021-10-10 16:25:50 +02:00
|
|
|
:message="fieldErrors"
|
|
|
|
:type="{ 'is-danger': fieldErrors.length }"
|
2020-07-31 17:52:26 +02:00
|
|
|
>
|
2021-10-10 16:25:50 +02:00
|
|
|
<template slot="label">
|
|
|
|
{{ actualLabel }}
|
|
|
|
<span
|
|
|
|
class="is-size-6 has-text-weight-normal"
|
2021-11-08 18:46:04 +01:00
|
|
|
v-if="gettingLocation"
|
2021-10-10 16:25:50 +02:00
|
|
|
>{{ $t("Getting location") }}</span
|
|
|
|
>
|
2020-07-31 17:52:26 +02:00
|
|
|
</template>
|
2021-11-08 18:46:04 +01:00
|
|
|
<p class="control" v-if="canShowLocateMeButton && !gettingLocation">
|
|
|
|
<b-button
|
|
|
|
icon-right="map-marker"
|
|
|
|
@click="locateMe"
|
|
|
|
:title="$t('Use my location')"
|
|
|
|
/>
|
|
|
|
</p>
|
2021-10-10 16:25:50 +02:00
|
|
|
<b-autocomplete
|
|
|
|
:data="addressData"
|
|
|
|
v-model="queryText"
|
|
|
|
:placeholder="$t('e.g. 10 Rue Jangot')"
|
|
|
|
field="fullName"
|
|
|
|
:loading="isFetching"
|
|
|
|
@typing="fetchAsyncData"
|
2021-11-08 18:46:04 +01:00
|
|
|
:icon="canShowLocateMeButton ? null : 'map-marker'"
|
2021-10-10 16:25:50 +02:00
|
|
|
expanded
|
|
|
|
@select="updateSelected"
|
|
|
|
v-bind="$attrs"
|
|
|
|
:id="id"
|
2021-10-15 15:59:49 +02:00
|
|
|
:disabled="disabled"
|
2021-11-07 21:02:06 +01:00
|
|
|
dir="auto"
|
2021-10-10 16:25:50 +02:00
|
|
|
>
|
|
|
|
<template #default="{ option }">
|
|
|
|
<b-icon :icon="option.poiInfos.poiIcon.icon" />
|
|
|
|
<b>{{ option.poiInfos.name }}</b
|
|
|
|
><br />
|
|
|
|
<small>{{ option.poiInfos.alternativeName }}</small>
|
|
|
|
</template>
|
2021-11-06 10:08:20 +01:00
|
|
|
<template #empty>
|
2021-10-10 16:25:50 +02:00
|
|
|
<span v-if="isFetching">{{ $t("Searching…") }}</span>
|
|
|
|
<div v-else-if="queryText.length >= 3" class="is-enabled">
|
|
|
|
<span>{{
|
|
|
|
$t('No results for "{queryText}"', { queryText })
|
|
|
|
}}</span>
|
|
|
|
<span>{{
|
|
|
|
$t(
|
|
|
|
"You can try another search term or drag and drop the marker on the map",
|
|
|
|
{
|
|
|
|
queryText,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}}</span>
|
|
|
|
<!-- <p class="control" @click="openNewAddressModal">-->
|
|
|
|
<!-- <button type="button" class="button is-primary">{{ $t('Add') }}</button>-->
|
|
|
|
<!-- </p>-->
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</b-autocomplete>
|
|
|
|
<b-button
|
|
|
|
:disabled="!queryText"
|
|
|
|
@click="resetAddress"
|
|
|
|
class="reset-area"
|
|
|
|
icon-left="close"
|
|
|
|
:title="$t('Clear address field')"
|
|
|
|
/>
|
|
|
|
</b-field>
|
2021-11-08 18:46:04 +01:00
|
|
|
<div
|
|
|
|
class="card"
|
|
|
|
v-if="!hideSelected && (selected.originId || selected.url)"
|
|
|
|
>
|
2021-10-10 16:25:50 +02:00
|
|
|
<div class="card-content">
|
|
|
|
<address-info
|
|
|
|
:address="selected"
|
|
|
|
:show-icon="true"
|
|
|
|
:show-timezone="true"
|
|
|
|
:user-timezone="userTimezone"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
class="map column"
|
2021-11-06 10:08:20 +01:00
|
|
|
v-if="!hideMap && selected && selected.geom && selected.poiInfos"
|
2021-10-10 16:25:50 +02:00
|
|
|
>
|
2020-07-31 17:52:26 +02:00
|
|
|
<map-leaflet
|
|
|
|
:coords="selected.geom"
|
|
|
|
:marker="{
|
|
|
|
text: [selected.poiInfos.name, selected.poiInfos.alternativeName],
|
|
|
|
icon: selected.poiInfos.poiIcon.icon,
|
|
|
|
}"
|
|
|
|
:updateDraggableMarkerCallback="reverseGeoCode"
|
|
|
|
:options="{ zoom: mapDefaultZoom }"
|
|
|
|
:readOnly="false"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script lang="ts">
|
2021-09-07 17:40:31 +02:00
|
|
|
import { Component, Prop, Watch, Mixins } from "vue-property-decorator";
|
2020-07-31 17:52:26 +02:00
|
|
|
import { LatLng } from "leaflet";
|
|
|
|
import { Address, IAddress } from "../../types/address.model";
|
2021-09-07 17:40:31 +02:00
|
|
|
import AddressAutoCompleteMixin from "../../mixins/AddressAutoCompleteMixin";
|
2021-10-10 16:25:50 +02:00
|
|
|
import AddressInfo from "../../components/Address/AddressInfo.vue";
|
2020-07-31 17:52:26 +02:00
|
|
|
|
|
|
|
@Component({
|
2021-09-07 17:40:31 +02:00
|
|
|
inheritAttrs: false,
|
2021-10-10 16:25:50 +02:00
|
|
|
components: {
|
|
|
|
AddressInfo,
|
|
|
|
},
|
2020-07-31 17:52:26 +02:00
|
|
|
})
|
2021-09-07 17:40:31 +02:00
|
|
|
export default class FullAddressAutoComplete extends Mixins(
|
|
|
|
AddressAutoCompleteMixin
|
|
|
|
) {
|
2020-08-05 16:44:08 +02:00
|
|
|
@Prop({ required: false, default: "" }) label!: string;
|
2021-10-10 16:25:50 +02:00
|
|
|
@Prop({ required: false }) userTimezone!: string;
|
2021-10-15 15:59:49 +02:00
|
|
|
@Prop({ required: false, default: false, type: Boolean }) disabled!: boolean;
|
2021-11-06 10:08:20 +01:00
|
|
|
@Prop({ required: false, default: false, type: Boolean }) hideMap!: boolean;
|
2021-11-08 18:46:04 +01:00
|
|
|
@Prop({ required: false, default: false, type: Boolean })
|
|
|
|
hideSelected!: boolean;
|
2020-07-31 17:52:26 +02:00
|
|
|
|
|
|
|
addressModalActive = false;
|
|
|
|
|
2021-09-07 17:40:31 +02:00
|
|
|
private static componentId = 0;
|
2020-07-31 17:52:26 +02:00
|
|
|
|
2021-09-07 17:40:31 +02:00
|
|
|
created(): void {
|
|
|
|
FullAddressAutoComplete.componentId += 1;
|
2020-07-31 17:52:26 +02:00
|
|
|
}
|
|
|
|
|
2021-09-07 17:40:31 +02:00
|
|
|
get id(): string {
|
|
|
|
return `full-address-autocomplete-${FullAddressAutoComplete.componentId}`;
|
2020-07-31 17:52:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Watch("value")
|
2020-10-15 16:48:11 +02:00
|
|
|
updateEditing(): void {
|
2020-07-31 17:52:26 +02:00
|
|
|
if (!(this.value && this.value.id)) return;
|
|
|
|
this.selected = this.value;
|
|
|
|
}
|
|
|
|
|
2020-10-15 16:48:11 +02:00
|
|
|
updateSelected(option: IAddress): void {
|
2020-07-31 17:52:26 +02:00
|
|
|
if (option == null) return;
|
|
|
|
this.selected = option;
|
|
|
|
this.$emit("input", this.selected);
|
|
|
|
}
|
|
|
|
|
2020-10-15 16:48:11 +02:00
|
|
|
resetPopup(): void {
|
2020-07-31 17:52:26 +02:00
|
|
|
this.selected = new Address();
|
|
|
|
}
|
|
|
|
|
2020-10-15 16:48:11 +02:00
|
|
|
openNewAddressModal(): void {
|
2020-07-31 17:52:26 +02:00
|
|
|
this.resetPopup();
|
|
|
|
this.addressModalActive = true;
|
|
|
|
}
|
|
|
|
|
2020-10-15 16:48:11 +02:00
|
|
|
checkCurrentPosition(e: LatLng): boolean {
|
2020-07-31 17:52:26 +02:00
|
|
|
if (!this.selected || !this.selected.geom) return false;
|
|
|
|
const lat = parseFloat(this.selected.geom.split(";")[1]);
|
|
|
|
const lon = parseFloat(this.selected.geom.split(";")[0]);
|
|
|
|
|
|
|
|
return e.lat === lat && e.lng === lon;
|
|
|
|
}
|
|
|
|
|
2020-08-05 16:44:08 +02:00
|
|
|
get actualLabel(): string {
|
|
|
|
return this.label || (this.$t("Find an address") as string);
|
|
|
|
}
|
|
|
|
|
2020-10-15 16:48:11 +02:00
|
|
|
// eslint-disable-next-line class-methods-use-this
|
2020-08-05 16:44:08 +02:00
|
|
|
get canShowLocateMeButton(): boolean {
|
|
|
|
return window.isSecureContext;
|
|
|
|
}
|
2020-07-31 17:52:26 +02:00
|
|
|
}
|
|
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
|
|
.address-autocomplete {
|
|
|
|
margin-bottom: 0.75rem;
|
|
|
|
}
|
|
|
|
|
|
|
|
.autocomplete {
|
|
|
|
.dropdown-menu {
|
|
|
|
z-index: 2000;
|
|
|
|
}
|
|
|
|
|
|
|
|
.dropdown-item.is-disabled {
|
|
|
|
opacity: 1 !important;
|
|
|
|
cursor: auto;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.read-only {
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
.map {
|
|
|
|
height: 400px;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
</style>
|