magellan/src/components/Search.vue

120 lines
3.0 KiB
Vue

<template>
<div>
<span class="form">
<input type="text" placeholder="place" v-model="searchInput" @keydown="doSearch" />
<button @click="clearSearch()" :disabled="searchInput.length === 0">
<i class="fa fa-trash-alt"></i>
</button>
</span>
<p v-if="searchStatus">{{ searchStatus }}</p>
<ul class="results" v-if="results.length > 0">
<li
v-for="result in results"
@click="openPopup(result)"
>
<router-link :to="{ name: 'position', params: {
lat: result.coordinates[0],
lng: result.coordinates[1] } }">{{result.label}}</router-link>
<i class="fa fa-save" @click="save(result)"></i>
</li>
</ul>
<p v-if="searchInput.length > 0 && searchStatus === null && results.length == 0">
No results found.
</p>
</div>
</template>
<script>
import debounce from 'lodash.debounce';
import store from '../store';
const GEOCODING_URL = 'https://demo.addok.xyz/search/?q={query}&limit=20';
export default {
name: 'Menu',
data() {
return {
store,
searchInput: '',
searchStatus: null,
results: [],
}
},
methods: {
debouncedSearch: debounce(async function() {
if (this.searchInput.length === 0) {
// Just cleared the input.
this.searchStatus = null;
this.results = [];
return;
}
// Launch search.
this.searchStatus = "Searching...";
let resp = await fetch(GEOCODING_URL.replace('{query}', this.searchInput));
let results = await resp.json();
this.searchStatus = null;
this.results = (results && results.features && results.features.map(feature => {
let { properties: {label: label}, geometry: { coordinates: coordinates }} = feature;
coordinates.unshift(coordinates.pop());
return {label, coordinates}
})) || [];
}, 300),
doSearch() {
if (this.searchInput.length > 0) {
this.searchStatus = "Waiting for more characters...";
this.results = [];
}
this.debouncedSearch();
},
openPopup(loc) {
this.store.openPopup(loc.label, loc.coordinates[0], loc.coordinates[1]);
},
clearSearch() {
this.searchInput = '';
this.searchStatus = null;
this.results = [];
},
async save(loc) {
await store.addLocation(loc);
this.clearSearch();
}
}
}
</script>
<style scoped>
.form {
display: flex;
align-items: center;
}
input {
flex-grow: 2;
margin-left: 0;
margin-right: 5px;
}
button {
display: block;
padding: 10px;
background-color: white;
border: 0;
}
.fa-save, .fa-trash-alt {
cursor: pointer;
}
</style>