aboutsummaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/Settings.tsx23
-rw-r--r--src/pages/StopList.tsx51
2 files changed, 48 insertions, 26 deletions
diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx
index e4a1a31..1ad15ab 100644
--- a/src/pages/Settings.tsx
+++ b/src/pages/Settings.tsx
@@ -2,7 +2,7 @@ import { useApp } from "../AppContext";
import "../styles/Settings.css";
export function Settings() {
- const { theme, setTheme, tableStyle, setTableStyle } = useApp();
+ const { theme, setTheme, tableStyle, setTableStyle, mapPositionMode, setMapPositionMode } = useApp();
return (
<div className="about-page">
@@ -15,20 +15,25 @@ export function Settings() {
<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 as "light" | "dark")}
- style={{ backgroundColor: theme === "dark" ? "#333" : "#fff", color: theme === "dark" ? "#fff" : "#000" }}>
+ <select id="theme" className="form-select-inline" value={theme} onChange={(e) => setTheme(e.target.value as "light" | "dark")}>
<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 as "regular" | "grouped")}
- style={{ backgroundColor: theme === "dark" ? "#333" : "#fff", color: theme === "dark" ? "#fff" : "#000" }}>
+ <select id="tableStyle" className="form-select-inline" value={tableStyle} onChange={(e) => setTableStyle(e.target.value as "regular" | "grouped")}>
<option value="regular">Mostrar por orden</option>
<option value="grouped">Agrupar por línea</option>
</select>
</div>
+ <div className="settings-content-inline">
+ <label htmlFor="mapPositionMode" className="form-label-inline">Posición del mapa:</label>
+ <select id="mapPositionMode" className="form-select-inline" value={mapPositionMode} onChange={e => setMapPositionMode(e.target.value as 'gps' | 'last')}>
+ <option value="gps">Posición GPS</option>
+ <option value="last">Donde lo dejé</option>
+ </select>
+ </div>
<details className="form-details">
<summary>¿Qué significa esto?</summary>
<p>
@@ -44,16 +49,16 @@ export function Settings() {
</section>
<h2>Créditos</h2>
<p>
- <a href="https://github.com/arielcostas/urbanovigo-web" className="about-link" style={{ color: theme === "dark" ? "#bbb" : "#000" }}>
+ <a href="https://github.com/arielcostas/urbanovigo-web" className="about-link" rel="nofollow noreferrer noopener">
Código en GitHub
</a> -
- Desarrollado por <a href="https://www.costas.dev" className="about-link" style={{ color: theme === "dark" ? "#bbb" : "#000" }}>
+ Desarrollado por <a href="https://www.costas.dev" className="about-link" rel="nofollow noreferrer noopener">
Ariel Costas
</a>
</p>
<p>
- Datos obtenidos de <a href="https://datos.vigo.org" style={{ color: theme === "dark" ? "#bbb" : "#000" }}>datos.vigo.org</a> bajo
- licencia <a href="https://opendefinition.org/licenses/odc-by/" style={{ color: theme === "dark" ? "#bbb" : "#000" }}>Open Data Commons Attribution License</a>
+ Datos obtenidos de <a href="https://datos.vigo.org" className="about-link" rel="nofollow noreferrer noopener">datos.vigo.org</a> bajo
+ licencia <a href="https://opendefinition.org/licenses/odc-by/" className="about-link" rel="nofollow noreferrer noopener">Open Data Commons Attribution License</a>
</p>
</div>
)
diff --git a/src/pages/StopList.tsx b/src/pages/StopList.tsx
index a2269ec..b965456 100644
--- a/src/pages/StopList.tsx
+++ b/src/pages/StopList.tsx
@@ -1,35 +1,54 @@
-import { useEffect, useMemo, useState } from "react";
+import { useEffect, useMemo, useRef, useState } from "react";
import StopDataProvider, { Stop } from "../data/StopDataProvider";
import StopItem from "../components/StopItem";
import Fuse from "fuse.js";
const placeholders = [
- "Urzaiz",
- "Gran Vía",
- "Castelao",
- "García Barbón",
- "Valladares",
- "Florida",
- "Pizarro",
- "Estrada Madrid",
- "Sanjurjo Badía"
+ "Urzaiz",
+ "Gran Vía",
+ "Castelao",
+ "García Barbón",
+ "Valladares",
+ "Florida",
+ "Pizarro",
+ "Estrada Madrid",
+ "Sanjurjo Badía"
];
export function StopList() {
const [data, setData] = useState<Stop[] | null>(null)
const [searchResults, setSearchResults] = useState<Stop[] | null>(null);
+ const searchTimeout = useRef<NodeJS.Timeout | null>(null);
+
+ const randomPlaceholder = useMemo(() => placeholders[Math.floor(Math.random() * placeholders.length)], []);
+ const fuse = useMemo(() => new Fuse(data || [], { threshold: 0.3, keys: ['name.original'] }), [data]);
useEffect(() => {
StopDataProvider.getStops().then((stops: Stop[]) => setData(stops))
}, []);
const handleStopSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
- const stopName = event.target.value;
- if (data) {
- const fuse = new Fuse(data, { keys: ['name'], threshold: 0.3 });
- const results = fuse.search(stopName).map(result => result.item);
- setSearchResults(results);
+ const stopName = event.target.value || "";
+
+ if (searchTimeout.current) {
+ clearTimeout(searchTimeout.current);
}
+
+ searchTimeout.current = setTimeout(() => {
+ if (stopName.length === 0) {
+ setSearchResults(null);
+ return;
+ }
+
+ if (!data) {
+ console.error("No data available for search");
+ return;
+ }
+
+ const results = fuse.search(stopName);
+ const items = results.map(result => result.item);
+ setSearchResults(items);
+ }, 300);
}
const favouritedStops = useMemo(() => {
@@ -50,8 +69,6 @@ export function StopList() {
if (data === null) return <h1 className="page-title">Loading...</h1>
- const randomPlaceholder = placeholders[Math.floor(Math.random() * placeholders.length)];
-
return (
<div className="page-container">
<h1 className="page-title">UrbanoVigo Web</h1>