diff --git a/web/src/lib/components/trail/trail_info_panel.svelte b/web/src/lib/components/trail/trail_info_panel.svelte
index 711f95cb..8c295c07 100644
--- a/web/src/lib/components/trail/trail_info_panel.svelte
+++ b/web/src/lib/components/trail/trail_info_panel.svelte
@@ -38,7 +38,7 @@
const tabs = [
$_("description"),
- $_("waypoints"),
+ $_("waypoints", { values: { n: 2 } }),
$_("photos"),
$_("summit-book"),
...($currentUser ? [$_("comment", { values: { n: 2 } })] : []),
diff --git a/web/src/lib/i18n/locales/de.json b/web/src/lib/i18n/locales/de.json
index 5083e610..a7dd9b5f 100644
--- a/web/src/lib/i18n/locales/de.json
+++ b/web/src/lib/i18n/locales/de.json
@@ -40,6 +40,7 @@
"distance": "Distanz",
"documentation": "Dokumentation",
"download-gpx": "GPX herunterladen",
+ "draw-on-map": "",
"dutch": "Niederländisch",
"easy": "Einfach",
"edit": "Bearbeiten",
@@ -128,6 +129,7 @@
"show-on-map": "Auf der Karte anzeigen",
"slogan": "Speichere deine Abenteuer!",
"sort": "Sortieren",
+ "stop-drawing": "",
"summit-book": "Gipfelbuch",
"text": "Text",
"trail": "{n, plural, =1 {Route} other {Routen}}",
@@ -136,7 +138,7 @@
"upload-file": "Datei hochladen",
"upload-gpx": "GPX hochladen",
"username": "Nutzername",
- "waypoints": "Wegpunkte",
+ "waypoints": "{n, plural, =1 {Wegpunkt} other {Wegpunkte}}",
"welcome_to": "Willkommen bei",
"wrong-username-or-password": "Falscher Nutzername oder falsches Passwort"
}
diff --git a/web/src/lib/i18n/locales/en.json b/web/src/lib/i18n/locales/en.json
index 131cf09a..1a365926 100644
--- a/web/src/lib/i18n/locales/en.json
+++ b/web/src/lib/i18n/locales/en.json
@@ -40,6 +40,7 @@
"distance": "Distance",
"documentation": "Documentation",
"download-gpx": "Download GPX",
+ "draw-on-map": "Draw on map",
"dutch": "Dutch",
"easy": "Easy",
"edit": "Edit",
@@ -128,6 +129,7 @@
"show-on-map": "Show on map",
"slogan": "Save your adventures!",
"sort": "Sort",
+ "stop-drawing": "Stop drawing",
"summit-book": "Summit Book",
"text": "Text",
"trail": "{n, plural, =1 {Trail} other {Trails}}",
@@ -136,7 +138,7 @@
"upload-file": "Upload file",
"upload-gpx": "Upload GPX",
"username": "Username",
- "waypoints": "Waypoints",
+ "waypoints": "{n, plural, =1 {Waypoint} other {Waypoints}}",
"welcome_to": "Welcome to",
"wrong-username-or-password": "Wrong username or password"
}
diff --git a/web/src/lib/i18n/locales/fr.json b/web/src/lib/i18n/locales/fr.json
index ffba2cd3..4c3af7ca 100644
--- a/web/src/lib/i18n/locales/fr.json
+++ b/web/src/lib/i18n/locales/fr.json
@@ -40,6 +40,7 @@
"distance": "Distance",
"documentation": "Documentation",
"download-gpx": "Télécharger le GPX",
+ "draw-on-map": "",
"dutch": "Néerlandais",
"easy": "Facile",
"edit": "Editer",
@@ -128,6 +129,7 @@
"show-on-map": "Voir sur la carte",
"slogan": "Sauvegarder vos aventures !",
"sort": "Trier",
+ "stop-drawing": "",
"summit-book": "Livre du sommet",
"text": "Texte",
"trail": "{n, plural, =1 {Itinéraire} other {Itinéraires}}",
diff --git a/web/src/lib/i18n/locales/hu.json b/web/src/lib/i18n/locales/hu.json
index b84c910a..acbb5aa3 100644
--- a/web/src/lib/i18n/locales/hu.json
+++ b/web/src/lib/i18n/locales/hu.json
@@ -40,6 +40,7 @@
"distance": "Távolság",
"documentation": "Dokumentáció",
"download-gpx": "GPX letöltése",
+ "draw-on-map": "",
"dutch": "Holland",
"easy": "Könnyű",
"edit": "Szerkesztés",
@@ -128,6 +129,7 @@
"show-on-map": "Mutatás térképen",
"slogan": "Mentse el a kalandjait!",
"sort": "Rendezés",
+ "stop-drawing": "",
"summit-book": "Csúcspont könyv",
"text": "Szöveg",
"trail": "{n, plural, =1 {Útvonal} other {Útvonalak}}",
diff --git a/web/src/lib/i18n/locales/nl.json b/web/src/lib/i18n/locales/nl.json
index 9d7a11b9..764a177c 100644
--- a/web/src/lib/i18n/locales/nl.json
+++ b/web/src/lib/i18n/locales/nl.json
@@ -40,6 +40,7 @@
"distance": "Afstand",
"documentation": "Documentatie",
"download-gpx": "GPX-bestand downloaden",
+ "draw-on-map": "",
"dutch": "Nederlands",
"easy": "Makkelijk",
"edit": "Bewerken",
@@ -128,6 +129,7 @@
"show-on-map": "Tonen op kaart",
"slogan": "Bewaar je avonturen!",
"sort": "Sorteren",
+ "stop-drawing": "",
"summit-book": "Bergtopboek",
"text": "Tekst",
"trail": "{n, plural, =1 {wandelroute} other {wandelroutes}}",
diff --git a/web/src/lib/i18n/locales/pl.json b/web/src/lib/i18n/locales/pl.json
index 9ce4314a..0b22aca3 100644
--- a/web/src/lib/i18n/locales/pl.json
+++ b/web/src/lib/i18n/locales/pl.json
@@ -40,6 +40,7 @@
"distance": "Dystans",
"documentation": "Dokumentacja",
"download-gpx": "Popierz GPX",
+ "draw-on-map": "",
"dutch": "Niderlandzki",
"easy": "Łatwy",
"edit": "Edytuj",
@@ -128,6 +129,7 @@
"show-on-map": "Pokaż na mapie",
"slogan": "Zapisz swoją wyprawę!",
"sort": "Sortowanie",
+ "stop-drawing": "",
"summit-book": "Logbook",
"text": "Tekst",
"trail": "{n, plural, =1 {Szlak} other {Szlaki}}",
diff --git a/web/src/lib/i18n/locales/pt.json b/web/src/lib/i18n/locales/pt.json
index 3928d8f1..4e9c8028 100644
--- a/web/src/lib/i18n/locales/pt.json
+++ b/web/src/lib/i18n/locales/pt.json
@@ -40,6 +40,7 @@
"distance": "Distância",
"documentation": "Documentação",
"download-gpx": "Baixar GPX",
+ "draw-on-map": "",
"dutch": "Holandês",
"easy": "Fácil",
"edit": "Editar",
@@ -128,6 +129,7 @@
"show-on-map": "Mostrar no mapa",
"slogan": "Guarde as suas aventuras!",
"sort": "Ordenar",
+ "stop-drawing": "",
"summit-book": "Livro da cimeira",
"text": "Texto",
"trail": "{n, plural, =1 {Percurso} other {Percursos}}",
diff --git a/web/src/lib/i18n/locales/zh.json b/web/src/lib/i18n/locales/zh.json
index c5585021..b9a23232 100644
--- a/web/src/lib/i18n/locales/zh.json
+++ b/web/src/lib/i18n/locales/zh.json
@@ -40,6 +40,7 @@
"distance": "距离",
"documentation": "文档",
"download-gpx": "下载 GPX",
+ "draw-on-map": "",
"dutch": "荷兰语",
"easy": "简单",
"edit": "编辑",
@@ -128,6 +129,7 @@
"show-on-map": "地图中展示",
"slogan": "保存你的冒险!",
"sort": "排序",
+ "stop-drawing": "",
"summit-book": "详细日程",
"text": "文本",
"trail": "{n, plural, =1 {路线} other {路线}}",
diff --git a/web/src/lib/models/valhalla.ts b/web/src/lib/models/valhalla.ts
new file mode 100644
index 00000000..9350d6b7
--- /dev/null
+++ b/web/src/lib/models/valhalla.ts
@@ -0,0 +1,31 @@
+interface ValhallaResponse {
+ trip: {
+ legs: {
+ shape: string[];
+ }[];
+ };
+}
+
+class ValhallaRoute {
+ type: "Feature";
+ properties: {};
+ geometry: {
+ type: "LineString";
+ coordinates: number[][];
+ };
+
+ constructor() {
+ this.type = "Feature"
+ this.properties = {}
+ this.geometry = {
+ type: "LineString",
+ coordinates: []
+ }
+ }
+
+ toString() {
+ return JSON.stringify(this);
+ }
+}
+
+export {type ValhallaResponse, ValhallaRoute}
\ No newline at end of file
diff --git a/web/src/lib/stores/valhalla_store.ts b/web/src/lib/stores/valhalla_store.ts
new file mode 100644
index 00000000..8ed1001b
--- /dev/null
+++ b/web/src/lib/stores/valhalla_store.ts
@@ -0,0 +1,79 @@
+import { ValhallaRoute, type ValhallaResponse } from "$lib/models/valhalla";
+import { ClientResponseError } from "pocketbase";
+
+
+
+export const route: ValhallaRoute = new ValhallaRoute();
+
+
+export function clearRoute() {
+ route.geometry.coordinates = [];
+}
+
+export async function calculateRouteBetween(startLat: number, startLon: number, endLat: number, endLon: number) {
+ const requestBody = {
+ "directions_type": "none",
+ "locations": [{ "lat": startLat, "lon": startLon }, { "lat": endLat, "lon": endLon }],
+ "costing": "pedestrian", "costing_options": { "pedestrian": { "max_hiking_difficulty": 6, "use_ferry": 0 } }
+ }
+ const r = await fetch("/api/v1/valhalla", { method: "POST", body: JSON.stringify(requestBody) })
+ if (!r.ok) {
+ throw new ClientResponseError(await r.json())
+ }
+ const response: ValhallaResponse = await r.json();
+
+ appendToRoute(response);
+}
+
+function appendToRoute(valhallaResponse: any) {
+ const routeGeometry = decodeShape(valhallaResponse.trip.legs[0].shape);
+
+ for (const point of routeGeometry) {
+ route.geometry.coordinates.push([point[1], point[0]])
+ }
+}
+
+
+function decodeShape(shape: string, precision: number = 6) {
+ var index = 0,
+ lat = 0,
+ lng = 0,
+ coordinates = [],
+ shift = 0,
+ result = 0,
+ byte = null,
+ latitude_change,
+ longitude_change,
+ factor = Math.pow(10, precision);
+
+ while (index < shape.length) {
+ byte = null;
+ shift = 0;
+ result = 0;
+
+ do {
+ byte = shape.charCodeAt(index++) - 63;
+ result |= (byte & 0x1f) << shift;
+ shift += 5;
+ } while (byte >= 0x20);
+
+ latitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
+
+ shift = result = 0;
+
+ do {
+ byte = shape.charCodeAt(index++) - 63;
+ result |= (byte & 0x1f) << shift;
+ shift += 5;
+ } while (byte >= 0x20);
+
+ longitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
+
+ lat += latitude_change;
+ lng += longitude_change;
+
+ coordinates.push([lat / factor, lng / factor]);
+ }
+
+ return coordinates;
+};
\ No newline at end of file
diff --git a/web/src/routes/api/v1/valhalla/+server.ts b/web/src/routes/api/v1/valhalla/+server.ts
index 275b5228..60d0f70c 100644
--- a/web/src/routes/api/v1/valhalla/+server.ts
+++ b/web/src/routes/api/v1/valhalla/+server.ts
@@ -1,16 +1,20 @@
-import { error, json, type RequestEvent } from "@sveltejs/kit";
-import { env } from '$env/dynamic/public'
+import { env } from '$env/dynamic/public';
+import { error, json, type NumericRange, type RequestEvent } from "@sveltejs/kit";
export async function POST(event: RequestEvent) {
const data = await event.request.json()
- if(!env.PUBLIC_VALHALLA_URL) {
+ if (!env.PUBLIC_VALHALLA_URL) {
return error(400, "PUBLIC_VALHALLA_URL not set")
}
try {
- const r = await event.fetch(env.PUBLIC_VALHALLA_URL + '/route', data);
- return json(r);
+ const r = await event.fetch(env.PUBLIC_VALHALLA_URL + '/route', { method: "POST", body: JSON.stringify(data) });
+ const response = await r.json();
+ if (!r.ok) {
+ throw error(r.status as NumericRange<400,500>, response);
+ }
+ return json(response);
} catch (e: any) {
- throw error(e.status, e)
+ throw error(e.status || 500, e)
}
}
\ No newline at end of file
diff --git a/web/src/routes/trail/edit/[id]/+page.svelte b/web/src/routes/trail/edit/[id]/+page.svelte
index dabf307c..744e04cf 100644
--- a/web/src/routes/trail/edit/[id]/+page.svelte
+++ b/web/src/routes/trail/edit/[id]/+page.svelte
@@ -1,4 +1,5 @@
@@ -342,9 +392,21 @@
on:submit={handleSubmit}
>
{$_("pick-a-trail")}
- {$_("upload-file")}
+ {#if PUBLIC_VALHALLA_URL}
+
+ {/if}
- {$_("waypoints")}
+
+ {$_("waypoints", { values: { n: 2 } })}
+
{#each $form.expand.waypoints ?? [] as waypoint, i}
- openMarkerPopup(waypoint)}>
@@ -549,7 +613,13 @@
{loading}>{$_("save-trail")}
-
+ handleMapClick(e.detail)}
+ >