avance mejora parada
parent
ea07d6c579
commit
9958a53ebe
|
@ -0,0 +1,110 @@
|
||||||
|
<script>
|
||||||
|
// imagenes
|
||||||
|
import IconParada from "$/assets/parada-de-autobus.png";
|
||||||
|
// libs
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
import FormParadero from "./FormParadero.svelte";
|
||||||
|
import FormParaderoDispositivos from "./FormParaderoDispositivos.svelte";
|
||||||
|
import FormParaderoDetalle from "./FormParaderoDetalle.svelte";
|
||||||
|
import FormParaderoServicios from "./FormParaderoServicios.svelte";
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
export let parada = null;
|
||||||
|
let canvas = null;
|
||||||
|
let tab = 0;
|
||||||
|
|
||||||
|
$: init(!!parada);
|
||||||
|
|
||||||
|
function init(show) {
|
||||||
|
if (!canvas) return;
|
||||||
|
if (show) {
|
||||||
|
canvas.classList.add("show");
|
||||||
|
} else {
|
||||||
|
canvas.classList.remove("show");
|
||||||
|
tab = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="offcanvas offcanvas-end"
|
||||||
|
tabindex="-1"
|
||||||
|
bind:this={canvas}
|
||||||
|
aria-labelledby="offcanvasParaderoLabel"
|
||||||
|
style="visibility: inherit; --bs-offcanvas-width: 500px;"
|
||||||
|
>
|
||||||
|
<div class="offcanvas-header">
|
||||||
|
<h5 class="offcanvas-title text-info" id="offcanvasParaderoLabel">
|
||||||
|
<img src={IconParada} alt="Icono de Paradero" width="64" />
|
||||||
|
Paradero
|
||||||
|
</h5>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-close"
|
||||||
|
aria-label="Close"
|
||||||
|
on:click|preventDefault={() => dispatch("close")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="offcanvas-body">
|
||||||
|
<nav class="mb-3">
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class={"nav-link" + (tab === 0 ? ' active' : '')} href={"#"}
|
||||||
|
on:click|preventDefault={() => tab = 0}
|
||||||
|
>General</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class={"nav-link" + (tab === 1 ? ' active' : '')} href={"#"}
|
||||||
|
on:click|preventDefault={() => tab = 1}
|
||||||
|
>Dispositivos</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class={"nav-link" + (tab === 2 ? ' active' : '')} href={"#"}
|
||||||
|
on:click|preventDefault={() => tab = 2}
|
||||||
|
>Detalle</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class={"nav-link" + (tab === 3 ? ' active' : '')} href={"#"}
|
||||||
|
on:click|preventDefault={() => tab = 3}
|
||||||
|
>Servicios</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{#if tab === 0}
|
||||||
|
<FormParadero {parada} />
|
||||||
|
{/if}
|
||||||
|
{#if tab === 1}
|
||||||
|
<FormParaderoDispositivos {parada} />
|
||||||
|
{/if}
|
||||||
|
{#if tab === 2}
|
||||||
|
<FormParaderoDetalle {parada} />
|
||||||
|
{/if}
|
||||||
|
{#if tab === 3}
|
||||||
|
<FormParaderoServicios {parada} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if parada}
|
||||||
|
<div
|
||||||
|
class="offcanvas-backdrop fade show"
|
||||||
|
on:click|preventDefault={() => dispatch("close")}
|
||||||
|
on:keydown={() => {}}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if parada}
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
.seccion-imagen {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.seccion-imagen > a {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0.5rem;
|
||||||
|
right: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{/if}
|
|
@ -1,139 +1,134 @@
|
||||||
<script>
|
<script>
|
||||||
// imagenes
|
// imagenes
|
||||||
import IconParada from '$/assets/parada-de-autobus.png'
|
import IconParada from "$/assets/parada-de-autobus.png";
|
||||||
// servicios
|
// servicios
|
||||||
import { getParadero, updateParadero, getParaderoImagenes, createParaderoImagen, deleteParaderoImagen } from '$/services/paraderos'
|
import {
|
||||||
// libs
|
getParadero,
|
||||||
import { createEventDispatcher } from "svelte"
|
updateParadero,
|
||||||
const dispatch = createEventDispatcher()
|
getParaderoImagenes,
|
||||||
|
createParaderoImagen,
|
||||||
|
deleteParaderoImagen,
|
||||||
|
} from "$/services/paraderos";
|
||||||
|
|
||||||
export let parada = null
|
export let parada = null;
|
||||||
let canvas = null
|
let form = {};
|
||||||
let form = {}
|
let imagenes = [];
|
||||||
let imagenes = []
|
|
||||||
|
|
||||||
$: init(!!parada)
|
$: init(!!parada);
|
||||||
|
|
||||||
async function init(show) {
|
async function init(show) {
|
||||||
if (!canvas) return;
|
|
||||||
!show && canvas.classList.remove('show')
|
|
||||||
show && canvas.classList.add('show')
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (parada) {
|
if (parada) {
|
||||||
form = await getParadero(parada.id_paradero)
|
form = await getParadero(parada.id_paradero);
|
||||||
imagenes = await getParaderoImagenes(parada.id_paradero)
|
imagenes = await getParaderoImagenes(parada.id_paradero);
|
||||||
}
|
}
|
||||||
} catch(error) {
|
} catch (error) {
|
||||||
alert(error)
|
alert(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSave() {
|
async function onSave() {
|
||||||
try {
|
try {
|
||||||
await updateParadero(form)
|
await updateParadero(form);
|
||||||
alert('Información guardada')
|
alert("Información guardada");
|
||||||
} catch(error) {
|
} catch (error) {
|
||||||
alert(error)
|
alert(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSaveImagen({ target: form }) {
|
async function onSaveImagen({ target: form }) {
|
||||||
try {
|
try {
|
||||||
const [ file = null ] = form.file1.files;
|
const [file = null] = form.file1.files;
|
||||||
await createParaderoImagen(parada.id_paradero, file)
|
await createParaderoImagen(parada.id_paradero, file);
|
||||||
imagenes = await getParaderoImagenes(parada.id_paradero)
|
imagenes = await getParaderoImagenes(parada.id_paradero);
|
||||||
form.file1.value = ''
|
form.file1.value = "";
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error)
|
alert(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onDeleteImagen({ id_paradero_imagen }) {
|
async function onDeleteImagen({ id_paradero_imagen }) {
|
||||||
try {
|
try {
|
||||||
if (!confirm('Estás seguro de eliminar la imagen?')) return;
|
if (!confirm("Estás seguro de eliminar la imagen?")) return;
|
||||||
await deleteParaderoImagen(id_paradero_imagen)
|
await deleteParaderoImagen(id_paradero_imagen);
|
||||||
imagenes = imagenes.filter(imagen => imagen.id_paradero_imagen !== id_paradero_imagen)
|
imagenes = imagenes.filter(
|
||||||
|
(imagen) => imagen.id_paradero_imagen !== id_paradero_imagen
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error)
|
alert(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="offcanvas offcanvas-end" tabindex="-1" bind:this={canvas} aria-labelledby="offcanvasParaderoLabel" style="visibility: inherit;">
|
<div>
|
||||||
<div class="offcanvas-header">
|
Coordenadas:
|
||||||
<h5 class="offcanvas-title text-info" id="offcanvasParaderoLabel">
|
<div class="input-group mb-3">
|
||||||
<img src={IconParada} alt="Icono de Paradero" width="64">
|
<div class="input-group-text">Latitud</div>
|
||||||
Paradero
|
<div class="form-control">{form.stop_lat}</div>
|
||||||
</h5>
|
|
||||||
<button type="button" class="btn-close" aria-label="Close" on:click|preventDefault={() => dispatch('close')}></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="offcanvas-body">
|
<div class="input-group mb-3">
|
||||||
Coordenadas:
|
<div class="input-group-text">Longitud</div>
|
||||||
|
<div class="form-control">{form.stop_lon}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Propiedades:
|
||||||
|
<form on:submit|preventDefault={onSave}>
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<div class="input-group-text">Latitud</div>
|
<div class="input-group-text">Nombre</div>
|
||||||
<div class="form-control">{form.stop_lat}</div>
|
<input
|
||||||
|
type="text"
|
||||||
|
bind:value={form.stop_name}
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<div class="input-group-text">Longitud</div>
|
<div class="input-group-text">Descripción</div>
|
||||||
<div class="form-control">{form.stop_lon}</div>
|
<input
|
||||||
|
type="text"
|
||||||
|
bind:value={form.stop_desc}
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div class="text-center">
|
||||||
|
<button type="submit" class="btn btn-primary"
|
||||||
|
><i class="bi bi-save" /> Guardar</button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="my-3" />
|
||||||
|
|
||||||
Propiedades:
|
<!-- imagenes -->
|
||||||
<form on:submit|preventDefault={onSave}>
|
{#each imagenes as imagen}
|
||||||
<div class="input-group mb-3">
|
|
||||||
<div class="input-group-text">Nombre</div>
|
|
||||||
<input type="text" bind:value={form.stop_name} class="form-control">
|
|
||||||
</div>
|
|
||||||
<div class="input-group mb-3">
|
|
||||||
<div class="input-group-text">Descripción</div>
|
|
||||||
<input type="text" bind:value={form.stop_desc} class="form-control">
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<div class="text-center">
|
|
||||||
<button type="submit" class="btn btn-primary"><i class="bi bi-save"></i> Guardar</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div class="my-3"></div>
|
|
||||||
|
|
||||||
<!-- imagenes -->
|
|
||||||
{#each imagenes as imagen}
|
|
||||||
<div class="seccion-imagen mb-3">
|
<div class="seccion-imagen mb-3">
|
||||||
<img src={imagen.url} alt="imagen paradero" class="img-fluid">
|
<img src={imagen.url} alt="imagen paradero" class="img-fluid" />
|
||||||
<a href={"#"} class="btn btn-danger" on:click|preventDefault={() => onDeleteImagen(imagen)}>
|
<a
|
||||||
<i class="bi bi-trash"></i> Eliminar
|
href={"#"}
|
||||||
|
class="btn btn-danger"
|
||||||
|
on:click|preventDefault={() => onDeleteImagen(imagen)}
|
||||||
|
>
|
||||||
|
<i class="bi bi-trash" /> Eliminar
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<!-- agregar imagen -->
|
<!-- agregar imagen -->
|
||||||
<form action="" on:submit|preventDefault={onSaveImagen}>
|
<form action="" on:submit|preventDefault={onSaveImagen}>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="form-control" style="overflow: hidden">
|
<div class="form-control" style="overflow: hidden">
|
||||||
<input type="file" name="file1" accept="*.png,*.jpg,*.jpeg">
|
<input
|
||||||
</div>
|
type="file"
|
||||||
</div>
|
name="file1"
|
||||||
<div class="card-footer text-center">
|
accept="*.png,*.jpg,*.jpeg"
|
||||||
<button class="btn btn-primary" type="submit">
|
/>
|
||||||
<i class="bi bi-plus-lg"></i> Agregar imagen
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="card-footer text-center">
|
||||||
|
<button class="btn btn-primary" type="submit">
|
||||||
</div>
|
<i class="bi bi-plus-lg" /> Agregar imagen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if parada}
|
|
||||||
<div class="offcanvas-backdrop fade show" on:click|preventDefault={() => dispatch('close')}></div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
|
|
||||||
{#if parada}
|
|
||||||
<style>
|
|
||||||
html { overflow-y: hidden; }
|
|
||||||
.seccion-imagen { position: relative; }
|
|
||||||
.seccion-imagen > a { position: absolute; bottom: .5rem; right: .5rem; }
|
|
||||||
</style>
|
|
||||||
{/if}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<script>
|
||||||
|
import ModalParaderoDetalle from "./ModalParaderoDetalle.svelte";
|
||||||
|
|
||||||
|
export let parada = null
|
||||||
|
let showModal = false
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="mb-3">Detalle</h4>
|
||||||
|
<p> </p>
|
||||||
|
<p> </p>
|
||||||
|
<p> </p>
|
||||||
|
<div class="text-center">
|
||||||
|
<button class="btn btn-secondary"
|
||||||
|
on:click|preventDefault={() => showModal = true}
|
||||||
|
>Información</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if showModal}
|
||||||
|
<ModalParaderoDetalle {parada} on:close={() => showModal = false} />
|
||||||
|
{/if}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<script>
|
||||||
|
export let parada = null
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="mb-3">Dispositivos</h4>
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID Dipositivo</th>
|
||||||
|
<th>Tipo</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>AAAAAAAAAA</td>
|
||||||
|
<td>Panel Led</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>BBBBBBBBBB</td>
|
||||||
|
<td>Totem</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="text-center mb-3">
|
||||||
|
<img loading="lazy" width="300" height="300" src="https://gravatar.com/avatar/2db5ce9c15a9178854325b844485702b?s=400&d=wavatar&r=x" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<button class="btn btn-secondary">Imprimir QR</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<script>
|
||||||
|
export let parada = null
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="mb-3">Servicios</h4>
|
||||||
|
|
||||||
|
<div class="p-3 bg-white">
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item">Servicio 1</li>
|
||||||
|
<li class="list-group-item">Servicio 2</li>
|
||||||
|
<li class="list-group-item">Servicio 3</li>
|
||||||
|
<li class="list-group-item">Servicio 4</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script>
|
||||||
|
import Modal from "../../components/Modal.svelte";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
import TablaEditaParada from "../paraderos/TablaEditaParada.svelte";
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
export let parada = null
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal title="Detalle del Paradero" size="xl"
|
||||||
|
on:close={() => dispatch('close')}>
|
||||||
|
|
||||||
|
<TablaEditaParada {parada} />
|
||||||
|
</Modal>
|
|
@ -2,7 +2,7 @@
|
||||||
// components
|
// components
|
||||||
import PageTitle from "$/components/PageTitle.svelte"
|
import PageTitle from "$/components/PageTitle.svelte"
|
||||||
import IconLoading from "$/components/IconLoading.svelte"
|
import IconLoading from "$/components/IconLoading.svelte"
|
||||||
import FormParadero from "./FormParadero.svelte"
|
import CanvasParadero from "./CanvasParadero.svelte"
|
||||||
|
|
||||||
// services
|
// services
|
||||||
import { getRegiones } from "$/services/regiones"
|
import { getRegiones } from "$/services/regiones"
|
||||||
|
@ -195,4 +195,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormParadero {parada} on:close={() => parada = null} />
|
<CanvasParadero {parada} on:close={() => parada = null} />
|
|
@ -1,70 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import "./Home.css"
|
import "./Home.css"
|
||||||
|
import TablaEditaParada from "./TablaEditaParada.svelte";
|
||||||
let table = null
|
|
||||||
let data = [ {} ]
|
|
||||||
|
|
||||||
function onKeyDownCell(ev) {
|
|
||||||
if (ev.key === 'Escape') {
|
|
||||||
ev.target.blur()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ev.key === 'Enter') {
|
|
||||||
ev.returnValue = false;
|
|
||||||
const {nextElementSibling: nextTd} = ev.target;
|
|
||||||
if (nextTd && nextTd.contentEditable === 'true') {
|
|
||||||
nextTd.focus()
|
|
||||||
} else if (nextTd && nextTd.querySelector('input')) {
|
|
||||||
nextTd.querySelector('input').focus()
|
|
||||||
} else {
|
|
||||||
ev.target.blur()
|
|
||||||
const { cellIndex } = ev.target
|
|
||||||
const rowTable = ev.target.parentElement
|
|
||||||
if (rowTable.children.length === cellIndex + 1) {
|
|
||||||
data = [ ...data, {}]
|
|
||||||
setTimeout(() => {
|
|
||||||
table.querySelector('tbody > tr:last-child > td').focus()
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ev.key === 'ArrowDown') {
|
|
||||||
const { cellIndex } = ev.target
|
|
||||||
const { rowIndex } = ev.target.parentElement
|
|
||||||
const rowTable = table.querySelectorAll('tbody tr')[rowIndex] || null
|
|
||||||
if (rowTable) {
|
|
||||||
ev.target.blur()
|
|
||||||
const cellTable = rowTable.querySelectorAll('td')[cellIndex]
|
|
||||||
cellTable.focus()
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ev.key === 'ArrowUp') {
|
|
||||||
const { cellIndex } = ev.target
|
|
||||||
const { rowIndex } = ev.target.parentElement
|
|
||||||
const rowTable = table.querySelectorAll('tbody tr')[rowIndex - 2] || null
|
|
||||||
if (rowTable) {
|
|
||||||
ev.target.blur()
|
|
||||||
const cellTable = rowTable.querySelectorAll('td')[cellIndex]
|
|
||||||
cellTable.focus()
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onKeyDownInput(ev) {
|
|
||||||
if (ev.key === 'Enter') {
|
|
||||||
ev.returnValue = false;
|
|
||||||
const {nextElementSibling: nextTd} = ev.target.parentElement;
|
|
||||||
if (nextTd && nextTd.contentEditable === 'true') {
|
|
||||||
nextTd.focus()
|
|
||||||
} else if (nextTd.querySelector('input')) {
|
|
||||||
nextTd.querySelector('input').focus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,51 +9,7 @@
|
||||||
<button class="btn btn-primary"><i class="bi bi-save"></i> Guardar</button>
|
<button class="btn btn-primary"><i class="bi bi-save"></i> Guardar</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<TablaEditaParada parada={null} />
|
||||||
<table class="table table-hover table-bordered table-paraderos" bind:this={table}>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Instalación</th>
|
|
||||||
<th>Secuencia</th>
|
|
||||||
<th>Comuna</th>
|
|
||||||
<th>Eje</th>
|
|
||||||
<th>Cod. Eje</th>
|
|
||||||
<th>Desde</th>
|
|
||||||
<th>Hasta</th>
|
|
||||||
<th>Uso Parada</th>
|
|
||||||
<th>Sentido</th>
|
|
||||||
<th>Tipo Parada</th>
|
|
||||||
<th>Nombre Corredor</th>
|
|
||||||
<th>Refugio</th>
|
|
||||||
<th>Categoría</th>
|
|
||||||
<th>Nombre Parada</th>
|
|
||||||
<th>Referencia Urbana</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{#each data as item}
|
|
||||||
<tr>
|
|
||||||
<td contenteditable data-name="instalacion" bind:innerText={item.instalacion} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable data-name="secuencia" bind:innerText={item.secuencia} on:keydown={onKeyDownCell}></td>
|
|
||||||
<!-- <td contenteditable bind:innerText={item.comuna} on:keydown={onKeyDownCell}></td> -->
|
|
||||||
<td><input type="text" list="ex1" class="form-select" on:keydown={onKeyDownInput}></td>
|
|
||||||
<td contenteditable bind:innerText={item.eje} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.codigo_eje} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.desde} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.hasta} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.uso_parada} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.sentido} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.tipo_parada} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.nombre_corredor} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.refugio} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.categoria} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.nombre_parada} on:keydown={onKeyDownCell}></td>
|
|
||||||
<td contenteditable bind:innerText={item.referencia_urbana} on:keydown={onKeyDownCell}></td>
|
|
||||||
</tr>
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer"></div>
|
<div class="card-footer"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
<script>
|
||||||
|
export let parada = null;
|
||||||
|
let table = null;
|
||||||
|
let data = [{}];
|
||||||
|
|
||||||
|
function onKeyDownCell(ev) {
|
||||||
|
if (ev.key === "Escape") {
|
||||||
|
ev.target.blur();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ev.key === "Enter") {
|
||||||
|
ev.returnValue = false;
|
||||||
|
const { nextElementSibling: nextTd } = ev.target;
|
||||||
|
if (nextTd && nextTd.contentEditable === "true") {
|
||||||
|
nextTd.focus();
|
||||||
|
} else if (nextTd && nextTd.querySelector("input")) {
|
||||||
|
nextTd.querySelector("input").focus();
|
||||||
|
} else {
|
||||||
|
ev.target.blur();
|
||||||
|
const { cellIndex } = ev.target;
|
||||||
|
const rowTable = ev.target.parentElement;
|
||||||
|
if (rowTable.children.length === cellIndex + 1) {
|
||||||
|
data = [...data, {}];
|
||||||
|
setTimeout(() => {
|
||||||
|
table
|
||||||
|
.querySelector("tbody > tr:last-child > td")
|
||||||
|
.focus();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ev.key === "ArrowDown") {
|
||||||
|
const { cellIndex } = ev.target;
|
||||||
|
const { rowIndex } = ev.target.parentElement;
|
||||||
|
const rowTable =
|
||||||
|
table.querySelectorAll("tbody tr")[rowIndex] || null;
|
||||||
|
if (rowTable) {
|
||||||
|
ev.target.blur();
|
||||||
|
const cellTable = rowTable.querySelectorAll("td")[cellIndex];
|
||||||
|
cellTable.focus();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ev.key === "ArrowUp") {
|
||||||
|
const { cellIndex } = ev.target;
|
||||||
|
const { rowIndex } = ev.target.parentElement;
|
||||||
|
const rowTable =
|
||||||
|
table.querySelectorAll("tbody tr")[rowIndex - 2] || null;
|
||||||
|
if (rowTable) {
|
||||||
|
ev.target.blur();
|
||||||
|
const cellTable = rowTable.querySelectorAll("td")[cellIndex];
|
||||||
|
cellTable.focus();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeyDownInput(ev) {
|
||||||
|
if (ev.key === "Enter") {
|
||||||
|
ev.returnValue = false;
|
||||||
|
const { nextElementSibling: nextTd } = ev.target.parentElement;
|
||||||
|
if (nextTd && nextTd.contentEditable === "true") {
|
||||||
|
nextTd.focus();
|
||||||
|
} else if (nextTd.querySelector("input")) {
|
||||||
|
nextTd.querySelector("input").focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table
|
||||||
|
class="table table-hover table-bordered table-paraderos"
|
||||||
|
bind:this={table}
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Instalación</th>
|
||||||
|
<th>Secuencia</th>
|
||||||
|
<th>Comuna</th>
|
||||||
|
<th>Eje</th>
|
||||||
|
<th>Cod. Eje</th>
|
||||||
|
<th>Desde</th>
|
||||||
|
<th>Hasta</th>
|
||||||
|
<th>Uso Parada</th>
|
||||||
|
<th>Sentido</th>
|
||||||
|
<th>Tipo Parada</th>
|
||||||
|
<th>Nombre Corredor</th>
|
||||||
|
<th>Refugio</th>
|
||||||
|
<th>Categoría</th>
|
||||||
|
<th>Nombre Parada</th>
|
||||||
|
<th>Referencia Urbana</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each data as item}
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
data-name="instalacion"
|
||||||
|
bind:innerText={item.instalacion}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
data-name="secuencia"
|
||||||
|
bind:innerText={item.secuencia}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<!-- <td contenteditable bind:innerText={item.comuna} on:keydown={onKeyDownCell}></td> -->
|
||||||
|
<td
|
||||||
|
><input
|
||||||
|
type="text"
|
||||||
|
list="ex1"
|
||||||
|
class="form-select"
|
||||||
|
on:keydown={onKeyDownInput}
|
||||||
|
/></td
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.eje}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.codigo_eje}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.desde}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.hasta}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.uso_parada}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.sentido}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.tipo_parada}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.nombre_corredor}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.refugio}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.categoria}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.nombre_parada}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
<td
|
||||||
|
contenteditable
|
||||||
|
bind:innerText={item.referencia_urbana}
|
||||||
|
on:keydown={onKeyDownCell}
|
||||||
|
/>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
Loading…
Reference in New Issue