se integra paradero a cms

master
Francisco Sandoval 2024-03-13 21:15:21 -03:00
parent 92e485c60d
commit 975b9603d8
6 changed files with 274 additions and 104 deletions

View File

@ -2,8 +2,8 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" href="https://www.mtt.gob.cl/wp-content/themes/mtt/images/favicon.ico" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -1,102 +0,0 @@
<script>
import { spring } from 'svelte/motion';
let count = 0;
const displayed_count = spring();
$: displayed_count.set(count);
$: offset = modulo($displayed_count, 1);
function modulo(n, m) {
// handle negative numbers
return ((n % m) + m) % m;
}
</script>
<div class="counter">
<button on:click={() => (count -= 1)} aria-label="Decrease the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5" />
</svg>
</button>
<div class="counter-viewport">
<div class="counter-digits" style="transform: translate(0, {100 * offset}%)">
<strong class="hidden" aria-hidden="true">{Math.floor($displayed_count + 1)}</strong>
<strong>{Math.floor($displayed_count)}</strong>
</div>
</div>
<button on:click={() => (count += 1)} aria-label="Increase the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
</svg>
</button>
</div>
<style>
.counter {
display: flex;
border-top: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
margin: 1rem 0;
}
.counter button {
width: 2em;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
border: 0;
background-color: transparent;
touch-action: manipulation;
font-size: 2rem;
}
.counter button:hover {
background-color: var(--color-bg-1);
}
svg {
width: 25%;
height: 25%;
}
path {
vector-effect: non-scaling-stroke;
stroke-width: 2px;
stroke: #444;
}
.counter-viewport {
width: 8em;
height: 4em;
overflow: hidden;
text-align: center;
position: relative;
}
.counter-viewport strong {
position: absolute;
display: flex;
width: 100%;
height: 100%;
font-weight: 400;
color: var(--color-theme-1);
font-size: 4rem;
align-items: center;
justify-content: center;
}
.counter-digits {
position: absolute;
width: 100%;
height: 100%;
}
.hidden {
top: -100%;
user-select: none;
}
</style>

View File

@ -4,7 +4,7 @@
<div class="bg-dark text-light py-2 sticky-top">
<div class="container">
<a href={base}>Inicio</a>
<a href={`${base}/`}>Inicio</a>
</div>
</div>

View File

