wip migration
This commit is contained in:
253
components/GoogleAddress.vue
Normal file
253
components/GoogleAddress.vue
Normal file
@@ -0,0 +1,253 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<label>{{ label }}</label>
|
||||
<p v-if="value && !place">{{ value }}</p>
|
||||
<p v-if="place">{{ place.address }}</p>
|
||||
<p v-show="error" class="error">{{ error }}</p>
|
||||
|
||||
<div class="input-and-btn">
|
||||
<button class="geo-btn" type="button" @click="getGeoLocation">
|
||||
<v-progress-circular
|
||||
v-if="loading"
|
||||
:size="15"
|
||||
:width="2"
|
||||
indeterminate
|
||||
/>
|
||||
<v-icon v-else small class="geo-icon"> mdi-crosshairs-gps </v-icon>
|
||||
</button>
|
||||
<input
|
||||
ref="googleMap"
|
||||
:required="!value"
|
||||
placeholder=""
|
||||
type="search"
|
||||
@focus="clear"
|
||||
/>
|
||||
|
||||
<!-- <button class="add-btn" type="button" @click="logPlace">Añadir</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Loader } from '@googlemaps/js-api-loader'
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
geo: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Dirección',
|
||||
},
|
||||
},
|
||||
emits: ['addedData'],
|
||||
data() {
|
||||
return {
|
||||
google: null,
|
||||
autocomplete: null,
|
||||
geocoder: null,
|
||||
place: null,
|
||||
error: null,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
const config = useRuntimeConfig()
|
||||
const apiKey = config.public.googleMapsApiKey
|
||||
if (!apiKey) {
|
||||
console.error('Google Maps API key is not defined in the runtime config.')
|
||||
return
|
||||
}
|
||||
const googleMapApi = new Loader({
|
||||
libraries: ['places'],
|
||||
apiKey: apiKey,
|
||||
})
|
||||
|
||||
try {
|
||||
await googleMapApi.load()
|
||||
await this.initializeMap()
|
||||
} catch (error) {
|
||||
console.error('Error loading Google Maps API:', error)
|
||||
this.error = 'Error al cargar el mapa de Google'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initializeMap() {
|
||||
const mapContainer = this.$refs.googleMap
|
||||
|
||||
if (!mapContainer || !window.google) {
|
||||
this.error = 'Google Maps no disponible'
|
||||
return
|
||||
}
|
||||
|
||||
this.autocomplete = new window.google.maps.places.PlaceAutocompleteElement(mapContainer)
|
||||
window.google.maps.event.addListener(this.autocomplete, 'place_changed', () => this.logPlace())
|
||||
this.geocoder = new window.google.maps.Geocoder()
|
||||
if (this.geo) {
|
||||
this.getGeoData(this.geo)
|
||||
}
|
||||
},
|
||||
|
||||
async getGeoLocation() {
|
||||
this.place = null
|
||||
this.error = null
|
||||
const geoLocation = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (!navigator.geolocation) {
|
||||
reject(new Error('Geolocalización no soportada'))
|
||||
return
|
||||
}
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(posData) => {
|
||||
resolve(posData)
|
||||
},
|
||||
(error) => {
|
||||
reject(error)
|
||||
}
|
||||
)
|
||||
} )
|
||||
try {
|
||||
this.loading = true
|
||||
const position = await geoLocation()
|
||||
const geo = {
|
||||
lat: position.coords.latitude,
|
||||
lng: position.coords.longitude,
|
||||
}
|
||||
this.getGeoData(geo)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
this.error = 'No se puede obtener la ubicación'
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
getGeoData(coordinates) {
|
||||
if (!this.geocoder) {
|
||||
this.error = 'Geocoder no inicializado'
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
|
||||
this.geocoder.geocode({ location: coordinates }, (result, status) => {
|
||||
if (status === 'OK') {
|
||||
const data = result[0]
|
||||
const address = data.formatted_address
|
||||
const geo = {
|
||||
latitude: Number(data.geometry.location.lat().toFixed(4)),
|
||||
longitude: Number(data.geometry.location.lng().toFixed(4)),
|
||||
}
|
||||
const city = data.address_components.find(
|
||||
(element) => element.types[0] === 'locality'
|
||||
).long_name || ''
|
||||
this.place = { address, geo, city }
|
||||
if (this.$refs.googleMap) {
|
||||
this.$refs.googleMap.value = this.place.address
|
||||
}
|
||||
this.$emit('addedData', this.place)
|
||||
this.loading = false
|
||||
} else {
|
||||
this.error = 'No se puede obtener la ubicación'
|
||||
this.loading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.place = null
|
||||
this.error = null
|
||||
this.$refs.googleMap.value = null
|
||||
this.$emit('addedData', this.place)
|
||||
},
|
||||
|
||||
async logPlace() {
|
||||
this.place = null
|
||||
this.error = null
|
||||
try {
|
||||
const googlePlace = await this.autocomplete.getPlace()
|
||||
console.log('Google Place:', googlePlace)
|
||||
const address = googlePlace.formatted_address
|
||||
const geo = {
|
||||
latitude: Number(googlePlace.geometry.location.lat().toFixed(4)),
|
||||
longitude: Number(googlePlace.geometry.location.lng().toFixed(4)),
|
||||
}
|
||||
const city =
|
||||
googlePlace.address_components.find(
|
||||
(element) => element.types[0] === 'locality'
|
||||
)?.long_name || ''
|
||||
this.place = { address, geo, city }
|
||||
this.$emit('addedData', this.place)
|
||||
} catch {
|
||||
this.place = null
|
||||
this.error = 'Debe introducir una dirección correcta'
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
label {
|
||||
text-align: left;
|
||||
color: $color-navy;
|
||||
font-weight: $bold;
|
||||
font-size: $xs;
|
||||
display: block;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
background-color: $color-grey-inputs;
|
||||
border: 1px solid $color-grey-inputs-border;
|
||||
border-radius: 4px;
|
||||
padding: 9px 5px;
|
||||
display: block;
|
||||
outline: none;
|
||||
font-size: $s;
|
||||
}
|
||||
|
||||
.input-and-btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
input {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
button {
|
||||
height: auto;
|
||||
background-color: $color-navy;
|
||||
color: $color-light;
|
||||
border: 1px solid $color-navy;
|
||||
border-radius: 5px;
|
||||
text-transform: uppercase;
|
||||
padding: 5px 5px;
|
||||
font-size: $xxs;
|
||||
|
||||
@include mobile {
|
||||
font-size: $xxs;
|
||||
}
|
||||
}
|
||||
.geo-btn {
|
||||
width: 10%;
|
||||
min-width: 30px;
|
||||
}
|
||||
// .add-btn {
|
||||
// width: 20%;
|
||||
// }
|
||||
}
|
||||
|
||||
.error {
|
||||
color: $color-error;
|
||||
}
|
||||
|
||||
.geo-icon {
|
||||
color: $color-light !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user