Initialize no-go areas client-side via URL params
In dev mode, the sessions API and the Yjs WebSocket server are separate processes (Vite plugin vs React Router action), so server-side Yjs doc initialization doesn't reach the client. Now no-go areas flow the same way as waypoints: API response → URL params → client-side Yjs initialization. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fdfacd2997
commit
b6179fbdd2
5 changed files with 26 additions and 8 deletions
|
|
@ -36,13 +36,17 @@ export async function action({ params, request }: Route.ActionArgs) {
|
|||
const session = (await sessionResp.json()) as {
|
||||
url: string;
|
||||
initialWaypoints?: Array<{ lat: number; lon: number; name?: string }>;
|
||||
initialNoGoAreas?: Array<{ points: Array<{ lat: number; lon: number }> }>;
|
||||
};
|
||||
|
||||
// Encode waypoints in URL params (small — just coordinates, not full GPX)
|
||||
// Encode planning data in URL params
|
||||
const urlParams = new URLSearchParams({ returnUrl });
|
||||
if (session.initialWaypoints?.length) {
|
||||
urlParams.set("waypoints", JSON.stringify(session.initialWaypoints));
|
||||
}
|
||||
if (session.initialNoGoAreas?.length) {
|
||||
urlParams.set("noGoAreas", JSON.stringify(session.initialNoGoAreas));
|
||||
}
|
||||
|
||||
return data({
|
||||
url: `${plannerUrl}${session.url}?${urlParams}`,
|
||||
|
|
|
|||
|
|
@ -179,12 +179,13 @@ interface SessionViewProps {
|
|||
callbackToken?: string;
|
||||
returnUrl?: string;
|
||||
initialWaypoints?: Array<{ lat: number; lon: number; name?: string }>;
|
||||
initialNoGoAreas?: Array<{ points: Array<{ lat: number; lon: number }> }>;
|
||||
}
|
||||
|
||||
export function SessionView({ sessionId, callbackUrl, callbackToken, returnUrl, initialWaypoints }: SessionViewProps) {
|
||||
export function SessionView({ sessionId, callbackUrl, callbackToken, returnUrl, initialWaypoints, initialNoGoAreas }: SessionViewProps) {
|
||||
const { t } = useTranslation("planner");
|
||||
useEffect(() => { Sentry.setTag("session_id", sessionId); }, [sessionId]);
|
||||
const yjs = useYjs(sessionId, initialWaypoints);
|
||||
const yjs = useYjs(sessionId, initialWaypoints, initialNoGoAreas);
|
||||
const { computing, routeError, routeStats, requestRoute } = useRouting(yjs);
|
||||
const [highlightPosition, setHighlightPosition] = useState<[number, number] | null>(null);
|
||||
const { toasts, addToast } = useToasts();
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export interface YjsState {
|
|||
export function useYjs(
|
||||
sessionId: string,
|
||||
initialWaypoints?: Array<{ lat: number; lon: number; name?: string }>,
|
||||
initialNoGoAreas?: Array<{ points: Array<{ lat: number; lon: number }> }>,
|
||||
): YjsState | null {
|
||||
const [state, setState] = useState<YjsState | null>(null);
|
||||
const providerRef = useRef<WebsocketProvider | null>(null);
|
||||
|
|
@ -106,6 +107,13 @@ export function useYjs(
|
|||
if (wp.name) yMap.set("name", wp.name);
|
||||
waypoints.push([yMap]);
|
||||
}
|
||||
if (initialNoGoAreas?.length && noGoAreas.length === 0) {
|
||||
for (const area of initialNoGoAreas) {
|
||||
const yMap = new Y.Map();
|
||||
yMap.set("points", area.points);
|
||||
noGoAreas.push([yMap]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { data } from "react-router";
|
||||
import type { Route } from "./+types/api.sessions";
|
||||
import { createSession, listSessions, initializeSessionWithNoGoAreas } from "~/lib/sessions";
|
||||
import { createSession, listSessions } from "~/lib/sessions";
|
||||
import { parseGpxAsync, extractWaypoints } from "@trails-cool/gpx";
|
||||
import { withDb } from "@trails-cool/db";
|
||||
|
||||
|
|
@ -20,21 +20,20 @@ export async function action({ request }: Route.ActionArgs) {
|
|||
const session = await createSession({ callbackUrl, callbackToken });
|
||||
|
||||
let initialWaypoints: Array<{ lat: number; lon: number; name?: string }> | undefined;
|
||||
let initialNoGoAreas: Array<{ points: Array<{ lat: number; lon: number }> }> | undefined;
|
||||
if (gpx) {
|
||||
try {
|
||||
const gpxData = await parseGpxAsync(gpx);
|
||||
const wps = extractWaypoints(gpxData);
|
||||
if (wps.length > 0) initialWaypoints = wps;
|
||||
if (gpxData.noGoAreas.length > 0) {
|
||||
initializeSessionWithNoGoAreas(session.id, gpxData.noGoAreas);
|
||||
}
|
||||
if (gpxData.noGoAreas.length > 0) initialNoGoAreas = gpxData.noGoAreas;
|
||||
} catch {
|
||||
// Continue with empty session if GPX is invalid
|
||||
}
|
||||
}
|
||||
|
||||
return data(
|
||||
{ sessionId: session.id, url: `/session/${session.id}`, initialWaypoints },
|
||||
{ sessionId: session.id, url: `/session/${session.id}`, initialWaypoints, initialNoGoAreas },
|
||||
{ status: 201 },
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ export default function SessionPage({ loaderData }: Route.ComponentProps) {
|
|||
if (waypointsParam) {
|
||||
try { initialWaypoints = JSON.parse(waypointsParam); } catch { /* ignore */ }
|
||||
}
|
||||
const noGoParam = searchParams.get("noGoAreas");
|
||||
let initialNoGoAreas: Array<{ points: Array<{ lat: number; lon: number }> }> | undefined;
|
||||
if (noGoParam) {
|
||||
try { initialNoGoAreas = JSON.parse(noGoParam); } catch { /* ignore */ }
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
|
|
@ -61,6 +66,7 @@ export default function SessionPage({ loaderData }: Route.ComponentProps) {
|
|||
callbackToken={loaderData.callbackToken ?? undefined}
|
||||
returnUrl={returnUrl}
|
||||
initialWaypoints={initialWaypoints}
|
||||
initialNoGoAreas={initialNoGoAreas}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue