forked from TDTP/admin_transporte_frontend
203 lines
6.5 KiB
Svelte
203 lines
6.5 KiB
Svelte
<script>
|
|
// components
|
|
import PageTitle from "$/components/PageTitle.svelte"
|
|
import IconLoading from "$/components/IconLoading.svelte"
|
|
import OffcanvasParadero from "./OffcanvasParadero.svelte"
|
|
|
|
// services
|
|
import { getRegiones } from "$/services/regiones"
|
|
import { getComunas } from "$/services/comunas"
|
|
import { getMarcasParaderos } from "$/services/mapas"
|
|
|
|
// libs
|
|
import { storeParaderos } from "$/stores/global"
|
|
import imagenParada from '$/assets/parada.png'
|
|
import { onMount } from "svelte";
|
|
|
|
let myMap = null
|
|
let elMap = null
|
|
let loading = false
|
|
let regiones = []
|
|
let comunas = []
|
|
let comunas_x_region = []
|
|
let L = null
|
|
let iconParada = null
|
|
let markers = []
|
|
let form = {}
|
|
let parada = null
|
|
|
|
cargar_regiones_comunas()
|
|
|
|
$: myMap && crear_marcadores_por_criterio()
|
|
|
|
onMount(() => {
|
|
if(globalThis.L) create_map();
|
|
cargar_paraderos_todos($storeParaderos)
|
|
})
|
|
|
|
function create_map() {
|
|
if (!elMap || !globalThis.L) return;
|
|
if (!L) L = globalThis.L;
|
|
if (!iconParada) {
|
|
iconParada = L.icon({
|
|
iconUrl: imagenParada,
|
|
iconSize: [32, 32],
|
|
iconAnchor: [16, 32],
|
|
popupAnchor: [0, -16]
|
|
})
|
|
}
|
|
if (!myMap) {
|
|
myMap = L.map(elMap)
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
|
{ attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' }
|
|
).addTo(myMap);
|
|
}
|
|
|
|
// obtener coordenadas actuales
|
|
// centrar mapa en coordenadas del navegador
|
|
navigator.geolocation.getCurrentPosition(
|
|
({ coords }) => {
|
|
const { latitude, longitude } = coords;
|
|
myMap.setView([latitude, longitude], 16)
|
|
},
|
|
(error) => console.log({ error })
|
|
)
|
|
}
|
|
|
|
|
|
async function cargar_regiones_comunas() {
|
|
try {
|
|
regiones = await getRegiones()
|
|
comunas = await getComunas({ ordering: 'nombre_comuna' })
|
|
} catch (error) {
|
|
globalThis.toast.error(error)
|
|
}
|
|
}
|
|
|
|
async function cargar_paraderos_todos(data_default) {
|
|
try {
|
|
loading = true
|
|
const paraderos = data_default || await getMarcasParaderos()
|
|
storeParaderos.set(paraderos)
|
|
} catch (error) {
|
|
globalThis.toast.error(error)
|
|
} finally {
|
|
loading = false
|
|
}
|
|
}
|
|
|
|
function crear_marcadores_por_criterio() {
|
|
if (form.id_region) {
|
|
comunas_x_region = comunas.filter(comuna => comuna.id_region === form.id_region)
|
|
} else {
|
|
form.id_comuna = null
|
|
comunas_x_region = []
|
|
}
|
|
|
|
if (!$storeParaderos?.marks) {
|
|
setTimeout(crear_marcadores_por_criterio, 1000)
|
|
return
|
|
}
|
|
// 1. eliminar los marcadores anteriores
|
|
markers.forEach(marker => marker.remove())
|
|
|
|
// 2. filtrar resultado de marcadores
|
|
const paraderos = $storeParaderos.marks.filter(m => {
|
|
// filtrar por comunas de la region
|
|
if (form.id_region && !form.id_comuna) {
|
|
const existe = comunas_x_region.findIndex(com => com.id_comuna === m.id_comuna) !== -1
|
|
if (!existe) return false
|
|
}
|
|
|
|
// filtrar por comuna seleccionada
|
|
if (form.id_comuna && m.id_comuna !== form.id_comuna) return false
|
|
|
|
// filtrar por texto de busqueda
|
|
if (form.search && m.location.toUpperCase().indexOf(form.search.toUpperCase()) === -1) return false
|
|
|
|
// filtro coincide a criterio
|
|
return true
|
|
})
|
|
|
|
// 3. crear marcadores
|
|
for (let mark of paraderos) {
|
|
const { lat, lng } = mark.position
|
|
const marker = L.marker([lat, lng], { icon: iconParada }).addTo(myMap)
|
|
const { title, location } = mark;
|
|
const html = `${title}<br>${location}`
|
|
|
|
marker.bindTooltip(html)
|
|
|
|
marker.on('click', function() {
|
|
parada = { ...mark }
|
|
})
|
|
markers.push(marker)
|
|
}
|
|
|
|
// 4. centrar mapa
|
|
if (myMap && paraderos.length) {
|
|
const { lat, lng } = paraderos[0].position
|
|
myMap.setView([ lat, lng ],16)
|
|
const bounds = myMap.getBounds()
|
|
paraderos.forEach(el => bounds.extend(el.position))
|
|
myMap.fitBounds(bounds)
|
|
}
|
|
}
|
|
|
|
|
|
function run_search_text() {
|
|
form.time_search && clearTimeout(form.time_search)
|
|
form.time_search = setTimeout(() => crear_marcadores_por_criterio(), 1000)
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" on:load={create_map}></script>
|
|
</svelte:head>
|
|
|
|
<div class="row">
|
|
<div class="col-md">
|
|
<PageTitle>
|
|
{#if loading}<IconLoading />{/if}
|
|
Paraderos
|
|
</PageTitle>
|
|
</div>
|
|
<div class="col-md-auto">
|
|
<div class="input-group mb-sm-3">
|
|
<div class="input-group-text">Región</div>
|
|
<select bind:value={form.id_region} class="form-select" on:change={crear_marcadores_por_criterio}>
|
|
<option value=""></option>
|
|
{#each regiones as r}
|
|
<option value={r.id_region}>{r.nombre_region}</option>
|
|
{/each}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-auto">
|
|
<div class="input-group mb-sm-3">
|
|
<div class="input-group-text">Comuna</div>
|
|
<select bind:value={form.id_comuna} class="form-select" on:change={crear_marcadores_por_criterio}>
|
|
<option value=""></option>
|
|
{#each comunas_x_region as c}
|
|
<option value={c.id_comuna}>{c.nombre_comuna}</option>
|
|
{/each}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-auto">
|
|
<div class="input-group mb-sm-3">
|
|
<input type="search" bind:value={form.search} class="form-control" on:input={run_search_text}>
|
|
<div class="input-group-text"><i class="bi bi-search"></i></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div bind:this={elMap} style="height: 100vh;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<OffcanvasParadero {parada} on:close={() => parada = null} />
|