import { useCallback, useState, useRef, useEffect } from "react"; import { useTranslation } from "react-i18next"; import * as Y from "yjs"; import type { YjsState } from "~/lib/use-yjs"; import { generateGpx } from "@trails-cool/gpx"; import type { TrackPoint, NoGoArea } from "@trails-cool/gpx"; function getTracks(yjs: YjsState): TrackPoint[][] { const geojsonStr = yjs.routeData.get("geojson") as string | undefined; if (!geojsonStr) return []; try { const geojson = JSON.parse(geojsonStr); const coords: number[][] = geojson.features?.[0]?.geometry?.coordinates ?? []; if (coords.length > 0) { return [coords.map((c) => ({ lat: c[1]!, lon: c[0]!, ele: c[2] }))]; } } catch { /* invalid geojson */ } return []; } function getWaypoints(yjs: YjsState) { return yjs.waypoints.toArray().map((yMap: Y.Map) => ({ lat: yMap.get("lat") as number, lon: yMap.get("lon") as number, name: yMap.get("name") as string | undefined, })); } function getNoGoAreas(yjs: YjsState): NoGoArea[] { return yjs.noGoAreas.toArray().map((yMap: Y.Map) => ({ points: (yMap.get("points") as Array<{ lat: number; lon: number }>) ?? [], })).filter((a) => a.points.length >= 3); } function download(gpx: string, filename: string) { const blob = new Blob([gpx], { type: "application/gpx+xml" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); } export function ExportButton({ yjs }: { yjs: YjsState }) { const { t } = useTranslation("planner"); const [open, setOpen] = useState(false); const ref = useRef(null); // Close dropdown on outside click useEffect(() => { if (!open) return; const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false); }; document.addEventListener("click", handler); return () => document.removeEventListener("click", handler); }, [open]); const handleExportRoute = useCallback(() => { const tracks = getTracks(yjs); const gpx = generateGpx({ name: "trails.cool route", waypoints: [], tracks }); download(gpx, "route.gpx"); setOpen(false); }, [yjs]); const handleExportPlan = useCallback(() => { const tracks = getTracks(yjs); const waypoints = getWaypoints(yjs); const noGoAreas = getNoGoAreas(yjs); const gpx = generateGpx({ name: "trails.cool route", waypoints, tracks, noGoAreas }); download(gpx, "route-plan.gpx"); setOpen(false); }, [yjs]); return (
{open && (
)}
); }