aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/data
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2025-12-12 10:24:43 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2025-12-12 10:24:54 +0100
commit3a1a1e6dc2f6f0abceac5da0cfb530fdb45fc6f5 (patch)
tree0b887eece835ff12ebd2eea831483407223e1a22 /src/frontend/app/data
parentd65ce8288bbda3cb6e0b37613c29d7bf52703ba7 (diff)
Initial ultra-ñapa implementation of OTP integration
Diffstat (limited to 'src/frontend/app/data')
-rw-r--r--src/frontend/app/data/PlannerApi.ts96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/frontend/app/data/PlannerApi.ts b/src/frontend/app/data/PlannerApi.ts
new file mode 100644
index 0000000..db47dcc
--- /dev/null
+++ b/src/frontend/app/data/PlannerApi.ts
@@ -0,0 +1,96 @@
+export interface PlannerSearchResult {
+ name?: string;
+ label?: string;
+ lat: number;
+ lon: number;
+ layer?: string;
+}
+
+export interface RoutePlan {
+ itineraries: Itinerary[];
+}
+
+export interface Itinerary {
+ durationSeconds: number;
+ startTime: string;
+ endTime: string;
+ walkDistanceMeters: number;
+ walkTimeSeconds: number;
+ transitTimeSeconds: number;
+ waitingTimeSeconds: number;
+ legs: Leg[];
+}
+
+export interface Leg {
+ mode?: string;
+ routeName?: string;
+ routeShortName?: string;
+ routeLongName?: string;
+ headsign?: string;
+ agencyName?: string;
+ from?: PlannerPlace;
+ to?: PlannerPlace;
+ startTime: string;
+ endTime: string;
+ distanceMeters: number;
+ geometry?: PlannerGeometry;
+ steps: Step[];
+}
+
+export interface PlannerPlace {
+ name?: string;
+ lat: number;
+ lon: number;
+ stopId?: string;
+ stopCode?: string;
+}
+
+export interface PlannerGeometry {
+ type: string;
+ coordinates: number[][];
+}
+
+export interface Step {
+ distanceMeters: number;
+ relativeDirection?: string;
+ absoluteDirection?: string;
+ streetName?: string;
+ lat: number;
+ lon: number;
+}
+
+export async function searchPlaces(
+ query: string
+): Promise<PlannerSearchResult[]> {
+ const response = await fetch(
+ `/api/planner/autocomplete?query=${encodeURIComponent(query)}`
+ );
+ if (!response.ok) return [];
+ return response.json();
+}
+
+export async function reverseGeocode(
+ lat: number,
+ lon: number
+): Promise<PlannerSearchResult | null> {
+ const response = await fetch(`/api/planner/reverse?lat=${lat}&lon=${lon}`);
+ if (!response.ok) return null;
+ return response.json();
+}
+
+export async function planRoute(
+ fromLat: number,
+ fromLon: number,
+ toLat: number,
+ toLon: number,
+ time?: Date,
+ arriveBy: boolean = false
+): Promise<RoutePlan> {
+ let url = `/api/planner/plan?fromLat=${fromLat}&fromLon=${fromLon}&toLat=${toLat}&toLon=${toLon}&arriveBy=${arriveBy}`;
+ if (time) {
+ url += `&time=${time.toISOString()}`;
+ }
+ const response = await fetch(url);
+ if (!response.ok) throw new Error("Failed to plan route");
+ return response.json();
+}