Implement Planner-Journal handoff (Group 9)
JWT-based handoff between Journal and Planner: Journal side: - JWT token generation scoped to route_id with 7-day expiry (jose) - "Edit in Planner" button on route detail page — generates JWT, redirects to Planner /new with callback URL, token, and GPX - Callback endpoint (POST /api/routes/:id/callback) validates JWT and creates new route version from received GPX Planner side: - /new route accepts callback, token, returnUrl, gpx params - Creates session with callback metadata, initializes with GPX - "Save to Journal" button POSTs GPX with Bearer token to callback - "Return to Journal" link shown after successful save All 6 Group 9 tasks complete. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f47eca565c
commit
40e541fcce
12 changed files with 287 additions and 11 deletions
|
|
@ -3,6 +3,7 @@ import { useYjs } from "~/lib/use-yjs";
|
|||
import { useRouting } from "~/lib/use-routing";
|
||||
import { ProfileSelector } from "~/components/ProfileSelector";
|
||||
import { ExportButton } from "~/components/ExportButton";
|
||||
import { SaveToJournalButton } from "~/components/SaveToJournalButton";
|
||||
import { YjsDebugPanel } from "~/components/YjsDebugPanel";
|
||||
|
||||
const PlannerMap = lazy(() =>
|
||||
|
|
@ -15,7 +16,14 @@ const ElevationChart = lazy(() =>
|
|||
import("~/components/ElevationChart").then((m) => ({ default: m.ElevationChart })),
|
||||
);
|
||||
|
||||
export function SessionView({ sessionId }: { sessionId: string }) {
|
||||
interface SessionViewProps {
|
||||
sessionId: string;
|
||||
callbackUrl?: string;
|
||||
callbackToken?: string;
|
||||
returnUrl?: string;
|
||||
}
|
||||
|
||||
export function SessionView({ sessionId, callbackUrl, callbackToken, returnUrl }: SessionViewProps) {
|
||||
const yjs = useYjs(sessionId);
|
||||
const { isHost, computing, routeStats, requestRoute } = useRouting(yjs);
|
||||
const [highlightPosition, setHighlightPosition] = useState<[number, number] | null>(null);
|
||||
|
|
@ -40,6 +48,14 @@ export function SessionView({ sessionId }: { sessionId: string }) {
|
|||
<ProfileSelector yjs={yjs} />
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
{callbackUrl && callbackToken && (
|
||||
<SaveToJournalButton
|
||||
yjs={yjs}
|
||||
callbackUrl={callbackUrl}
|
||||
callbackToken={callbackToken}
|
||||
returnUrl={returnUrl}
|
||||
/>
|
||||
)}
|
||||
<ExportButton yjs={yjs} />
|
||||
{computing && (
|
||||
<span className="text-xs text-blue-600">Computing route...</span>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue