From 7b8594debceb93a1fa400d48fe1dcff943bd5af6 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Thu, 26 Jun 2025 23:44:25 +0200
Subject: Implement stop sheet modal for map stop interactions (#27)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: arielcostas <94913521+arielcostas@users.noreply.github.com>
Co-authored-by: Ariel Costas Guerrero <ariel@costas.dev>
---
 src/frontend/app/routes/estimates-$id.tsx | 162 +++++++++++++++---------------
 1 file changed, 82 insertions(+), 80 deletions(-)

(limited to 'src/frontend/app/routes/estimates-$id.tsx')

diff --git a/src/frontend/app/routes/estimates-$id.tsx b/src/frontend/app/routes/estimates-$id.tsx
index e0e4fff..f2ef83a 100644
--- a/src/frontend/app/routes/estimates-$id.tsx
+++ b/src/frontend/app/routes/estimates-$id.tsx
@@ -1,7 +1,7 @@
 import { type JSX, useEffect, useState } from "react";
 import { useParams } from "react-router";
 import StopDataProvider from "../data/StopDataProvider";
-import { Star, Edit2 } from 'lucide-react';
+import { Star, Edit2 } from "lucide-react";
 import "./estimates-$id.css";
 import { RegularTable } from "../components/RegularTable";
 import { useApp } from "../AppContext";
@@ -9,97 +9,99 @@ import { GroupedTable } from "../components/GroupedTable";
 import { useTranslation } from "react-i18next";
 
 export interface StopDetails {
-	stop: {
-		id: number;
-		name: string;
-		latitude: number;
-		longitude: number;
-	}
-	estimates: {
-		line: string;
-		route: string;
-		minutes: number;
-		meters: number;
-	}[]
+  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();
+  const resp = await fetch(`/api/GetStopEstimates?id=${stopId}`, {
+    headers: {
+      Accept: "application/json",
+    },
+  });
+  return await resp.json();
 };
 
 export default function Estimates() {
-	const { t } = useTranslation();
-	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();
+  const { t } = useTranslation();
+  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));
-			})
+  useEffect(() => {
+    loadData(params.id!).then((body: StopDetails) => {
+      setData(body);
+      setDataDate(new Date());
+      setCustomName(StopDataProvider.getCustomName(stopIdNum));
+    });
 
+    StopDataProvider.pushRecent(parseInt(params.id ?? ""));
 
-		StopDataProvider.pushRecent(parseInt(params.id ?? ""));
+    setFavourited(StopDataProvider.isFavourite(parseInt(params.id ?? "")));
+  }, [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);
+    }
+  };
 
-	const toggleFavourite = () => {
-		if (favourited) {
-			StopDataProvider.removeFavourite(stopIdNum);
-			setFavourited(false);
-		} else {
-			StopDataProvider.addFavourite(stopIdNum);
-			setFavourited(true);
-		}
-	}
+  if (data === null)
+    return <h1 className="page-title">{t("common.loading")}</h1>;
 
-	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);
-		}
-	};
+  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>
 
-	if (data === null) return <h1 className="page-title">{t('common.loading')}</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>
-	)
+      <div className="table-responsive">
+        {tableStyle === "grouped" ? (
+          <GroupedTable data={data} dataDate={dataDate} />
+        ) : (
+          <RegularTable data={data} dataDate={dataDate} />
+        )}
+      </div>
+    </div>
+  );
 }
-- 
cgit v1.3

