aboutsummaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
authorAriel Costas Guerrero <94913521+arielcostas@users.noreply.github.com>2025-03-04 00:51:42 +0100
committerAriel Costas Guerrero <94913521+arielcostas@users.noreply.github.com>2025-03-04 00:51:42 +0100
commit79f3c42b0c04c7fd77481c14e6e9c345677b8c42 (patch)
tree6022fdb9d4cad1a77bc98eea88ad29803290f67d /src/pages
parent0a96e26ade5d3eafe64807fcbd877742d6bcf6da (diff)
Add table layout like iTranvias, remake settings page
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/About.tsx45
-rw-r--r--src/pages/Estimates.tsx68
2 files changed, 43 insertions, 70 deletions
diff --git a/src/pages/About.tsx b/src/pages/About.tsx
index 918d484..7e1b0d3 100644
--- a/src/pages/About.tsx
+++ b/src/pages/About.tsx
@@ -1,8 +1,9 @@
-import { Moon, Sun } from "lucide-react";
-import { useTheme } from "../ThemeContext";
+import { List, Moon, Sun, Table, Table2, TableCellsMerge, TableColumnsSplit } from "lucide-react";
+import { useApp } from "../AppContext";
+import "../styles/About.css";
export function About() {
- const {theme, toggleTheme} = useTheme();
+ const { theme, setTheme, tableStyle, setTableStyle } = useApp();
return (
<div className="about-page">
@@ -11,12 +12,36 @@ export function About() {
Aplicación web para encontrar paradas y tiempos de llegada de los autobuses
urbanos de Vigo, España.
</p>
- <button className="form-button" onClick={toggleTheme}>
- {theme === 'light' ?
- <><Moon size={24} /> Usar modo oscuro</> :
- <><Sun size={24} /> Usar modo claro</>
- }
- </button>
+ <section className="settings-section">
+ <h2>Ajustes</h2>
+ <div className="settings-content-inline">
+ <label htmlFor="theme" className="form-label-inline">Modo:</label>
+ <select id="theme" className="form-select-inline" value={theme} onChange={(e) => setTheme(e.target.value)}>
+ <option value="light">Claro</option>
+ <option value="dark">Oscuro</option>
+ </select>
+ </div>
+ <div className="settings-content-inline">
+ <label htmlFor="tableStyle" className="form-label-inline">Estilo de tabla:</label>
+ <select id="tableStyle" className="form-select-inline" value={tableStyle} onChange={(e) => setTableStyle(e.target.value)}>
+ <option value="regular">Mostrar por orden</option>
+ <option value="grouped">Agrupar por línea</option>
+ </select>
+ </div>
+ <details className="form-details">
+ <summary>¿Qué significa esto?</summary>
+ <p>
+ La tabla de horarios puede mostrarse de dos formas:
+ </p>
+ <dl>
+ <dt>Mostrar por orden</dt>
+ <dd>Las paradas se muestran en el orden en que se visitan. Aplicaciones como Infobus (Vitrasa) usan este estilo.</dd>
+ <dt>Agrupar por línea</dt>
+ <dd>Las paradas se agrupan por la línea de autobús. Aplicaciones como iTranvias (A Coruña) o Moovit (más o menos) usan este estilo.</dd>
+ </dl>
+ </details>
+ </section>
+ <h2>Créditos</h2>
<p>
<a href="https://github.com/arielcostas/urbanovigo-web" className="about-link">
Código en GitHub
@@ -26,7 +51,7 @@ export function About() {
</a>
</p>
<p>
- Datos obtenidos de <a href="https://datos.vigo.org">datos.vigo.org</a> bajo
+ Datos obtenidos de <a href="https://datos.vigo.org">datos.vigo.org</a> bajo
licencia <a href="https://opendefinition.org/licenses/odc-by/">Open Data Commons Attribution License</a>
</p>
</div>
diff --git a/src/pages/Estimates.tsx b/src/pages/Estimates.tsx
index a445300..900ffc5 100644
--- a/src/pages/Estimates.tsx
+++ b/src/pages/Estimates.tsx
@@ -1,11 +1,13 @@
import { JSX, useEffect, useState } from "react";
import { useParams } from "react-router";
import { StopDataProvider } from "../data/StopDataProvider";
-import LineIcon from "../components/LineIcon";
import { Star } from 'lucide-react';
import "../styles/Estimates.css";
+import { RegularTable } from "../components/RegularTable";
+import { useApp } from "../AppContext";
+import { GroupedTable } from "../components/GroupedTable";
-interface StopDetails {
+export interface StopDetails {
stop: {
id: number;
name: string;
@@ -32,6 +34,7 @@ export function Estimates(): JSX.Element {
const [dataDate, setDataDate] = useState<Date | null>(null);
const [favourited, setFavourited] = useState(false);
const params = useParams();
+ const { tableStyle } = useApp();
useEffect(() => {
loadData(params.stopId!)
@@ -48,22 +51,6 @@ export function Estimates(): JSX.Element {
);
}, [params.stopId]);
- const absoluteArrivalTime = (minutes: number) => {
- const now = new Date()
- const arrival = new Date(now.getTime() + minutes * 60000)
- return Intl.DateTimeFormat(navigator.language, {
- hour: '2-digit',
- minute: '2-digit'
- }).format(arrival)
- }
-
- const formatDistance = (meters: number) => {
- if (meters > 1024) {
- return `${(meters / 1000).toFixed(1)} km`;
- } else {
- return `${meters} m`;
- }
- }
const toggleFavourite = () => {
if (favourited) {
@@ -87,48 +74,9 @@ export function Estimates(): JSX.Element {
</div>
<div className="table-responsive">
- <table className="table">
- <caption>Estimaciones de llegadas a las {dataDate?.toLocaleTimeString()}</caption>
-
- <thead>
- <tr>
- <th>Línea</th>
- <th>Ruta</th>
- <th>Minutos</th>
- <th>Metros</th>
- </tr>
- </thead>
-
- <tbody>
- {data.estimates
- .sort((a, b) => a.minutes - b.minutes)
- .map((estimate, idx) => (
- <tr key={idx}>
- <td><LineIcon line={estimate.line} /></td>
- <td>{estimate.route}</td>
- <td>
- {estimate.minutes > 15
- ? absoluteArrivalTime(estimate.minutes)
- : `${estimate.minutes} min`}
- </td>
- <td>
- {estimate.meters > -1
- ? formatDistance(estimate.meters)
- : "No disponible"
- }
- </td>
- </tr>
- ))}
- </tbody>
-
- {data?.estimates.length === 0 && (
- <tfoot>
- <tr>
- <td colSpan={4}>No hay estimaciones disponibles</td>
- </tr>
- </tfoot>
- )}
- </table>
+ {tableStyle === 'grouped' ?
+ <GroupedTable data={data} dataDate={dataDate} /> :
+ <RegularTable data={data} dataDate={dataDate} />}
</div>
</div>
)