From c5cf7703b835d52fb9ee0f9245c42d491275b0b6 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Thu, 19 Feb 2026 23:03:49 -0600 Subject: [PATCH] Improve backlog drag targets and persistent handle visibility --- data/tasks.json | 11 ++++--- src/components/BacklogView.tsx | 55 ++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/data/tasks.json b/data/tasks.json index 0e8efb0..4430a6a 100644 --- a/data/tasks.json +++ b/data/tasks.json @@ -33,7 +33,7 @@ "projectId": "2", "sprintId": "sprint-1", "createdAt": "2026-02-18T17:01:23.109Z", - "updatedAt": "2026-02-18T17:01:23.109Z", + "updatedAt": "2026-02-20T05:01:04.207Z", "comments": [ { "id": "c1", @@ -57,7 +57,6 @@ { "id": "2", "title": "MoodWeave App Idea - UPDATED", - "sprintId": "1771551323429", "projectId": "1", "status": "backlog", "priority": "high", @@ -69,7 +68,7 @@ "OpenClaw iOS" ], "createdAt": "2026-02-18T17:01:23.109Z", - "updatedAt": "2026-02-20T02:28:23.700Z" + "updatedAt": "2026-02-20T05:02:47.264Z" }, { "id": "3", @@ -323,7 +322,7 @@ "priority": "low", "projectId": "3", "createdAt": "2026-02-18T17:01:23.109Z", - "updatedAt": "2026-02-18T17:01:23.109Z", + "updatedAt": "2026-02-20T05:02:42.002Z", "comments": [ { "id": "c52", @@ -472,7 +471,7 @@ ] } ], - "lastUpdated": 1771556223745, + "lastUpdated": 1771563767290, "sprints": [ { "name": "Sprint 1", @@ -506,4 +505,4 @@ "createdAt": "2026-02-20T01:37:45.241Z" } ] -} +} \ No newline at end of file diff --git a/src/components/BacklogView.tsx b/src/components/BacklogView.tsx index 55df60e..4b73c64 100644 --- a/src/components/BacklogView.tsx +++ b/src/components/BacklogView.tsx @@ -1,12 +1,13 @@ "use client" -import { useState } from "react" +import { useState, type ReactNode } from "react" import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, PointerSensor, + useDroppable, useSensor, useSensors, closestCorners, @@ -17,8 +18,8 @@ import { useSortable, } from "@dnd-kit/sortable" import { CSS } from "@dnd-kit/utilities" -import { useTaskStore, Task, Sprint } from "@/stores/useTaskStore" -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { useTaskStore, Task } from "@/stores/useTaskStore" +import { Card, CardContent } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Plus, GripVertical, ChevronDown, ChevronRight, Calendar } from "lucide-react" @@ -66,13 +67,15 @@ function SortableTaskRow({
@@ -106,6 +109,19 @@ function DragOverlayItem({ task }: { task: Task }) { ) } +function SectionDropZone({ id, children }: { id: string; children: ReactNode }) { + const { isOver, setNodeRef } = useDroppable({ id }) + + return ( +
+ {children} +
+ ) +} + // Collapsible Section function TaskSection({ title, @@ -242,14 +258,23 @@ export function BacklogView() { const taskId = active.id as string const overId = over.id as string + const overTask = tasks.find((t) => t.id === overId) + + const destinationId = overTask + ? overTask.sprintId + ? currentSprint && overTask.sprintId === currentSprint.id + ? "current" + : `sprint-${overTask.sprintId}` + : "backlog" + : overId // If dropped over a section header, move task to that section's sprint - if (overId === "backlog") { + if (destinationId === "backlog") { updateTask(taskId, { sprintId: undefined }) - } else if (overId === "current" && currentSprint) { + } else if (destinationId === "current" && currentSprint) { updateTask(taskId, { sprintId: currentSprint.id }) - } else if (overId.startsWith("sprint-")) { - const sprintId = overId.replace("sprint-", "") + } else if (destinationId.startsWith("sprint-")) { + const sprintId = destinationId.replace("sprint-", "") updateTask(taskId, { sprintId }) } } @@ -283,7 +308,7 @@ export function BacklogView() { >
{/* Current Sprint Section */} -
+ -
+ {/* Other Sprints Sections - ordered by start date */} {otherSprints @@ -314,7 +339,7 @@ export function BacklogView() { const sprintTasks = tasks.filter((t) => t.sprintId === sprint.id) console.log(`Sprint ${sprint.name}: ${sprintTasks.length} tasks`, sprintTasks.map(t => t.title)) return ( -
+ -
+ ) })} @@ -391,7 +416,7 @@ export function BacklogView() { )} {/* Backlog Section */} -
+ toggleSection("backlog")} onTaskClick={(task) => selectTask(task.id)} /> -
+