feat: persist task lane user responses to backend
Add PUT /ai-sessions/{id}/task-lane endpoint that saves the full task
lane state (AI questions/actions + user's in-progress responses) to
the pending_task_lane JSONB column. TaskLane debounce-saves to the
backend every 2s after changes. On session load, user responses are
restored from the backend into sessionStorage so TaskLane picks them
up on mount. Users can now close the browser, come back later, and
find their task lane exactly where they left it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
} from 'lucide-react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { toast } from '@/lib/toast'
|
||||
import { aiSessionsApi } from '@/api/aiSessions'
|
||||
import type { ActionItem, QuestionItem } from '@/types/ai-session'
|
||||
|
||||
// ── Types ──
|
||||
@@ -129,10 +130,22 @@ export function TaskLane({ questions, actions, sessionId, onSubmit, onClose, loa
|
||||
}
|
||||
}, [handleMouseMove, handleMouseUp])
|
||||
|
||||
// Save task state to sessionStorage on every change
|
||||
// Save task state to sessionStorage on every change + debounce to backend
|
||||
const saveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
useEffect(() => {
|
||||
if (sessionId) saveTaskState(sessionId, tasks)
|
||||
}, [sessionId, tasks])
|
||||
if (!sessionId) return
|
||||
saveTaskState(sessionId, tasks)
|
||||
// Debounce save to backend (2s after last change)
|
||||
if (saveTimerRef.current) clearTimeout(saveTimerRef.current)
|
||||
saveTimerRef.current = setTimeout(() => {
|
||||
aiSessionsApi.saveTaskLane(sessionId, {
|
||||
questions: questions.map(q => ({ text: q.text, context: q.context })),
|
||||
actions: actions.map(a => ({ label: a.label, command: a.command, description: a.description })),
|
||||
responses: tasks as unknown as Array<Record<string, unknown>>,
|
||||
}).catch(() => { /* silent — best-effort save */ })
|
||||
}, 2000)
|
||||
return () => { if (saveTimerRef.current) clearTimeout(saveTimerRef.current) }
|
||||
}, [sessionId, tasks]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Reset when new tasks come in from AI response
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user