From f81ff82f2a07f87f6eb4f43de49ede64215519e5 Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Sat, 27 Dec 2025 16:39:09 +0100 Subject: Refactor route planner to use new GraphQL backend --- src/frontend/app/api/planner.ts | 34 ++++++++++++++++++++ src/frontend/app/api/schema.ts | 69 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/frontend/app/api/planner.ts (limited to 'src/frontend/app/api') diff --git a/src/frontend/app/api/planner.ts b/src/frontend/app/api/planner.ts new file mode 100644 index 0000000..86f44f0 --- /dev/null +++ b/src/frontend/app/api/planner.ts @@ -0,0 +1,34 @@ +import { RoutePlanSchema, type RoutePlan } from "./schema"; + +export const fetchPlan = async ( + fromLat: number, + fromLon: number, + toLat: number, + toLon: number, + time?: Date, + arriveBy: boolean = false +): Promise => { + let url = `/api/planner/plan?fromLat=${fromLat}&fromLon=${fromLon}&toLat=${toLat}&toLon=${toLon}&arriveBy=${arriveBy}`; + if (time) { + url += `&time=${time.toISOString()}`; + } + + const resp = await fetch(url, { + headers: { + Accept: "application/json", + }, + }); + + if (!resp.ok) { + throw new Error(`HTTP ${resp.status}: ${resp.statusText}`); + } + + const data = await resp.json(); + try { + return RoutePlanSchema.parse(data); + } catch (e) { + console.error("Zod parsing failed for route plan:", e); + console.log("Received data:", data); + throw e; + } +}; diff --git a/src/frontend/app/api/schema.ts b/src/frontend/app/api/schema.ts index 9cc5bd4..05f3a87 100644 --- a/src/frontend/app/api/schema.ts +++ b/src/frontend/app/api/schema.ts @@ -8,7 +8,7 @@ export const RouteInfoSchema = z.object({ export const HeadsignInfoSchema = z.object({ badge: z.string().optional().nullable(), - destination: z.string(), + destination: z.string().nullable(), marquee: z.string().optional().nullable(), }); @@ -108,3 +108,70 @@ export const ConsolidatedCirculationSchema = z.object({ export type ConsolidatedCirculation = z.infer< typeof ConsolidatedCirculationSchema >; + +// Route Planner +export const PlannerPlaceSchema = z.object({ + name: z.string().optional().nullable(), + lat: z.number(), + lon: z.number(), + stopId: z.string().optional().nullable(), + stopCode: z.string().optional().nullable(), +}); + +export const PlannerGeometrySchema = z.object({ + type: z.string(), + coordinates: z.array(z.array(z.number())), +}); + +export const PlannerStepSchema = z.object({ + distanceMeters: z.number(), + relativeDirection: z.string().optional().nullable(), + absoluteDirection: z.string().optional().nullable(), + streetName: z.string().optional().nullable(), + lat: z.number(), + lon: z.number(), +}); + +export const PlannerLegSchema = z.object({ + mode: z.string().optional().nullable(), + routeName: z.string().optional().nullable(), + routeShortName: z.string().optional().nullable(), + routeLongName: z.string().optional().nullable(), + routeColor: z.string().optional().nullable(), + routeTextColor: z.string().optional().nullable(), + headsign: z.string().optional().nullable(), + agencyName: z.string().optional().nullable(), + from: PlannerPlaceSchema.optional().nullable(), + to: PlannerPlaceSchema.optional().nullable(), + startTime: z.string(), + endTime: z.string(), + distanceMeters: z.number(), + geometry: PlannerGeometrySchema.optional().nullable(), + steps: z.array(PlannerStepSchema), + intermediateStops: z.array(PlannerPlaceSchema), +}); + +export const ItinerarySchema = z.object({ + durationSeconds: z.number(), + startTime: z.string(), + endTime: z.string(), + walkDistanceMeters: z.number(), + walkTimeSeconds: z.number(), + transitTimeSeconds: z.number(), + waitingTimeSeconds: z.number(), + legs: z.array(PlannerLegSchema), + cashFareEuro: z.number().optional().nullable(), + cardFareEuro: z.number().optional().nullable(), +}); + +export const RoutePlanSchema = z.object({ + itineraries: z.array(ItinerarySchema), + timeOffsetSeconds: z.number().optional().nullable(), +}); + +export type PlannerPlace = z.infer; +export type PlannerGeometry = z.infer; +export type PlannerStep = z.infer; +export type PlannerLeg = z.infer; +export type Itinerary = z.infer; +export type RoutePlan = z.infer; -- cgit v1.3