aboutsummaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-04-20 20:15:55 +0200
committerAriel Costas Guerrero <ariel@costas.dev>2025-04-20 20:15:55 +0200
commit3676b1d1d9216a676c7d5a40affa5b3256ca8df3 (patch)
treeefa63a0d21ae52e32e405fe7b4ce56b02d782e86 /src/pages
parentc86b4655f72c86362c064dd50bb701782b39e6eb (diff)
Refactor stop data handling with caching and custom names support
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/Estimates.tsx28
-rw-r--r--src/pages/Map.tsx14
-rw-r--r--src/pages/StopList.tsx16
3 files changed, 36 insertions, 22 deletions
diff --git a/src/pages/Estimates.tsx b/src/pages/Estimates.tsx
index 90745da..7cf941a 100644
--- a/src/pages/Estimates.tsx
+++ b/src/pages/Estimates.tsx
@@ -1,7 +1,7 @@
import { JSX, useEffect, useState } from "react";
import { useParams } from "react-router";
import StopDataProvider from "../data/StopDataProvider";
-import { Star } from 'lucide-react';
+import { Star, Edit2 } from 'lucide-react';
import "../styles/Estimates.css";
import { RegularTable } from "../components/RegularTable";
import { useApp } from "../AppContext";
@@ -28,10 +28,12 @@ const loadData = async (stopId: string) => {
};
export function Estimates(): JSX.Element {
+ const params = useParams();
+ const stopIdNum = parseInt(params.stopId ?? "");
+ const [customName, setCustomName] = useState<string | undefined>(undefined);
const [data, setData] = useState<StopDetails | null>(null);
const [dataDate, setDataDate] = useState<Date | null>(null);
const [favourited, setFavourited] = useState(false);
- const params = useParams();
const { tableStyle } = useApp();
useEffect(() => {
@@ -39,6 +41,7 @@ export function Estimates(): JSX.Element {
.then((body: StopDetails) => {
setData(body);
setDataDate(new Date());
+ setCustomName(StopDataProvider.getCustomName(stopIdNum));
})
@@ -52,14 +55,28 @@ export function Estimates(): JSX.Element {
const toggleFavourite = () => {
if (favourited) {
- StopDataProvider.removeFavourite(parseInt(params.stopId ?? ""));
+ StopDataProvider.removeFavourite(stopIdNum);
setFavourited(false);
} else {
- StopDataProvider.addFavourite(parseInt(params.stopId ?? ""));
+ StopDataProvider.addFavourite(stopIdNum);
setFavourited(true);
}
}
+ const handleRename = () => {
+ const current = customName ?? data?.stop.name;
+ const input = window.prompt('Custom name for this stop:', current);
+ if (input === null) return; // cancelled
+ const trimmed = input.trim();
+ if (trimmed === '') {
+ StopDataProvider.removeCustomName(stopIdNum);
+ setCustomName(undefined);
+ } else {
+ StopDataProvider.setCustomName(stopIdNum, trimmed);
+ setCustomName(trimmed);
+ }
+ };
+
if (data === null) return <h1 className="page-title">Cargando datos en tiempo real...</h1>
return (
@@ -67,7 +84,8 @@ export function Estimates(): JSX.Element {
<div className="estimates-header">
<h1 className="page-title">
<Star className={`star-icon ${favourited ? 'active' : ''}`} onClick={toggleFavourite} />
- {data?.stop.name} <span className="estimates-stop-id">({data?.stop.id})</span>
+ <Edit2 className="edit-icon" onClick={handleRename} />
+ {(customName ?? data.stop.name)} <span className="estimates-stop-id">({data.stop.id})</span>
</h1>
</div>
diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx
index af95bf9..1f0a9e0 100644
--- a/src/pages/Map.tsx
+++ b/src/pages/Map.tsx
@@ -41,17 +41,9 @@ export function StopMap() {
const { mapState } = useApp();
useEffect(() => {
- StopDataProvider.getStops().then((stops) => { setStops(stops); });
+ StopDataProvider.getStops().then(setStops);
}, []);
- const getDisplayName = (stop: Stop): string => {
- if (typeof stop.name === 'string') {
- return stop.name;
- }
-
- return stop.name.intersect || stop.name.original;
- }
-
return (
<MapContainer
center={mapState.center}
@@ -66,10 +58,10 @@ export function StopMap() {
<EnhancedLocateControl />
<MapEventHandler />
<MarkerClusterGroup>
- {stops.map((stop) => (
+ {stops.map(stop => (
<Marker key={stop.stopId} position={[stop.latitude, stop.longitude] as LatLngTuple} icon={icon}>
<Popup>
- <Link to={`/estimates/${stop.stopId}`}>{getDisplayName(stop)}</Link>
+ <Link to={`/estimates/${stop.stopId}`}>{StopDataProvider.getDisplayName(stop)}</Link>
<br />
{stop.lines.map((line) => (
<LineIcon key={line} line={line} />
diff --git a/src/pages/StopList.tsx b/src/pages/StopList.tsx
index 449ae84..a2269ec 100644
--- a/src/pages/StopList.tsx
+++ b/src/pages/StopList.tsx
@@ -37,12 +37,16 @@ export function StopList() {
}, [data])
const recentStops = useMemo(() => {
- const recent = StopDataProvider.getRecent();
-
- if (recent.length === 0) return null;
-
- return recent.map(stopId => data?.find(stop => stop.stopId === stopId) as Stop).reverse();
- }, [data])
+ // no recent items if data not loaded
+ if (!data) return null;
+ const recentIds = StopDataProvider.getRecent();
+ if (recentIds.length === 0) return null;
+ // map and filter out missing entries
+ const stopsList = recentIds
+ .map(id => data.find(stop => stop.stopId === id))
+ .filter((s): s is Stop => Boolean(s));
+ return stopsList.reverse();
+ }, [data]);
if (data === null) return <h1 className="page-title">Loading...</h1>