diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2025-11-03 11:20:27 +0100 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2025-11-03 11:20:27 +0100 |
| commit | 769d12a525875d3577b2868208d6315c56ce77d6 (patch) | |
| tree | 4fa84a86a2eda352b6bea14e6ecab741134de62a /src/frontend/app/components | |
| parent | 809941dcc8f37967a22516b1c4f7af1f3b8a82bc (diff) | |
Display available lines on StopSheet
Diffstat (limited to 'src/frontend/app/components')
| -rw-r--r-- | src/frontend/app/components/LineIcon.css | 37 | ||||
| -rw-r--r-- | src/frontend/app/components/LineIcon.tsx | 8 | ||||
| -rw-r--r-- | src/frontend/app/components/StopSheet.css | 6 | ||||
| -rw-r--r-- | src/frontend/app/components/StopSheet.tsx | 29 |
4 files changed, 63 insertions, 17 deletions
diff --git a/src/frontend/app/components/LineIcon.css b/src/frontend/app/components/LineIcon.css index 7d46b98..b52e566 100644 --- a/src/frontend/app/components/LineIcon.css +++ b/src/frontend/app/components/LineIcon.css @@ -1,6 +1,7 @@ /* Vigo line colors */ :root { --line-vigo-c1: rgb(237, 71, 19); + --line-vigo-c1-text: #ffffff; --line-vigo-c3d: rgb(255, 204, 0); --line-vigo-c3i: rgb(255, 204, 0); --line-vigo-l4a: rgb(0, 153, 0); @@ -11,7 +12,9 @@ --line-vigo-l7: rgb(150, 220, 153); --line-vigo-l9b: rgb(244, 202, 140); --line-vigo-l10: rgb(153, 51, 0); + --line-vigo-l10-text: #ffffff; --line-vigo-l11: rgb(226, 0, 38); + --line-vigo-l11-text: #ffffff; --line-vigo-l12a: rgb(106, 150, 190); --line-vigo-l12b: rgb(106, 150, 190); --line-vigo-l13: rgb(0, 176, 240); @@ -22,8 +25,11 @@ --line-vigo-l16: rgb(129, 142, 126); --line-vigo-l17: rgb(214, 245, 31); --line-vigo-l18a: rgb(212, 80, 168); - --line-vigo-l18b: rgb(0, 0, 0); - --line-vigo-l18h: rgb(0, 0, 0); + --line-vigo-l18a-text: #ffffff; + --line-vigo-l18b: rgb(212, 80, 168); + --line-vigo-l18b-text: #ffffff; + --line-vigo-l18h: rgb(212, 80, 168); + --line-vigo-l18h-text: #ffffff; --line-vigo-l23: rgb(0, 70, 210); --line-vigo-l24: rgb(191, 191, 191); --line-vigo-l25: rgb(172, 100, 4); @@ -32,6 +38,7 @@ --line-vigo-l29: rgb(248, 184, 90); --line-vigo-l31: rgb(255, 255, 0); --line-vigo-a: rgb(119, 41, 143); + --line-vigo-a-text: #ffffff; --line-vigo-h: rgb(0, 96, 168); --line-vigo-h1: rgb(0, 96, 168); --line-vigo-h2: rgb(0, 96, 168); @@ -39,6 +46,7 @@ --line-vigo-lzd: rgb(61, 78, 167); --line-vigo-n1: rgb(191, 191, 191); --line-vigo-n4: rgb(102, 51, 102); + --line-vigo-n4-text: #ffffff; --line-vigo-psa1: rgb(0, 153, 0); --line-vigo-psa4: rgb(0, 153, 0); --line-vigo-ptl: rgb(150, 220, 153); @@ -56,12 +64,18 @@ --line-santiago-l9: #46b8bb; --line-santiago-c11: #aec741; --line-santiago-l12: #842e14; + --line-santiago-l12-text: #ffffff; --line-santiago-l13: #336600; + --line-santiago-l13-text: #ffffff; --line-santiago-l15: #7a4b2a; + --line-santiago-l15-text: #ffffff; --line-santiago-c2: #283a87; + --line-santiago-c2-text: #ffffff; --line-santiago-c4: #283a87; + --line-santiago-c4-text: #ffffff; --line-santiago-c5: #999999; --line-santiago-c6: #006666; + --line-santiago-c6-text: #ffffff; --line-santiago-p1: #537eb3; --line-santiago-p2: #d23354; --line-santiago-p3: #75bd96; @@ -76,13 +90,30 @@ display: inline-block; padding: 0.25rem 0.5rem; margin-right: 0.5rem; - border-bottom: 3px solid; font-size: 0.9rem; font-weight: 600; text-transform: uppercase; border-radius: 0.25rem 0.25rem 0 0; color: var(--text-color); background-color: var(--background-color); + + border-bottom: 3px solid; + border-color: var(--line-colour); } +.line-icon-rounded { + display: block; + width: 54px; + height: 54px; + box-sizing: border-box; + + background-color: var(--line-colour); + color: var(--line-text-colour); + padding: 1.25rem 0.5rem; + text-align: center; + border-radius: 50%; + + font: 600 14px/1 monospace; + letter-spacing: 0.05em; +} diff --git a/src/frontend/app/components/LineIcon.tsx b/src/frontend/app/components/LineIcon.tsx index 4f4bfd9..55e38c2 100644 --- a/src/frontend/app/components/LineIcon.tsx +++ b/src/frontend/app/components/LineIcon.tsx @@ -5,18 +5,20 @@ import { type RegionId } from "../data/RegionConfig"; interface LineIconProps { line: string; region?: RegionId; + rounded?: boolean; } -const LineIcon: React.FC<LineIconProps> = ({ line, region = "vigo" }) => { +const LineIcon: React.FC<LineIconProps> = ({ line, region = "vigo", rounded = false }) => { const formattedLine = useMemo(() => { return /^[a-zA-Z]/.test(line) ? line : `L${line}`; }, [line]); const cssVarName = `--line-${region}-${formattedLine.toLowerCase()}`; + const cssTextVarName = `--line-${region}-${formattedLine.toLowerCase()}-text`; return ( <span - className="line-icon" - style={{ borderColor: `var(${cssVarName})` }} + className={rounded ? 'line-icon-rounded' : 'line-icon'} + style={{ '--line-colour': `var(${cssVarName})`, '--line-text-colour': `var(${cssTextVarName}, unset)` } as React.CSSProperties} > {formattedLine} </span> diff --git a/src/frontend/app/components/StopSheet.css b/src/frontend/app/components/StopSheet.css index d3c0b06..931dcc3 100644 --- a/src/frontend/app/components/StopSheet.css +++ b/src/frontend/app/components/StopSheet.css @@ -29,6 +29,11 @@ color: var(--subtitle-color); } +.stop-sheet-lines-container { + display: flex; + gap: 0.75rem; +} + .stop-sheet-loading { display: flex; justify-content: center; @@ -42,6 +47,7 @@ flex: 1; overflow-y: auto; min-height: 0; + margin-block-start: 1.25rem; } .stop-sheet-subtitle { diff --git a/src/frontend/app/components/StopSheet.tsx b/src/frontend/app/components/StopSheet.tsx index 8080220..afa530b 100644 --- a/src/frontend/app/components/StopSheet.tsx +++ b/src/frontend/app/components/StopSheet.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import { Sheet } from "react-modal-sheet"; import { Link } from "react-router"; import { useTranslation } from "react-i18next"; -import { Clock, ClockFading, Hourglass, RefreshCw } from "lucide-react"; +import { Clock, RefreshCw } from "lucide-react"; import LineIcon from "./LineIcon"; import { StopSheetSkeleton } from "./StopSheetSkeleton"; import { ErrorDisplay } from "./ErrorDisplay"; @@ -10,12 +10,12 @@ import { type Estimate } from "../routes/estimates-$id"; import { REGIONS, type RegionId, getRegionConfig } from "../data/RegionConfig"; import { useApp } from "../AppContext"; import "./StopSheet.css"; +import type { Stop } from "~/data/StopDataProvider"; interface StopSheetProps { isOpen: boolean; onClose: () => void; - stopId: number; - stopName: string; + stop: Stop; } interface ErrorInfo { @@ -42,8 +42,7 @@ const loadStopData = async (region: RegionId, stopId: number): Promise<Estimate[ export const StopSheet: React.FC<StopSheetProps> = ({ isOpen, onClose, - stopId, - stopName, + stop }) => { const { t } = useTranslation(); const { region } = useApp(); @@ -77,7 +76,7 @@ export const StopSheet: React.FC<StopSheetProps> = ({ setError(null); setData(null); - const stopData = await loadStopData(region, stopId); + const stopData = await loadStopData(region, stop.stopId); setData(stopData); setLastUpdated(new Date()); } catch (err) { @@ -89,10 +88,10 @@ export const StopSheet: React.FC<StopSheetProps> = ({ }; useEffect(() => { - if (isOpen && stopId) { + if (isOpen && stop.stopId) { loadData(); } - }, [isOpen, stopId, region]); + }, [isOpen, stop.stopId, region]); const formatTime = (minutes: number) => { if (minutes > 15) { @@ -133,8 +132,16 @@ export const StopSheet: React.FC<StopSheetProps> = ({ <Sheet.Content> <div className="stop-sheet-content"> <div className="stop-sheet-header"> - <h2 className="stop-sheet-title">{stopName}</h2> - <span className="stop-sheet-id">({stopId})</span> + <h2 className="stop-sheet-title">{stop.name.original}</h2> + <span className="stop-sheet-id">({stop.stopId})</span> + </div> + + <div className="stop-sheet-lines-container"> + {stop.lines.map((line) => ( + <div key={line} className="stop-sheet-line-icon"> + <LineIcon line={line} region={region} rounded /> + </div> + ))} </div> {loading ? ( @@ -210,7 +217,7 @@ export const StopSheet: React.FC<StopSheetProps> = ({ </button> <Link - to={`/estimates/${stopId}`} + to={`/estimates/${stop.stopId}`} className="stop-sheet-view-all" onClick={onClose} > |
