aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/components
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-12-19 13:06:27 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2025-12-19 13:06:27 +0100
commit2a9aca302485bc08f5b2dd2a54987de6f80fc338 (patch)
tree38171abad21b2952eca6ff9e8534545b4c28ed12 /src/frontend/app/components
parent37cdb0c418a7f2b47e40ae9db7ad86e1fddc86fe (diff)
Implement loading stops as tiles from OTP
Diffstat (limited to 'src/frontend/app/components')
-rw-r--r--src/frontend/app/components/LineIcon.tsx27
-rw-r--r--src/frontend/app/components/PlannerOverlay.tsx3
-rw-r--r--src/frontend/app/components/RegionSelector.tsx33
-rw-r--r--src/frontend/app/components/StopMapModal.tsx6
-rw-r--r--src/frontend/app/components/map/StopSummarySheet.css (renamed from src/frontend/app/components/StopSummarySheet.css)0
-rw-r--r--src/frontend/app/components/map/StopSummarySheet.tsx (renamed from src/frontend/app/components/StopSummarySheet.tsx)51
-rw-r--r--src/frontend/app/components/map/StopSummarySheetSkeleton.tsx (renamed from src/frontend/app/components/StopSummarySheetSkeleton.tsx)0
7 files changed, 57 insertions, 63 deletions
diff --git a/src/frontend/app/components/LineIcon.tsx b/src/frontend/app/components/LineIcon.tsx
index 8bbeb20..5d85c60 100644
--- a/src/frontend/app/components/LineIcon.tsx
+++ b/src/frontend/app/components/LineIcon.tsx
@@ -4,9 +4,16 @@ import "./LineIcon.css";
interface LineIconProps {
line: string;
mode?: "rounded" | "pill" | "default";
+ colour?: string;
+ textColour?: string;
}
-const LineIcon: React.FC<LineIconProps> = ({ line, mode = "default" }) => {
+const LineIcon: React.FC<LineIconProps> = ({
+ line,
+ mode = "default",
+ colour,
+ textColour,
+}) => {
const actualLine = useMemo(() => {
return line.trim().replace("510", "NAD");
}, [line]);
@@ -15,16 +22,26 @@ const LineIcon: React.FC<LineIconProps> = ({ line, mode = "default" }) => {
return /^[a-zA-Z]/.test(actualLine) ? actualLine : `L${actualLine}`;
}, [actualLine]);
- const cssVarName = `--line-${formattedLine.toLowerCase()}`;
- const cssTextVarName = `--line-${formattedLine.toLowerCase()}-text`;
+ const actualLineColour = useMemo(() => {
+ const actualColour = colour?.startsWith("#") ? colour : `#${colour}`;
+ return colour ? actualColour : `var(--line-${formattedLine.toLowerCase()})`;
+ }, [formattedLine]);
+ const actualTextColour = useMemo(() => {
+ const actualTextColour = textColour?.startsWith("#")
+ ? textColour
+ : `#${textColour}`;
+ return textColour
+ ? actualTextColour
+ : `var(--line-${formattedLine.toLowerCase()}-text, #000000)`;
+ }, [formattedLine]);
return (
<span
className={`line-icon-${mode}`}
style={
{
- "--line-colour": `var(${cssVarName})`,
- "--line-text-colour": `var(${cssTextVarName}, #000000)`,
+ "--line-colour": actualLineColour,
+ "--line-text-colour": actualTextColour,
} as React.CSSProperties
}
>
diff --git a/src/frontend/app/components/PlannerOverlay.tsx b/src/frontend/app/components/PlannerOverlay.tsx
index 12cfb0f..af71e48 100644
--- a/src/frontend/app/components/PlannerOverlay.tsx
+++ b/src/frontend/app/components/PlannerOverlay.tsx
@@ -8,7 +8,6 @@ import React, {
} from "react";
import { useTranslation } from "react-i18next";
import PlaceListItem from "~/components/PlaceListItem";
-import { REGION_DATA } from "~/config/RegionConfig";
import {
reverseGeocode,
searchPlaces,
@@ -59,7 +58,7 @@ export const PlannerOverlay: React.FC<PlannerOverlayProps> = ({
[]
);
const [recentPlaces, setRecentPlaces] = useState<PlannerSearchResult[]>([]);
- const RECENT_KEY = `recentPlaces_${REGION_DATA.id}`;
+ const RECENT_KEY = `recentPlaces`;
const clearRecentPlaces = useCallback(() => {
setRecentPlaces([]);
try {
diff --git a/src/frontend/app/components/RegionSelector.tsx b/src/frontend/app/components/RegionSelector.tsx
deleted file mode 100644
index 124b574..0000000
--- a/src/frontend/app/components/RegionSelector.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useApp } from "../AppContext";
-import { getAvailableRegions } from "../config/RegionConfig";
-import "./RegionSelector.css";
-
-export function RegionSelector() {
- const { region, setRegion } = useApp();
- const regions = getAvailableRegions();
-
- const handleRegionChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
- const newRegion = e.target.value as any;
- setRegion(newRegion);
- };
-
- return (
- <div className="region-selector">
- <label htmlFor="region-select" className="region-label">
- Región:
- </label>
- <select
- id="region-select"
- className="region-select"
- value={region}
- onChange={handleRegionChange}
- >
- {regions.map((r) => (
- <option key={r.id} value={r.id}>
- {r.name}
- </option>
- ))}
- </select>
- </div>
- );
-}
diff --git a/src/frontend/app/components/StopMapModal.tsx b/src/frontend/app/components/StopMapModal.tsx
index 1cb6d88..bb6a3fa 100644
--- a/src/frontend/app/components/StopMapModal.tsx
+++ b/src/frontend/app/components/StopMapModal.tsx
@@ -9,7 +9,7 @@ import React, {
import Map, { Layer, Marker, Source, type MapRef } from "react-map-gl/maplibre";
import { Sheet } from "react-modal-sheet";
import { useApp } from "~/AppContext";
-import { REGION_DATA } from "~/config/RegionConfig";
+import { APP_CONSTANTS } from "~/config/constants";
import { getLineColour } from "~/data/LineColors";
import type { Stop } from "~/data/StopDataProvider";
import { loadStyle } from "~/maps/styleloader";
@@ -243,7 +243,7 @@ export const StopMapModal: React.FC<StopMapModalProps> = ({
!selectedBus ||
!selectedBus.schedule?.shapeId ||
selectedBus.currentPosition?.shapeIndex === undefined ||
- !REGION_DATA.shapeEndpoint
+ !APP_CONSTANTS.shapeEndpoint
) {
setShapeData(null);
setPreviousShapeData(null);
@@ -263,7 +263,7 @@ export const StopMapModal: React.FC<StopMapModalProps> = ({
sLat?: number,
sLon?: number
) => {
- let url = `${REGION_DATA.shapeEndpoint}?shapeId=${sId}`;
+ let url = `${APP_CONSTANTS.shapeEndpoint}?shapeId=${sId}`;
if (bIndex !== undefined) url += `&busShapeIndex=${bIndex}`;
if (sIndex !== undefined) url += `&stopShapeIndex=${sIndex}`;
else if (sLat && sLon) url += `&stopLat=${sLat}&stopLon=${sLon}`;
diff --git a/src/frontend/app/components/StopSummarySheet.css b/src/frontend/app/components/map/StopSummarySheet.css
index 5869d41..5869d41 100644
--- a/src/frontend/app/components/StopSummarySheet.css
+++ b/src/frontend/app/components/map/StopSummarySheet.css
diff --git a/src/frontend/app/components/StopSummarySheet.tsx b/src/frontend/app/components/map/StopSummarySheet.tsx
index c2d6ffe..b24e71c 100644
--- a/src/frontend/app/components/StopSummarySheet.tsx
+++ b/src/frontend/app/components/map/StopSummarySheet.tsx
@@ -4,19 +4,27 @@ import { useTranslation } from "react-i18next";
import { Sheet } from "react-modal-sheet";
import { Link } from "react-router";
import { ConsolidatedCirculationList } from "~/components/Stops/ConsolidatedCirculationList";
-import { REGION_DATA } from "~/config/RegionConfig";
-import type { Stop } from "~/data/StopDataProvider";
-import { type ConsolidatedCirculation } from "../routes/stops-$id";
-import { ErrorDisplay } from "./ErrorDisplay";
-import LineIcon from "./LineIcon";
-import { StopAlert } from "./StopAlert";
+import { APP_CONSTANTS } from "~/config/constants";
+import { type ConsolidatedCirculation } from "../../routes/stops-$id";
+import { ErrorDisplay } from "../ErrorDisplay";
+import LineIcon from "../LineIcon";
import "./StopSummarySheet.css";
import { StopSummarySheetSkeleton } from "./StopSummarySheetSkeleton";
-interface StopSheetProps {
+export interface StopSheetProps {
isOpen: boolean;
onClose: () => void;
- stop: Stop;
+ stop: {
+ stopId: string;
+ stopCode?: string;
+ stopFeed?: string;
+ name: string;
+ lines: {
+ line: string;
+ colour?: string;
+ textColour?: string;
+ }[];
+ };
}
interface ErrorInfo {
@@ -29,7 +37,7 @@ const loadConsolidatedData = async (
stopId: string
): Promise<ConsolidatedCirculation[]> => {
const resp = await fetch(
- `${REGION_DATA.consolidatedCirculationsEndpoint}?stopId=${stopId}`,
+ `${APP_CONSTANTS.consolidatedCirculationsEndpoint}?stopId=${stopId}`,
{
headers: {
Accept: "application/json",
@@ -116,21 +124,24 @@ export const StopSheet: React.FC<StopSheetProps> = ({
<Sheet.Content drag="y">
<div className="stop-sheet-content">
<div className="stop-sheet-header">
- <h2 className="stop-sheet-title">{stop.name.original}</h2>
- <span className="stop-sheet-id">({stop.stopId})</span>
+ <h2 className="stop-sheet-title">{stop.name}</h2>
+ <span className="stop-sheet-id">({stop.stopCode})</span>
</div>
- <div
- className={`stop-sheet-lines-container ${stop.lines.length >= 10 ? "scrollable" : ""}`}
- >
- {stop.lines.map((line) => (
- <div key={line} className="stop-sheet-line-icon">
- <LineIcon line={line} mode="rounded" />
- </div>
+ <div className={`d-flex flex-wrap flex-row gap-2`}>
+ {stop.lines.map((lineObj) => (
+ <LineIcon
+ key={lineObj.line}
+ line={lineObj.line}
+ mode="pill"
+ colour={lineObj.colour}
+ textColour={lineObj.textColour}
+ />
))}
</div>
- <StopAlert stop={stop} compact />
+ {/* TODO: Enable stop alerts when available */}
+ {/*<StopAlert stop={stop} compact />*/}
{loading ? (
<StopSummarySheetSkeleton />
@@ -158,7 +169,7 @@ export const StopSheet: React.FC<StopSheetProps> = ({
) : (
<ConsolidatedCirculationList
data={data.slice(0, 4)}
- driver={stop.stopId.split(":")[0]}
+ driver={stop.stopFeed}
reduced
/>
)}
diff --git a/src/frontend/app/components/StopSummarySheetSkeleton.tsx b/src/frontend/app/components/map/StopSummarySheetSkeleton.tsx
index 7697efc..7697efc 100644
--- a/src/frontend/app/components/StopSummarySheetSkeleton.tsx
+++ b/src/frontend/app/components/map/StopSummarySheetSkeleton.tsx