trails/apps/planner/app/components/ExportButton.tsx
Ullrich Schäfer 54b6232c5d
Complete Planner UI: profile selector, elevation chart, GPX export
- ProfileSelector: dropdown synced via Y.Map, triggers route recompute
  (Hiking, Cycling fast/safe, Shortest, Car profiles)
- ElevationChart: canvas-based elevation profile extracted from BRouter
  GeoJSON, shows min/max elevation and distance
- ExportButton: generates GPX from current waypoints + route track,
  downloads as route.gpx

All Groups 5 + 6 tasks complete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:57:39 +01:00

57 lines
1.7 KiB
TypeScript

import { useCallback } from "react";
import * as Y from "yjs";
import type { YjsState } from "~/lib/use-yjs";
import { generateGpx } from "@trails-cool/gpx";
import type { TrackPoint } from "@trails-cool/gpx";
export function ExportButton({ yjs }: { yjs: YjsState }) {
const handleExport = useCallback(() => {
// Get waypoints from Yjs
const waypoints = yjs.waypoints.toArray().map((yMap: Y.Map<unknown>) => ({
lat: yMap.get("lat") as number,
lon: yMap.get("lon") as number,
name: yMap.get("name") as string | undefined,
}));
// Get route track from GeoJSON
let tracks: TrackPoint[][] = [];
const geojsonStr = yjs.routeData.get("geojson") as string | undefined;
if (geojsonStr) {
try {
const geojson = JSON.parse(geojsonStr);
const coords: number[][] = geojson.features?.[0]?.geometry?.coordinates ?? [];
if (coords.length > 0) {
tracks = [
coords.map((c) => ({
lat: c[1]!,
lon: c[0]!,
ele: c[2],
})),
];
}
} catch {
// Invalid GeoJSON
}
}
const gpx = generateGpx({ name: "trails.cool route", waypoints, tracks });
// Download
const blob = new Blob([gpx], { type: "application/gpx+xml" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "route.gpx";
a.click();
URL.revokeObjectURL(url);
}, [yjs.waypoints, yjs.routeData]);
return (
<button
onClick={handleExport}
className="rounded bg-gray-100 px-3 py-1 text-sm text-gray-700 hover:bg-gray-200"
>
Export GPX
</button>
);
}