Sistema_Gestion_Transporte/src/pages/mapas/Paraderos.svelte

198 lines
6.3 KiB
Svelte

<script>
// components
import PageTitle from "$/components/PageTitle.svelte"
import IconLoading from "$/components/IconLoading.svelte"
import FormParadero from "./FormParadero.svelte"
// services
import { getRegiones } from "$/services/regiones"
import { getComunas } from "$/services/comunas"
import { getMarcasParaderos } from "$/services/mapas"
// libs
import { onMount } from 'svelte'
import { storeParaderos } from "$/stores/global"
import imagenParada from '$/assets/parada-de-autobus.png'
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) return;
if (!L) L = globalThis.L;
if (!iconParada) {
iconParada = L.icon({
iconUrl: imagenParada,
iconSize: [64, 64],
iconAnchor: [32, 64],
popupAnchor: [0, -32]
})
}
if (!myMap) {
myMap = L.map(elMap)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{ attribution: '&copy; <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()
} catch (error) {
alert(error)
}
}
async function cargar_paraderos_todos(data_default) {
try {
loading = true
const paraderos = data_default || await getMarcasParaderos()
storeParaderos.set(paraderos)
} catch (error) {
alert(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)
}
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>
<FormParadero {parada} on:close={() => parada = null} />