avance ver buses y paraderos de ruta

develop/frontend
Francisco Sandoval 2023-11-26 20:05:39 -03:00
parent dd305eb15e
commit 9317ba8c54
8 changed files with 192 additions and 57 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,86 @@
<script>
import { getLineas } from "$/services/lineas";
import { getOperadores } from "$/services/operadores";
export let id_operador;
export let id_linea;
export let codigo;
export let ver_buses;
export let ver_paraderos;
let operadores = []
let lineas = []
let lineas_operador = []
getOperadores({ vigente: 1 })
.then(data => data.sort((a,b) => a.nombre_operador < b.nombre_operador? -1 : 1))
.then(data => operadores = data)
.catch(error => alert(error))
getLineas({ vigente: 1 })
.then(data => data.sort((a,b) => a.nombre_linea < b.nombre_linea? -1 : 1))
.then(data => lineas = data)
.catch(error => alert(error))
function onChangeOperador() {
id_linea = ''
ver_paraderos = false
ver_buses = false
if (!id_operador) {
lineas_operador = []
} else {
const lineas_filtradas = lineas.filter(el => el.id_operador === id_operador);
const lineas_ordenadas = lineas_filtradas.sort((a,b) => a.route_short_name < b.route_short_name ? -1 : 1);
lineas_operador = lineas_ordenadas;
}
}
function onChangeLinea() {
codigo = lineas.find(el => el.id_linea === id_linea)?.route_short_name || null
ver_paraderos = false
ver_buses = false
}
</script>
<div class="row">
<div class="col-md">
<div class="input-group mb-3">
<div class="input-group-text">Operador</div>
<select bind:value={id_operador} class="form-select" on:change={onChangeOperador}>
<option value=""></option>
{#each operadores as operador}
<option value={operador.id_operador}>{operador.nombre_operador}</option>
{/each}
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-text">Linea</div>
<select bind:value={id_linea} class="form-select" style="font-family: monospace;" on:change={onChangeLinea}>
<option value=""></option>
{#each lineas_operador as linea}
<option value={linea.id_linea}>{@html linea.route_short_name.padEnd(6).replace(/ /g,'&nbsp;')} {linea.route_long_name}</option>
{/each}
</select>
</div>
</div>
<div class="col-md-auto">
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="check-ver-buses-recorrido"
disabled={!id_linea}
bind:checked={ver_buses}>
<label class="form-check-label" for="check-ver-buses-recorrido">Ver Buses del Recorrido</label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="check-ver-paraderos"
disabled={!id_linea}
bind:checked={ver_paraderos}>
<label class="form-check-label" for="check-ver-paraderos">Ver Paraderos</label>
</div>
</div>
</div>

View File

@ -12,7 +12,7 @@
// libs
import { onMount } from 'svelte'
import { storeParaderos } from "$/stores/global"
import imagenParada from '$/assets/parada-de-autobus.png'
import imagenParada from '$/assets/parada.png'
let myMap = null
let elMap = null
@ -41,9 +41,9 @@
if (!iconParada) {
iconParada = L.icon({
iconUrl: imagenParada,
iconSize: [64, 64],
iconAnchor: [32, 64],
popupAnchor: [0, -32]
iconSize: [32, 32],
iconAnchor: [16, 32],
popupAnchor: [0, -16]
})
}
if (!myMap) {

View File

@ -2,54 +2,40 @@
// componentes
import PageTitle from "$/components/PageTitle.svelte";
import IconLoading from "$/components/IconLoading.svelte";
import imagenPartida from '$/assets/partida.png'
import imagenTermino from '$/assets/termino.png'
import imagenParada from '$/assets/parada.png'
import imagenAutobus from '$/assets/autobus.png'
import { onMount } from "svelte";
// servicios
import { getOperadores } from "$/services/operadores";
import { getLineas } from "$/services/lineas";
import { getRutas } from "$/services/mapas";
import ModalLetreroLUR from "./ModalLetreroLUR.svelte";
import FiltroRutas from "./FiltroRutas.svelte";
import { getBusesLinea, getParaderosLinea } from "$/services/lineas";
let myMap = null
let elMap = null
let operadores = []
let lineas = []
let lineas_operador = []
let id_operador = ''
let id_linea = ''
let loading = false
let polyline = null
let iconPartida = null
let iconTermino = null
let L = null
let iconParada = null
let L = null // leaflet.js
let marker1 = null
let marker2 = null
let showLetrero = false
let id_operador = ''
let id_linea = ''
let codigo = null
let ver_buses = false
let ver_paraderos = false
let markers = []
$: codigo = lineas.find(el => el.id_linea === id_linea)?.route_short_name || null
$: lineas_operador = id_operador ?
lineas.filter(el => el.id_operador === id_operador)
.sort((a,b) => a.route_short_name < b.route_short_name ? -1 : 1) : [];
getOperadores({ vigente: 1 })
.then(data => data.sort((a,b) => a.nombre_operador < b.nombre_operador? -1 : 1))
.then(data => operadores = data)
.catch(error => alert(error))
getLineas({ vigente: 1 })
.then(data => data.sort((a,b) => a.nombre_linea < b.nombre_linea? -1 : 1))
.then(data => lineas = data)
.catch(error => alert(error))
$: cargar_coordenadas(id_operador, id_linea)
onMount(() => {
create_map()
})
onMount(() => { create_map() })
function create_map() {
if (!elMap || !globalThis.L) return;
@ -66,10 +52,18 @@
iconTermino = L.icon({
iconUrl: imagenTermino,
iconSize: [64, 64],
iconAnchor: [32, 64],
iconAnchor: [0, 64],
popupAnchor: [0, -32]
})
}
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',
@ -88,8 +82,7 @@
)
}
async function cargar_coordenadas(id_operador, id_linea) {
async function onMostrarRuta(id_operador, id_linea) {
try {
loading = true
polyline && polyline.remove()
@ -105,7 +98,9 @@
if (coordenadas) {
marker1 = L.marker(coordenadas[0], { icon: iconPartida }).addTo(myMap)
marker1.bindTooltip('Inicio')
marker2 = L.marker(coordenadas[coordenadas.length -1], { icon: iconTermino }).addTo(myMap)
marker2.bindTooltip('Termino')
}
} catch (error) {
@ -114,6 +109,54 @@
loading = false;
}
}
async function onMostrarParaderos(ver_paraderos) {
// 1. eliminar marcadores anteriores
markers.forEach(marker => marker.remove())
if (!ver_paraderos || !id_linea) return;
const paraderos = await getParaderosLinea(id_linea)
// 2. crear marcadores
for (let mark of paraderos) {
const { stop_lat: lat, stop_lon: lng } = mark
const marker = L.marker([lat, lng], { icon: iconParada }).addTo(myMap)
const { id_paradero: title, stop_name: location } = mark;
const html = `${title}<br>${location}`
marker.bindTooltip(html)
markers.push(marker)
}
}
async function onMostrarBuses(ver_buses) {
// 1. eliminar marcadores anteriores
// markers.forEach(marker => marker.remove())
if (!ver_buses || !id_linea) return;
const buses = await getBusesLinea(id_linea)
console.log({ buses })
// 2. crear marcadores
// for (let mark of paraderos) {
// const { stop_lat: lat, stop_lon: lng } = mark
// const marker = L.marker([lat, lng], { icon: iconParada }).addTo(myMap)
// const { id_paradero: title, stop_name: location } = mark;
// const html = `${title}<br>${location}`
// marker.bindTooltip(html)
// markers.push(marker)
// }
}
$: onMostrarRuta(id_operador, id_linea)
$: onMostrarParaderos(ver_paraderos)
$: onMostrarBuses(ver_buses)
</script>
<svelte:head>
@ -123,37 +166,27 @@
<div class="row">
<div class="col-md">
<div class="col-md-auto">
<PageTitle {loading}>
Rutas
</PageTitle>
</div>
<div class="col-md-auto">
<div class="input-group">
<div class="input-group-text">Operador</div>
<select bind:value={id_operador} class="form-select" on:change={() => id_linea = ''}>
<option value=""></option>
{#each operadores as operador}
<option value={operador.id_operador}>{operador.nombre_operador}</option>
{/each}
</select>
<div class="input-group-text">Linea</div>
<select bind:value={id_linea} class="form-select" style="font-family: monospace;">
<option value=""></option>
{#each lineas_operador as linea}
<option value={linea.id_linea}>{@html linea.route_short_name.padEnd(6).replace(/ /g,'&nbsp;')} {linea.route_long_name}</option>
{/each}
</select>
</div>
<div class="col-md">
<FiltroRutas
bind:id_operador={id_operador}
bind:id_linea={id_linea}
bind:codigo={codigo}
bind:ver_buses={ver_buses}
bind:ver_paraderos={ver_paraderos}
/>
</div>
{#if id_operador && codigo}
<div class="col-auto">
<button class="btn btn-secondary"
on:click|preventDefault={() => showLetrero = true}
>Ver Letrero</button>
<button class="btn btn-secondary" on:click|preventDefault={() => showLetrero = true}>
Ver Letrero
</button>
</div>
{/if}
</div>

View File

@ -46,3 +46,19 @@ export async function deleteLinea(id) {
if (!res.ok) throw await res.text()
return res.json()
}
export async function getParaderosLinea(id_linea) {
const res = await fetch(`${base}/lineas/${id_linea}/paraderos`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function getBusesLinea(id_linea) {
const res = await fetch(`${base}/lineas/${id_linea}/buses`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}