aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/routes/estimates-$id.tsx
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-08-05 23:36:20 +0200
committerAriel Costas Guerrero <ariel@costas.dev>2025-08-05 23:36:20 +0200
commitb04fd7d33d07f9eddea2eb53e1389d5ca5453413 (patch)
treefec6f44639514ee4af70031f09a39fb1c808623f /src/frontend/app/routes/estimates-$id.tsx
parentc18063cc107c3126a9b62caa857e37062ab86c9c (diff)
Add timetable feature with caching and localization support
Diffstat (limited to 'src/frontend/app/routes/estimates-$id.tsx')
-rw-r--r--src/frontend/app/routes/estimates-$id.tsx49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/frontend/app/routes/estimates-$id.tsx b/src/frontend/app/routes/estimates-$id.tsx
index f2ef83a..b5ae91a 100644
--- a/src/frontend/app/routes/estimates-$id.tsx
+++ b/src/frontend/app/routes/estimates-$id.tsx
@@ -1,12 +1,13 @@
import { type JSX, useEffect, useState } from "react";
-import { useParams } from "react-router";
+import { useParams, Link } from "react-router";
import StopDataProvider from "../data/StopDataProvider";
-import { Star, Edit2 } from "lucide-react";
+import { Star, Edit2, ExternalLink } from "lucide-react";
import "./estimates-$id.css";
import { RegularTable } from "../components/RegularTable";
import { useApp } from "../AppContext";
import { GroupedTable } from "../components/GroupedTable";
import { useTranslation } from "react-i18next";
+import { TimetableTable, type TimetableEntry } from "../components/TimetableTable";
export interface StopDetails {
stop: {
@@ -32,6 +33,24 @@ const loadData = async (stopId: string) => {
return await resp.json();
};
+const loadTimetableData = async (stopId: string) => {
+ const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD format
+ try {
+ const resp = await fetch(`/api/GetStopTimetable?date=${today}&stopId=${stopId}`, {
+ headers: {
+ Accept: "application/json",
+ },
+ });
+ if (!resp.ok) {
+ throw new Error(`HTTP error! status: ${resp.status}`);
+ }
+ return await resp.json();
+ } catch (error) {
+ console.error('Error loading timetable data:', error);
+ return [];
+ }
+};
+
export default function Estimates() {
const { t } = useTranslation();
const params = useParams();
@@ -40,15 +59,22 @@ export default function Estimates() {
const [data, setData] = useState<StopDetails | null>(null);
const [dataDate, setDataDate] = useState<Date | null>(null);
const [favourited, setFavourited] = useState(false);
+ const [timetableData, setTimetableData] = useState<TimetableEntry[]>([]);
const { tableStyle } = useApp();
useEffect(() => {
+ // Load real-time estimates
loadData(params.id!).then((body: StopDetails) => {
setData(body);
setDataDate(new Date());
setCustomName(StopDataProvider.getCustomName(stopIdNum));
});
+ // Load timetable data
+ loadTimetableData(params.id!).then((timetableBody: TimetableEntry[]) => {
+ setTimetableData(timetableBody);
+ });
+
StopDataProvider.pushRecent(parseInt(params.id ?? ""));
setFavourited(StopDataProvider.isFavourite(parseInt(params.id ?? "")));
@@ -102,6 +128,25 @@ export default function Estimates() {
<RegularTable data={data} dataDate={dataDate} />
)}
</div>
+
+ <div className="timetable-section">
+ <TimetableTable
+ data={timetableData}
+ currentTime={new Date().toTimeString().slice(0, 8)} // HH:MM:SS
+ />
+
+ {timetableData.length > 0 && (
+ <div className="timetable-actions">
+ <Link
+ to={`/timetable/${params.id}`}
+ className="view-all-link"
+ >
+ <ExternalLink className="external-icon" />
+ {t("timetable.viewAll", "Ver todos los horarios")}
+ </Link>
+ </div>
+ )}
+ </div>
</div>
);
}