From 854be328986a09460249a55dbac3af26530c7b29 Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Sun, 8 Mar 2026 23:12:05 +0100 Subject: Enhance StopItem component to display next arrivals and improve layout; update StopList to show arrivals for the first three stops --- src/frontend/app/components/StopItem.tsx | 119 +++++++++++++++++++++++++------ src/frontend/app/routes/home.tsx | 82 ++++++++++++++++----- 2 files changed, 161 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/frontend/app/components/StopItem.tsx b/src/frontend/app/components/StopItem.tsx index 35ccf6d..362798e 100644 --- a/src/frontend/app/components/StopItem.tsx +++ b/src/frontend/app/components/StopItem.tsx @@ -1,37 +1,112 @@ -import React from "react"; +import { Clock } from "lucide-react"; +import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; import { Link } from "react-router"; +import { fetchArrivals } from "../api/arrivals"; +import { type Arrival } from "../api/schema"; import StopDataProvider, { type Stop } from "../data/StopDataProvider"; import RouteIcon from "./RouteIcon"; interface StopItemProps { stop: Stop; + showArrivals?: boolean; } -const StopItem: React.FC = ({ stop }) => { +const StopItem: React.FC = ({ stop, showArrivals }) => { + const { t } = useTranslation(); + const [arrivals, setArrivals] = useState(null); + + useEffect(() => { + let mounted = true; + if (showArrivals) { + fetchArrivals(stop.stopId, true) + .then((res) => { + if (mounted) { + setArrivals(res.arrivals.slice(0, 3)); + } + }) + .catch(console.error); + } + return () => { + mounted = false; + }; + }, [showArrivals, stop.stopId]); + return ( -
  • +
  • -
    - - {stop.favourite && } - {StopDataProvider.getDisplayName(stop)} - - - ({stop.stopCode || stop.stopId}) - -
    -
    - {stop.lines?.map((lineObj) => ( - - ))} +
    +
    + + {stop.favourite && ( + + )} + {StopDataProvider.getDisplayName(stop)} + +
    + +
    + + {stop.stopId.split(":")[0]} + + + {stop.stopCode || stop.stopId.split(":")[1] || stop.stopId} + +
    + + {stop.lines && stop.lines.length > 0 && ( +
    + {stop.lines.map((lineObj) => ( + + ))} +
    + )} + + {showArrivals && arrivals && arrivals.length > 0 && ( +
    +
    + + + {t("estimates.next_arrivals", "Próximas llegadas")} + +
    + {arrivals.map((arr, i) => ( +
    +
    + +
    + + {arr.headsign.destination} + + + {arr.estimate.minutes}' + +
    + ))} +
    + )}
  • diff --git a/src/frontend/app/routes/home.tsx b/src/frontend/app/routes/home.tsx index 973a534..0229ad5 100644 --- a/src/frontend/app/routes/home.tsx +++ b/src/frontend/app/routes/home.tsx @@ -1,11 +1,10 @@ -import { History } from "lucide-react"; +import { Clock, History, Star } from "lucide-react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router"; import { PlannerOverlay } from "~/components/PlannerOverlay"; import { usePageTitle } from "~/contexts/PageTitleContext"; import { usePlanner } from "~/hooks/usePlanner"; -import StopGallery from "../components/StopGallery"; import StopItem from "../components/StopItem"; import StopDataProvider, { type Stop } from "../data/StopDataProvider"; import "../tailwind-full.css"; @@ -246,8 +245,12 @@ export default function StopList() { {t("stoplist.search_results", "Resultados de la búsqueda")}
      - {searchResults.map((stop: Stop) => ( - + {searchResults.map((stop: Stop, index) => ( + ))}
    @@ -259,25 +262,68 @@ export default function StopList() { ) : ( <> - {/* Favourites Gallery */} - {!loading && ( - - a.stopId.localeCompare(b.stopId) - )} - title={t("stoplist.favourites")} - emptyMessage={t("stoplist.no_favourites")} - /> + {/* Favourites List */} + {!loading && favouriteStops.length > 0 && ( +
    +
    + +

    + {t("stoplist.favourites")} +

    +
    +
      + {favouriteStops + .sort((a, b) => a.stopId.localeCompare(b.stopId)) + .map((stop, index) => ( + + ))} +
    +
    )} - {/* Recent Stops Gallery - only show if no favourites */} {!loading && favouriteStops.length === 0 && ( - +
    +
    + +

    + {t("stoplist.favourites")} +

    +
    +
    +

    + {t("stoplist.no_favourites")} +

    +
    +
    )} + {/* Recent Stops List - only show if no favourites */} + {!loading && + favouriteStops.length === 0 && + recentStops.length > 0 && ( +
    +
    + +

    + {t("stoplist.recents")} +

    +
    +
      + {recentStops.slice(0, 5).map((stop, index) => ( + + ))} +
    +
    + )} + {/**/} )} -- cgit v1.3