aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/routes/estimates-$id.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/app/routes/estimates-$id.tsx')
-rw-r--r--src/frontend/app/routes/estimates-$id.tsx103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/frontend/app/routes/estimates-$id.tsx b/src/frontend/app/routes/estimates-$id.tsx
new file mode 100644
index 0000000..761a8d4
--- /dev/null
+++ b/src/frontend/app/routes/estimates-$id.tsx
@@ -0,0 +1,103 @@
+import { type JSX, useEffect, useState } from "react";
+import { useParams } from "react-router";
+import StopDataProvider from "../data/StopDataProvider";
+import { Star, Edit2 } from 'lucide-react';
+import "./estimates-$id.css";
+import { RegularTable } from "../components/RegularTable";
+import { useApp } from "../AppContext";
+import { GroupedTable } from "../components/GroupedTable";
+
+export interface StopDetails {
+ stop: {
+ id: number;
+ name: string;
+ latitude: number;
+ longitude: number;
+ }
+ estimates: {
+ line: string;
+ route: string;
+ minutes: number;
+ meters: number;
+ }[]
+}
+
+const loadData = async (stopId: string) => {
+ const resp = await fetch(`/api/GetStopEstimates?id=${stopId}`, {
+ headers: {
+ 'Accept': 'application/json',
+ }
+ });
+ return await resp.json();
+};
+
+export default function Estimates() {
+ const params = useParams();
+ const stopIdNum = parseInt(params.id ?? "");
+ 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 { tableStyle } = useApp();
+
+ useEffect(() => {
+ loadData(params.id!)
+ .then((body: StopDetails) => {
+ setData(body);
+ setDataDate(new Date());
+ setCustomName(StopDataProvider.getCustomName(stopIdNum));
+ })
+
+
+ StopDataProvider.pushRecent(parseInt(params.id ?? ""));
+
+ setFavourited(
+ StopDataProvider.isFavourite(parseInt(params.id ?? ""))
+ );
+ }, [params.id]);
+
+
+ const toggleFavourite = () => {
+ if (favourited) {
+ StopDataProvider.removeFavourite(stopIdNum);
+ setFavourited(false);
+ } else {
+ 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 (
+ <div className="page-container">
+ <div className="estimates-header">
+ <h1 className="page-title">
+ <Star className={`star-icon ${favourited ? 'active' : ''}`} onClick={toggleFavourite} />
+ <Edit2 className="edit-icon" onClick={handleRename} />
+ {(customName ?? data.stop.name)} <span className="estimates-stop-id">({data.stop.id})</span>
+ </h1>
+ </div>
+
+ <div className="table-responsive">
+ {tableStyle === 'grouped' ?
+ <GroupedTable data={data} dataDate={dataDate} /> :
+ <RegularTable data={data} dataDate={dataDate} />}
+ </div>
+ </div>
+ )
+}