- 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>
57 lines
1.7 KiB
TypeScript
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>
|
|
);
|
|
}
|