This commit is contained in:
Michal Kváček
2025-09-18 22:04:37 +02:00
parent 018153aff1
commit 448d97e310
7 changed files with 112 additions and 56 deletions
@@ -29,13 +29,18 @@ const placesFilter = (val, update, abort) => {
searchGeocode(val).then(results => {
if (!results) return;
placesOptions.value = results.map(result => ({
console.log(results)
placesOptions.value = results.map(result => {
console.log(result, result.geometry.location)
return {
name: result.formatted_address,
type: "geocode",
id: null,
gpsLatitude: result.geometry.location.lat,
gpsLongitude: result.geometry.location.lng,
}))
gpsLatitude: result.geometry.location.lat(),
gpsLongitude: result.geometry.location.lng(),
}
})
});
}
} else {
@@ -31,6 +31,9 @@ const swapMarkers = (idx1, idx2) => {
};
const handlePlaceSelect = (modelVal) => {
model.value.push(modelVal);
// TODO: upravit bounds u mapy
}
watch(() => model.value, () => {
+22 -10
View File
@@ -1,6 +1,6 @@
<script setup>
import {Marker} from "vue3-google-map";
import {onMounted, ref} from "vue";
import {onMounted, ref, watch} from "vue";
import MapWrapper from "components/map/MapWrapper.vue";
import {useGeocode} from "src/composables/geocoding";
import axios from "axios";
@@ -32,22 +32,34 @@ const markerDropped = (position) => {
}
const zoom = ref(8);
onMounted(() => {
if (props.gpsLatitude && props.gpsLongitude) {
center.value.lng = props.gpsLongitude;
center.value.lat = props.gpsLatitude
} else if (props.label) {
searchGeocode(props.label).then(results => {
watch(() => [props.label, props.gpsLongitude, props.gpsLatitude], (val, oldValue) => {
const [newAddress, newLon, newLat] = val
const [previousAddress, oldLon, oldLat] = oldValue
if (newAddress) {
if (newAddress === previousAddress) return
searchGeocode(newAddress).then(results => {
if (!results) return;
center.value = results[0].geometry.location;
const lat = results[0].geometry.location.lat()
const lng = results[0].geometry.location.lng()
center.value = {lng, lat}
emitModels(center.value.lat, center.value.lng);
zoom.value = 13;
});
} else if (newLat && newLon && (props.gpsLatitude !== newLat || props.gpsLongitude !== newLon)) {
center.value.lng = newLon;
center.value.lat = newLat
} else {
console.log(newAddress, newLon, newLat, props.label, props.gpsLongitude, props.gpsLatitude)
console.error("Set either label or gps coordinates.");
}
})
},
// {immediate: true}
)
</script>
<template>
+5
View File
@@ -241,6 +241,11 @@ const isControlsOpened = ref(false);
</script>
<template>
<!-- <q-banner>-->
<!-- https://dev.to/quasar/how-to-use-google-maps-in-a-quasar-project-1c13-->
<!-- </q-banner>-->
<GoogleMap
:api-key="key"
v-bind="$attrs"
+12 -11
View File
@@ -74,9 +74,18 @@ const handlePositionNotFound = () => {
<template #append v-if="showResetMapButton">
<q-btn @click="resetMap" icon="gps_fixed" round flat text-color="green" title="Nastav pozici na mapě"/>
</template>
<template #after>
<q-checkbox v-model="formData.isPublic" label="Veřejný?"/>
</template>
</q-input>
<ComboboxInput v-model="formData.type" :options="types" label="Kategorie" v-bind="commonProps"/>
<MapGPSInput
:label="poiNameForMap"
:zoom="zoom"
v-model:gpsLatitude="formData.gpsLatitude"
v-model:gpsLongitude="formData.gpsLongitude"
@not-found="handlePositionNotFound"
/>
<SlugInput
v-if="formData.isPublic"
v-bind="commonProps"
@@ -86,17 +95,9 @@ const handlePositionNotFound = () => {
:slug-source="formData.name"
:rules="rules.urlSlug"
/>
<q-checkbox v-model="formData.isPublic" label="Veřejný?"/>
<MapGPSInput
v-if="poiNameForMap"
:key="poiNameForMap"
:label="poiNameForMap"
:zoom="zoom"
v-model:gpsLatitude="formData.gpsLatitude"
v-model:gpsLongitude="formData.gpsLongitude"
@not-found="handlePositionNotFound"
/>
<ComboboxInput v-model="formData.type" :options="types" label="Kategorie" v-bind="commonProps"/>
<q-input type="textarea" v-model="formData.description" v-bind="commonProps" label="Popis"/>
+47 -17
View File
@@ -1,28 +1,54 @@
import {ref} from "vue";
import axios from "axios";
export const useGeocode = () => {
const center = ref({lat: 50.1314, lng: 14.5256});
const getGeocoder = (limitMs = 5000) => {
let interval = null
const poolingWindowMs = 100
const searchGeocode = (address) => {
return axios.get(`https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURI(address)}&key=${process.env.GOOGLE_MAPS_API_KEY}`).then(response => {
if (response.data.status !== 'OK') {
return null;
const tries = limitMs / poolingWindowMs
let currentTry = 0
return new Promise((resolve, reject) => {
let instance = null
interval = setInterval(() => {
try {
instance = new google.maps.Geocoder()
clearInterval(interval)
return resolve(instance)
} catch (e) {
if (++currentTry >= tries) {
clearInterval(interval)
return reject(instance)
}
}
}, poolingWindowMs)
})
}
return response.data.results;
});
}
const searchGeocode = (address) => new Promise((resolve, reject) => {
getGeocoder().then(geocoder => geocoder
.geocode({address})
.then(({results}) => resolve(results))
.catch((e) => reject(e))).catch(() => {
console.log("Cannot get geocoder")
})
})
const searchPlaceName = (lat, lng) => {
return axios.get(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${process.env.GOOGLE_MAPS_API_KEY}`).then(response => {
if (response.data.status !== 'OK' || !response.data.results?.length) {
return null;
}
const latlng = {
lat: parseFloat(lat), lng: parseFloat(lng),
};
const results = response.data.results;
return new Promise((resolve, reject) => {
getGeocoder().then((geocoder) => geocoder
.geocode({location: latlng})
.then((response) => {
const results = response.results;
const components = {};
for (const addressComponent of results[0].address_components) {
for (const namePartType of ["locality", "postal_town", 'administrative_area_level_2']) {
@@ -33,11 +59,15 @@ export const useGeocode = () => {
}
if (!Object.keys(components).length) {
return "Bod na mapě";
return resolve("Bod na mapě");
}
return Object.values(components).join(", ");
});
return resolve(Object.values(components).join(", "));
})
.catch((e) => reject(e))
)
})
}
return {center, searchGeocode, searchPlaceName}
+1 -1
View File
@@ -7,7 +7,7 @@ import {FRAGMENT_COPILOT_PUBLIC_INFO} from "src/graphql/fragments/copilot";
export const FRAGMENT_WEATHER_FULL_INFO = gql`
fragment weatherFullInfo on WeatherInfo {
datetime
dateTime
qnh
temperatureSurface
dewpointSurface