diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-16 16:44:43 +0100 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-16 16:44:43 +0100 |
| commit | fbcf5ecb762b3cff314b9339aec3314bb813a3fe (patch) | |
| tree | 7a4237ddb06188decf35aedd60f13c5c078429dc | |
| parent | ac626a9c2edc2e528eb0b39002c836a747b2fc16 (diff) | |
Display operator name on xunta arrivals
7 files changed, 69 insertions, 11 deletions
diff --git a/src/Enmarcha.Backend/Controllers/ArrivalsController.cs b/src/Enmarcha.Backend/Controllers/ArrivalsController.cs index 861038f..8ce63f7 100644 --- a/src/Enmarcha.Backend/Controllers/ArrivalsController.cs +++ b/src/Enmarcha.Backend/Controllers/ArrivalsController.cs @@ -146,6 +146,8 @@ public partial class ArrivalsController : ControllerBase var tz = TimeZoneInfo.FindSystemTimeZoneById("Europe/Madrid"); var nowLocal = TimeZoneInfo.ConvertTime(DateTime.UtcNow, tz); + var feedId = id.Split(':')[0]; + var requestContent = ArrivalsAtStopContent.Query(new ArrivalsAtStopContent.Args(id, reduced || nano)); var request = new HttpRequestMessage(HttpMethod.Post, $"{_config.OpenTripPlannerBaseUrl}/gtfs/v1"); @@ -192,6 +194,7 @@ public partial class ArrivalsController : ControllerBase Minutes = minutesToArrive, Precision = departureTime < nowLocal.AddMinutes(-1) ? ArrivalPrecision.Past : ArrivalPrecision.Scheduled }, + Operator = feedId == "xunta" ? item.Trip.Route.Agency?.Name : null, RawOtpTrip = item }); } diff --git a/src/Enmarcha.Backend/Services/Processors/NextStopsProcessor.cs b/src/Enmarcha.Backend/Services/Processors/NextStopsProcessor.cs index 84e0d0f..6a76fe3 100644 --- a/src/Enmarcha.Backend/Services/Processors/NextStopsProcessor.cs +++ b/src/Enmarcha.Backend/Services/Processors/NextStopsProcessor.cs @@ -94,7 +94,7 @@ public class NextStopsProcessor : IArrivalsProcessor if (!seenConcellos.Contains(concello)) { seenConcellos.Add(concello); - item += $" ({concello})"; + item = $"({concello}) {item}"; } items.Add(item); diff --git a/src/Enmarcha.Backend/Types/Arrivals/Arrival.cs b/src/Enmarcha.Backend/Types/Arrivals/Arrival.cs index a07c988..bdcae07 100644 --- a/src/Enmarcha.Backend/Types/Arrivals/Arrival.cs +++ b/src/Enmarcha.Backend/Types/Arrivals/Arrival.cs @@ -20,6 +20,9 @@ public class Arrival [JsonPropertyName("currentPosition")] public Position? CurrentPosition { get; set; } + [JsonPropertyName("operator")] public string? Operator { get; set; } + [JsonPropertyName("operation")] public VehicleOperation Operation { get; set; } = VehicleOperation.PickupDropoff; + [JsonPropertyName("vehicleInformation")] public VehicleBadge? VehicleInformation { get; set; } @@ -35,6 +38,16 @@ public class Arrival [JsonIgnore] public bool Delete { get; set; } } +public enum VehicleOperation +{ + [JsonStringEnumMemberName("pickup_dropoff")] + PickupDropoff = 0, + [JsonStringEnumMemberName("pickup_only")] + PickupOnly = 1, + [JsonStringEnumMemberName("dropoff_only")] + DropoffOnly = 2 +} + public class RouteInfo { [JsonPropertyName("gtfsId")] public required string GtfsId { get; set; } diff --git a/src/Enmarcha.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs b/src/Enmarcha.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs index 7cf107a..2ad30e5 100644 --- a/src/Enmarcha.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs +++ b/src/Enmarcha.Sources.OpenTripPlannerGql/Queries/ArrivalsAtStop.cs @@ -43,6 +43,9 @@ public class ArrivalsAtStopContent : IGraphRequest<ArrivalsAtStopContent.Args> color textColor longName + agency {{ + name + }} }} departureStoptime {{ scheduledDeparture @@ -190,6 +193,12 @@ public class ArrivalsAtStopResponse : AbstractGraphResponse [JsonPropertyName("textColor")] public string? TextColor { get; set; } [JsonPropertyName("longName")] public string? LongName { get; set; } + [JsonPropertyName("agency")] public AgencyDetails? Agency { get; set; } + } + + public class AgencyDetails + { + [JsonPropertyName("name")] public required string Name { get; set; } } public class PickupType diff --git a/src/frontend/app/api/schema.ts b/src/frontend/app/api/schema.ts index f68d413..20daede 100644 --- a/src/frontend/app/api/schema.ts +++ b/src/frontend/app/api/schema.ts @@ -65,6 +65,7 @@ export const ArrivalSchema = z.object({ shape: z.any().optional().nullable(), currentPosition: PositionSchema.optional().nullable(), vehicleInformation: VehicleInformationSchema.optional().nullable(), + operator: z.string().nullable(), }); export const ArrivalEstimateSchema = z.object({ diff --git a/src/frontend/app/components/arrivals/ArrivalCard.tsx b/src/frontend/app/components/arrivals/ArrivalCard.tsx index b99d3aa..bdd20a5 100644 --- a/src/frontend/app/components/arrivals/ArrivalCard.tsx +++ b/src/frontend/app/components/arrivals/ArrivalCard.tsx @@ -59,8 +59,15 @@ export const ArrivalCard: React.FC<ArrivalCardProps> = ({ onClick, }) => { const { t } = useTranslation(); - const { route, headsign, estimate, delay, shift, vehicleInformation } = - arrival; + const { + route, + headsign, + estimate, + delay, + shift, + vehicleInformation, + operator, + } = arrival; const etaValue = estimate.minutes.toString(); const etaUnit = t("estimates.minutes", "min"); @@ -211,11 +218,15 @@ export const ArrivalCard: React.FC<ArrivalCardProps> = ({ > {headsign.destination} </span> - {headsign.marquee && ( - <div className="mt-0.5 w-auto"> - <AutoMarquee text={headsign.marquee} /> - </div> - )} + <div className="mt-0.5 w-auto flex"> + {operator && ( + <span className="text-xs font-mono text-slate-700 dark:text-slate-200 font-medium shrink-0"> + {operator} + {headsign.marquee && <> ยท </>} + </span> + )} + {headsign.marquee && <AutoMarquee text={headsign.marquee} />} + </div> </div> </div> </div> diff --git a/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx b/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx index 27d97b3..19cc8d9 100644 --- a/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx +++ b/src/frontend/app/components/arrivals/ReducedArrivalCard.tsx @@ -15,8 +15,15 @@ export const ReducedArrivalCard: React.FC<ArrivalCardProps> = ({ onClick, }) => { const { t } = useTranslation(); - const { route, headsign, estimate, delay, shift, vehicleInformation } = - arrival; + const { + route, + headsign, + estimate, + delay, + shift, + vehicleInformation, + operator, + } = arrival; const etaValue = estimate.minutes.toString(); const etaUnit = t("estimates.minutes", "min"); @@ -41,6 +48,13 @@ export const ReducedArrivalCard: React.FC<ArrivalCardProps> = ({ kind?: "regular" | "gps" | "delay" | "warning" | "vehicle"; }> = []; + if (operator) { + chips.push({ + label: operator, + kind: "regular", + }); + } + // Badge/Shift info as a chip if (headsign.badge) { chips.push({ @@ -130,7 +144,14 @@ export const ReducedArrivalCard: React.FC<ArrivalCardProps> = ({ } return chips; - }, [delay, shift, estimate.precision, headsign.badge, vehicleInformation]); + }, [ + delay, + shift, + estimate.precision, + headsign.badge, + vehicleInformation, + operator, + ]); const isClickable = !!onClick && estimate.precision !== "past"; const Tag = isClickable ? "button" : "div"; |
