import { useState, useCallback } 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"; interface SaveToJournalButtonProps { yjs: YjsState; callbackUrl: string; callbackToken: string; returnUrl?: string; } export function SaveToJournalButton({ yjs, callbackUrl, callbackToken, returnUrl }: SaveToJournalButtonProps) { const { t } = useTranslation("planner"); const [saving, setSaving] = useState(false); const [saved, setSaved] = useState(false); const [error, setError] = useState(null); const handleSave = useCallback(async () => { setSaving(true); setError(null); try { // Build GPX from computed track with planning data (no-go areas) // so the route round-trips correctly through the journal. 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 noGoAreas: NoGoArea[] = yjs.noGoAreas.toArray().map((yMap: Y.Map) => ({ points: (yMap.get("points") as Array<{ lat: number; lon: number }>) ?? [], })).filter((a) => a.points.length >= 3); const waypoints = 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, isDayBreak: yMap.get("overnight") === true ? true : undefined, })); const notes = yjs.notes.toString() || undefined; const gpx = generateGpx({ name: "trails.cool route", description: notes, waypoints, tracks, noGoAreas }); // POST to Journal callback const response = await fetch(callbackUrl, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${callbackToken}`, }, body: JSON.stringify({ gpx }), }); if (!response.ok) { const result = await response.json(); throw new Error(result.error ?? "Save failed"); } setSaved(true); } catch (err) { setError((err as Error).message); } finally { setSaving(false); } }, [yjs, callbackUrl, callbackToken]); return (
{saved && {t("saved")}} {error && {error}} {saved && returnUrl && ( {t("returnToJournal")} )}
); }