166 lines
4.1 KiB
Vue
166 lines
4.1 KiB
Vue
<template>
|
|
<v-container v-if="settings && settings.address">
|
|
<v-sheet
|
|
class="store-location-section rounded-xl pa-6 pa-md-8"
|
|
elevation="2"
|
|
>
|
|
<div class="d-flex flex-column align-center text-center mb-4">
|
|
<div class="d-flex align-center mb-1">
|
|
<v-icon color="primary" size="36" class="mr-2">mdi-map-marker</v-icon>
|
|
<h2 class="text-h4 font-weight-bold mb-0">Visítanos</h2>
|
|
</div>
|
|
<p class="text-body-1 text-medium-emphasis mb-0">
|
|
Encuentra nuestra tienda física y adquiere nuestros productos
|
|
</p>
|
|
</div>
|
|
|
|
<div class="text-center mb-4">
|
|
<div class="d-flex align-center justify-center">
|
|
<v-icon color="red" class="mr-2">mdi-map-marker</v-icon>
|
|
<span class="text-h6 font-weight-medium">
|
|
{{ settings.address }}
|
|
</span>
|
|
</div>
|
|
<v-btn
|
|
v-if="hasCoordinates"
|
|
:href="directionsLink"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
color="primary"
|
|
variant="tonal"
|
|
size="small"
|
|
prepend-icon="mdi-directions"
|
|
class="mt-2"
|
|
>
|
|
Cómo llegar
|
|
</v-btn>
|
|
<v-btn
|
|
v-else
|
|
:href="searchLink"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
color="primary"
|
|
variant="tonal"
|
|
size="small"
|
|
prepend-icon="mdi-map-search"
|
|
class="mt-2"
|
|
>
|
|
Ver en el mapa
|
|
</v-btn>
|
|
</div>
|
|
|
|
<div v-if="hasCoordinates" ref="mapEl" class="map-wrapper"></div>
|
|
<v-alert v-else type="info" variant="tonal" class="ma-0">
|
|
La ubicación en el mapa aún no está configurada.
|
|
</v-alert>
|
|
</v-sheet>
|
|
</v-container>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, inject, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
|
import L from 'leaflet';
|
|
import 'leaflet/dist/leaflet.css';
|
|
|
|
const api = inject('api');
|
|
|
|
const settings = ref(null);
|
|
const mapEl = ref(null);
|
|
|
|
let map = null;
|
|
let marker = null;
|
|
|
|
const hasCoordinates = computed(
|
|
() =>
|
|
settings.value &&
|
|
settings.value.latitude != null &&
|
|
settings.value.longitude != null
|
|
);
|
|
|
|
const redPinIcon = L.divIcon({
|
|
className: 'store-map-pin',
|
|
html: '<i class="mdi mdi-map-marker" style="font-size:48px;line-height:1;color:#f44336;"></i>',
|
|
iconSize: [48, 48],
|
|
iconAnchor: [24, 48],
|
|
});
|
|
|
|
const directionsLink = computed(() => {
|
|
const lat = settings.value.latitude;
|
|
const lng = settings.value.longitude;
|
|
return `https://www.openstreetmap.org/?mlat=${lat}&mlon=${lng}#map=16/${lat}/${lng}`;
|
|
});
|
|
|
|
const searchLink = computed(
|
|
() =>
|
|
`https://www.openstreetmap.org/search?query=${encodeURIComponent(
|
|
settings.value.address
|
|
)}`
|
|
);
|
|
|
|
function initMap() {
|
|
if (!hasCoordinates.value || !mapEl.value || map) return;
|
|
|
|
const lat = settings.value.latitude;
|
|
const lng = settings.value.longitude;
|
|
|
|
map = L.map(mapEl.value, {
|
|
scrollWheelZoom: false,
|
|
}).setView([lat, lng], 16);
|
|
|
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
maxZoom: 19,
|
|
attribution:
|
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
|
}).addTo(map);
|
|
|
|
marker = L.marker([lat, lng], { icon: redPinIcon }).addTo(map);
|
|
marker.bindPopup(settings.value.address);
|
|
}
|
|
|
|
function handleResize() {
|
|
if (map) {
|
|
map.invalidateSize();
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
try {
|
|
settings.value = await api.getStoreSettings();
|
|
await nextTick();
|
|
initMap();
|
|
} catch (error) {
|
|
console.error('Error al cargar la información de la tienda:', error);
|
|
}
|
|
window.addEventListener('resize', handleResize);
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
window.removeEventListener('resize', handleResize);
|
|
if (map) {
|
|
map.remove();
|
|
map = null;
|
|
marker = null;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.store-location-section {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.map-wrapper {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 400px;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
z-index: 0;
|
|
}
|
|
|
|
.map-wrapper :deep(.leaflet-control-attribution) {
|
|
font-size: 10px;
|
|
}
|
|
</style>
|