From 2dc3b7e5c6bf69405725735695f17bd3a79b87d9 Mon Sep 17 00:00:00 2001 From: Aaron Brethorst Date: Tue, 5 Nov 2024 21:07:44 -0800 Subject: [PATCH] Foundational work for trip planner integration --- .env.example | 1 + README.md | 5 + src/components/search/SearchPane.svelte | 116 +++++++++++++----------- src/routes/api/otp/plan/+server.js | 31 +++++++ 4 files changed, 98 insertions(+), 55 deletions(-) create mode 100644 src/routes/api/otp/plan/+server.js diff --git a/.env.example b/.env.example index 1e38ce5..d7393d0 100644 --- a/.env.example +++ b/.env.example @@ -9,3 +9,4 @@ PRIVATE_OBA_GEOCODER_PROVIDER="google" PUBLIC_OBA_LOGO_URL="https://onebusaway.org/wp-content/uploads/oba_logo-1.png" PUBLIC_OBA_MAP_PROVIDER="osm" PUBLIC_NAV_BAR_LINKS={"Home": "/","About": "/about","Contact": "/contact","Fares & Tolls": "/fares-and-tolls"} +PUBLIC_OTP_SERVER_URL="" \ No newline at end of file diff --git a/README.md b/README.md index d4f8635..e36ce80 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,11 @@ See `.env.example` for an example of the required keys and values. - `PRIVATE_OBA_GEOCODER_API_KEY` - string: Your Geocoder service's API key. Leave this blank if you don't have one. - `PRIVATE_OBA_GEOCODER_PROVIDER` - string: Your Geocoder service. We currently only support the Google Places SDK (value: "google"). + +### Trip Planner + +- `PUBLIC_OTP_SERVER_URL` - string: Your OpenTripPlanner 1.x-compatible trip planner server URL. Leave this blank if you don't have one. + ## Building To create a production version of your app: diff --git a/src/components/search/SearchPane.svelte b/src/components/search/SearchPane.svelte index a37d00d..963f26c 100644 --- a/src/components/search/SearchPane.svelte +++ b/src/components/search/SearchPane.svelte @@ -8,6 +8,7 @@ import { t } from 'svelte-i18n'; import { clearVehicleMarkersMap, fetchAndUpdateVehicles } from '$lib/vehicleUtils'; import { calculateMidpoint } from '$lib/mathUtils'; + import { Tabs, TabItem } from 'flowbite-svelte'; const dispatch = createEventDispatcher(); @@ -107,63 +108,68 @@ }); -
-
- - - {#if query} -

- {$t('search.results_for')} "{query}". - -

- {/if} - -
- {#if location} - handleLocationClick(location)} - title={location.formatted_address} - icon={faMapPin} - subtitle={location.types.join(', ')} - /> - {/if} - - {#if routes?.length > 0} - {#each routes as route} - handleRouteClick(route)} - icon={prioritizedRouteTypeForDisplay(route.type)} - title={`${$t('route')} ${route.nullSafeShortName || route.id}`} - subtitle={route.description} - /> - {/each} +
+ + + + + {#if query} +

+ {$t('search.results_for')} "{query}". + +

{/if} - {#if stops?.length > 0} - {#each stops as stop} +
+ {#if location} handleStopClick(stop)} - icon={faSignsPost} - title={stop.name} - subtitle={`${compassDirection(stop.direction)}; Code: ${stop.code}`} + on:click={() => handleLocationClick(location)} + title={location.formatted_address} + icon={faMapPin} + subtitle={location.types.join(', ')} /> - {/each} - {/if} -
- -
- - - {$t('search.for_a_list_of_available_routes')} -
-
+ {/if} + + {#if routes?.length > 0} + {#each routes as route} + handleRouteClick(route)} + icon={prioritizedRouteTypeForDisplay(route.type)} + title={`${$t('route')} ${route.nullSafeShortName || route.id}`} + subtitle={route.description} + /> + {/each} + {/if} + + {#if stops?.length > 0} + {#each stops as stop} + handleStopClick(stop)} + icon={faSignsPost} + title={stop.name} + subtitle={`${compassDirection(stop.direction)}; Code: ${stop.code}`} + /> + {/each} + {/if} +
+ +
+ + + {$t('search.for_a_list_of_available_routes')} +
+ + + plan a trip UI goes here! + +
diff --git a/src/routes/api/otp/plan/+server.js b/src/routes/api/otp/plan/+server.js new file mode 100644 index 0000000..1f76039 --- /dev/null +++ b/src/routes/api/otp/plan/+server.js @@ -0,0 +1,31 @@ +import { error, json } from '@sveltejs/kit'; + +export async function GET() { + try { + const response = await fetch( + 'https://otp.prod.sound.obaweb.org/otp/routers/default/plan?fromPlace=47.5423055%2C-122.38677&toPlace=47.639376%2C-122.128238', + { + headers: { + 'Accept': 'application/json' + } + } + ); + + if (!response.ok) { + throw error(response.status, `OpenTripPlanner API returned status ${response.status}`); + } + + const data = await response.json(); + return json(data); + + } catch (err) { + // If it's already a SvelteKit error, rethrow it + if (err.status) throw err; + + // Otherwise wrap it in a 500 error + throw error(500, { + message: 'Failed to fetch trip planning data', + error: err.message + }); + } +} \ No newline at end of file