- useSoloStore: initTasks, optimisticMove (returns prev status), rollback, updatePlan - SoloBoard: DndContext with PointerSensor (distance:5), closestCorners, 3 columns - SoloColumn: useDroppable per status, MD3 status-color headers, task count, empty state - SoloTaskCard + SoloTaskCardOverlay: useDraggable (disabled for demo), priority left-border - onDragEnd: optimisticMove → updateTaskStatusAction → rollback + toast on error - REVIEW tasks mapped to IN_PROGRESS column Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
32 lines
1.1 KiB
TypeScript
32 lines
1.1 KiB
TypeScript
import { create } from 'zustand'
|
|
import type { SoloTask } from '@/components/solo/solo-board'
|
|
|
|
type TaskStatus = SoloTask['status']
|
|
|
|
interface SoloStore {
|
|
tasks: Record<string, SoloTask>
|
|
initTasks: (tasks: SoloTask[]) => void
|
|
optimisticMove: (taskId: string, toStatus: TaskStatus) => TaskStatus | null
|
|
rollback: (taskId: string, prevStatus: TaskStatus) => void
|
|
updatePlan: (taskId: string, plan: string | null) => void
|
|
}
|
|
|
|
export const useSoloStore = create<SoloStore>((set, get) => ({
|
|
tasks: {},
|
|
|
|
initTasks: (tasks) =>
|
|
set({ tasks: Object.fromEntries(tasks.map(t => [t.id, t])) }),
|
|
|
|
optimisticMove: (taskId, toStatus) => {
|
|
const prev = get().tasks[taskId]?.status ?? null
|
|
if (!prev) return null
|
|
set((s) => ({ tasks: { ...s.tasks, [taskId]: { ...s.tasks[taskId], status: toStatus } } }))
|
|
return prev
|
|
},
|
|
|
|
rollback: (taskId, prevStatus) =>
|
|
set((s) => ({ tasks: { ...s.tasks, [taskId]: { ...s.tasks[taskId], status: prevStatus } } })),
|
|
|
|
updatePlan: (taskId, plan) =>
|
|
set((s) => ({ tasks: { ...s.tasks, [taskId]: { ...s.tasks[taskId], implementation_plan: plan } } })),
|
|
}))
|