@ -0,0 +1,54 @@
const base = 'https://transporte.hz.kursor.cl/api'
export async function load({ url }) {
const id = url.searchParams.get('id');
if (!id) return null;
const token = await getToken()
return await fetchParaderoData(id, token)
}
async function getToken() {
try {
const rut = '11111111-1'
const password = 'usuario1'
const res = await fetch(`${base}/auth/`, {
method: 'POST',
body: JSON.stringify({ rut, password })
})
if (!res.ok) throw await res.text()
const { token } = await res.json()
// console.log({ token })
return token;
} catch (error) {
console.log('token',{ error })
}
}
async function fetchParaderoData(id, token) {
try {
const data = {
GetInfoDevice: {
idDispositivo: id,
KeyAuthorizacion: "token"
}
}
const res = await fetch(`${base}/dispositivos/getInfoDevice/`, {
method: 'POST',
body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
} catch (error) {
console.log('paradero',{ error })
}
}

View File

@ -0,0 +1,218 @@
<script>
import ImagenBus from "$lib/images/logo-autobus.png";
export let data;
const { NombreParadero: nombreParadero = null, ...paraderoData } = data?.GetInfoDeviceResponse || {};
const colores = [
"#5fbabe",
"#f05eb1",
"#5fab88",
"#f7646c",
"#5e66b5",
"#73776e",
];
function getColorAleatorio(index) {
return colores[index % 6];
}
function formatTimeMinutes({ EstimadaGPS: horaPlanificada, patente }) {
// const diferenciaMinutos = calcularDiferenciaMinutos(horaPlanificada);
const horaActual = new Date();
const horaUtc = horaActual.toISOString().substring(0, 10) + "T" + horaPlanificada + "Z";
const horaTrayecto = new Date(horaUtc);
const diferenciaMinutos = (horaTrayecto.getTime() - horaActual.getTime()) / (1000 * 60);
if (diferenciaMinutos <= 3) {
return "< a 3 Minutos";
} else if (diferenciaMinutos <= 5) {
return "3-5 Minutos";
} else if (diferenciaMinutos <= 10) {
return "Menos de 10 minutos";
} else {
return "Más de 10 minutos";
}
}
function LetraoNumeroMicro(cadena, flag) {
if (!cadena || (flag !== 0 && flag !== 1)) {
return "Error: Entrada no válida";
}
// Extraer el número y la letra
let numero = "";
let letra = "";
let i = 0;
// Caso en el que la cadena tenga un numero primero
if (!isNaN(parseInt(cadena[i]))) {
// Obtener el número
while (i < cadena.length && !isNaN(parseInt(cadena[i]))) {
numero += cadena[i];
i++;
}
// Obtener la letra (si hay)
while (i < cadena.length) {
letra += cadena[i];
i++;
}
if (flag === 0) {
return numero ? numero : "Error: No se encontró un número";
} else if (flag === 1) {
return letra ? letra : "Error: No se encontró una letra";
}
} else {
// Obtener la letra (si hay)
while (i < cadena.length && isNaN(parseInt(cadena[i]))) {
letra += cadena[i];
i++;
}
// Obtener el número
while (i < cadena.length) {
numero += cadena[i];
i++;
}
if (flag === 1) {
return numero ? numero : "Error: No se encontró un número";
} else if (flag === 0) {
return letra ? letra : "Error: No se encontró una letra";
}
}
}
</script>
<svelte:head>
<title>Transformación digital: Paradero</title>
<meta
name="description"
content="TRANSFORMACIÓN DIGITAL DEL TRANSPORTE EN GRAN CONCEPCIÓN"
/>
</svelte:head>
<div class="contenedor">
<div class="rectangulo-naranja">
<img src={ImagenBus} alt="Bus" width="200" />
<div class="nombre-paradero">{nombreParadero}</div>
</div>
<div class="rectangulo-gris">Buses que se detienen en esta parada</div>
<div class="cuadricula">
{#if paraderoData?.DetalleLineas}
{#each paraderoData.DetalleLineas as linea}
<div class="rectangulo-pequeno">
<div style="position: relative;">
<div class="numero-micro">
{LetraoNumeroMicro(linea.Descripcion, 0)}
</div>
<div
class="circulo-letra"
style="background-color: #{linea.colorFondo ||
'#5fbabe'}"
>
{LetraoNumeroMicro(linea.Descripcion, 1)}
</div>
</div>
<div
class="hora"
style="background-color: #{linea.colorFondo ||
'#5fbabe'}"
>
<div>{linea.Linea}</div>
{#if linea.Llegadas[0]?.EstimadaGPS}
{formatTimeMinutes(linea.Llegadas[0])}
({linea.Llegadas[0].patente})
{:else}
Sin información
{/if}
</div>
</div>
{/each}
{:else}
<p>Cargando datos...</p>
{/if}
</div>
</div>
<style>
/* Estilos generales */
.contenedor {
width: 800px;
margin: 5rem auto; /* Centra el contenedor en la pantalla */
}
.rectangulo-naranja {
background-color: #ffa976;
border-radius: 20px 20px 0 0;
padding: 20px;
display: flex;
align-items: center;
}
.nombre-paradero {
font-size: 28px;
font-weight: bold;
color: #fff;
margin-right: 10px;
margin-left: 120px;
}
.rectangulo-gris {
background-color: #8c8b8d;
padding-left: 20px;
color: #fff;
}
.cuadricula {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 5px;
margin-top: 10px;
}
.rectangulo-pequeno {
position: relative;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
min-height: 120px;
border: 1px solid #000000;
overflow: hidden;
}
.numero-micro {
font-size: 60px;
font-weight: bold;
margin-right: 100px;
color: #8c8b8d;
}
.circulo-letra {
width: 45px;
height: 45px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
color: #fff;
position: absolute;
top: 25px;
right: 10px;
}
.hora {
margin-top: 5px;
background-color: #2196f3;
color: #fff;
width: 266px;
}
</style>