diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2026-04-20 13:41:35 +0200 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2026-04-20 13:41:35 +0200 |
| commit | f2a37bc6366beccce247f834adee752b8e6323ae (patch) | |
| tree | bb893100ebb8a9ca6f057410adf83e293cfa1123 /src/frontend | |
| parent | 23b6fb227a1b840a36864bdebc4de89c19fd6463 (diff) | |
Distinguir pasos de subida y salida (inicio trayecto), y pasos de bajada de llegada (final trayecto)
Puede ser importante distinguir entre un viaje que solo permite bajar en un punto, y un viaje que finaliza ahí, ya que puede tener sentido ocultar los viajes que terminan en algunos feeds. Por otra parte, es útil saber que ciertos viajes salen de ese sitio, frente a ser pasantes de subida, porque el vehículo suele estar con antelación
Diffstat (limited to 'src/frontend')
| -rw-r--r-- | src/frontend/app/api/schema.ts | 8 | ||||
| -rw-r--r-- | src/frontend/app/components/arrivals/ArrivalCard.tsx | 43 | ||||
| -rw-r--r-- | src/frontend/app/components/arrivals/ReducedArrivalCard.tsx | 30 |
3 files changed, 63 insertions, 18 deletions
diff --git a/src/frontend/app/api/schema.ts b/src/frontend/app/api/schema.ts index 64a9e94..71eeae9 100644 --- a/src/frontend/app/api/schema.ts +++ b/src/frontend/app/api/schema.ts @@ -66,7 +66,13 @@ export const ArrivalSchema = z.object({ currentPosition: PositionSchema.optional().nullable(), vehicleInformation: VehicleInformationSchema.optional().nullable(), operator: z.string().nullable(), - operation: z.enum(["pickup_dropoff", "pickup_only", "dropoff_only"]), + operation: z.enum([ + "pickup_dropoff", + "pickup_only", + "dropoff_only", + "departure", + "arrival", + ]), }); export const ArrivalEstimateSchema = z.object({ diff --git a/src/frontend/app/components/arrivals/ArrivalCard.tsx b/src/frontend/app/components/arrivals/ArrivalCard.tsx index 827599e..51e0803 100644 --- a/src/frontend/app/components/arrivals/ArrivalCard.tsx +++ b/src/frontend/app/components/arrivals/ArrivalCard.tsx @@ -5,13 +5,18 @@ import { BusFront, LocateIcon, Navigation, + SquareArrowRightEnter, + SquareArrowRightExit, } from "lucide-react"; import React, { useEffect, useMemo, useRef, useState } from "react"; -import Marquee from "react-fast-marquee"; +import _MarqueeImport from "react-fast-marquee"; import { useTranslation } from "react-i18next"; import RouteIcon from "~/components/RouteIcon"; import { type Arrival } from "../../api/schema"; import "./ArrivalCard.css"; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const Marquee: typeof _MarqueeImport = + (_MarqueeImport as any).default ?? _MarqueeImport; interface ArrivalCardProps { arrival: Arrival; @@ -96,6 +101,22 @@ export const ArrivalCard: React.FC<ArrivalCardProps> = ({ } }, [estimate.precision]); + const OPERATION_LABELS: Record<string, string> = { + pickup_only: t("journey.pickup_only", "Solo subida"), + dropoff_only: t("journey.dropoff_only", "Solo bajada"), + departure: t("journey.departure", "Salida"), + arrival: t("journey.arrival", "Llegada"), + }; + + type OperationKind = "pickup" | "dropoff" | "departure" | "arrival"; + + const OPERATION_KINDS: Record<string, OperationKind> = { + pickup_only: "pickup", + dropoff_only: "dropoff", + departure: "departure", + arrival: "arrival", + }; + const metaChips = useMemo(() => { const chips: Array<{ label: string; @@ -106,18 +127,14 @@ export const ArrivalCard: React.FC<ArrivalCardProps> = ({ | "delay" | "warning" | "vehicle" - | "pickup" - | "dropoff"; + | OperationKind; }> = []; if (operation !== "pickup_dropoff") { chips.push({ - label: - operation === "pickup_only" - ? t("journey.pickup_only", "Solo subida") - : t("journey.dropoff_only", "Solo bajada"), - tone: operation === "pickup_only" ? "pickup" : "dropoff", - kind: operation === "pickup_only" ? "pickup" : "dropoff", + label: OPERATION_LABELS[operation] || operation, + tone: OPERATION_KINDS[operation] || "regular", + kind: OPERATION_KINDS[operation] || "regular", }); } @@ -258,10 +275,12 @@ export const ArrivalCard: React.FC<ArrivalCardProps> = ({ let chipColourClasses = ""; switch (chip.tone) { case "pickup": + case "departure": chipColourClasses = "bg-green-600/10 dark:bg-green-600/20 text-green-700 dark:text-green-300"; break; case "dropoff": + case "arrival": chipColourClasses = "bg-orange-400/10 dark:bg-orange-600/20 text-orange-700 dark:text-orange-300"; break; @@ -310,6 +329,12 @@ export const ArrivalCard: React.FC<ArrivalCardProps> = ({ {chip.kind === "dropoff" && ( <ArrowDownRightSquare className="w-3 h-3 inline-block" /> )} + {chip.kind === "departure" && ( + <SquareArrowRightExit className="w-3 h-3 inline-block" /> + )} + {chip.kind === "arrival" && ( + <SquareArrowRightEnter className="w-3 h-3 inline-block" /> + )} {chip.label} </span> diff --git a/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx b/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx index 6046ffc..6d6bf85 100644 --- a/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx +++ b/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx @@ -47,6 +47,22 @@ export const ReducedArrivalCard: React.FC<ArrivalCardProps> = ({ } }, [estimate.precision]); + const OPERATION_LABELS: Record<string, string> = { + pickup_only: t("journey.pickup_only", "Solo subida"), + dropoff_only: t("journey.dropoff_only", "Solo bajada"), + departure: t("journey.departure", "Salida"), + arrival: t("journey.arrival", "Llegada"), + }; + + type OperationKind = "pickup" | "dropoff" | "departure" | "arrival"; + + const OPERATION_KINDS: Record<string, OperationKind> = { + pickup_only: "pickup", + dropoff_only: "dropoff", + departure: "departure", + arrival: "arrival", + }; + const metaChips = useMemo(() => { const chips: Array<{ label: string; @@ -57,18 +73,14 @@ export const ReducedArrivalCard: React.FC<ArrivalCardProps> = ({ | "delay" | "warning" | "vehicle" - | "pickup" - | "dropoff"; + | OperationKind; }> = []; if (operation !== "pickup_dropoff") { chips.push({ - label: - operation === "pickup_only" - ? t("journey.pickup_only", "Solo subida") - : t("journey.dropoff_only", "Solo bajada"), - tone: operation === "pickup_only" ? "pickup" : "dropoff", - kind: operation === "pickup_only" ? "pickup" : "dropoff", + label: OPERATION_LABELS[operation] || operation, + tone: OPERATION_KINDS[operation] || "regular", + kind: OPERATION_KINDS[operation] || "regular", }); } @@ -210,10 +222,12 @@ export const ReducedArrivalCard: React.FC<ArrivalCardProps> = ({ let chipColourClasses = ""; switch (chip.tone) { case "pickup": + case "departure": chipColourClasses = "bg-green-600/10 dark:bg-green-600/20 text-green-700 dark:text-green-300"; break; case "dropoff": + case "arrival": chipColourClasses = "bg-orange-400/10 dark:bg-orange-600/20 text-orange-700 dark:text-orange-300"; break; |
