From 0761adedbedb8ad3a2821285888ce218b2e0f773 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Thu, 19 Feb 2026 17:53:33 -0600 Subject: [PATCH] Add Backlog view for sprint planning - Created BacklogView component with: - Search and filter (by type and priority) - List of unassigned backlog items - Quick sprint assignment dropdown - Sprint planning section showing all sprints - Drag-and-drop for reordering - Stats summary (total, urgent, high priority) - Quick add button for new backlog items - Added Backlog view toggle alongside Kanban/Sprint - Backlog items show type, priority, comment count --- data/tasks.json | 18 +- src/app/page.tsx | 18 +- src/components/BacklogView.tsx | 438 +++++++++++++++++++++++++++++++++ 3 files changed, 469 insertions(+), 5 deletions(-) create mode 100644 src/components/BacklogView.tsx diff --git a/data/tasks.json b/data/tasks.json index 789763a..baebf95 100644 --- a/data/tasks.json +++ b/data/tasks.json @@ -87,7 +87,7 @@ }, { "id": "c7", - "text": "\u2705 All 3 repos created and pushed to Gitea: gantt-board, blog-backup, heartbeat-monitor", + "text": "✅ All 3 repos created and pushed to Gitea: gantt-board, blog-backup, heartbeat-monitor", "createdAt": "2026-02-18T17:01:23.109Z", "author": "assistant" } @@ -469,5 +469,17 @@ ] } ], - "lastUpdated": 1771529100000 -} + "lastUpdated": 1771544832422, + "sprints": [ + { + "name": "Sprint 1", + "goal": "", + "startDate": "2026-02-19", + "endDate": "2026-02-22", + "status": "planning", + "projectId": "1", + "id": "1771544832363", + "createdAt": "2026-02-19T23:47:12.363Z" + } + ] +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 310aaec..7d8390b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -9,7 +9,8 @@ import { Textarea } from "@/components/ui/textarea" import { Label } from "@/components/ui/label" import { useTaskStore, Task, TaskType, TaskStatus, Priority, Project } from "@/stores/useTaskStore" import { SprintBoard } from "@/components/SprintBoard" -import { Plus, MessageSquare, Calendar, Tag, Trash2, Edit2, X, Check, MoreHorizontal, LayoutGrid, Flag } from "lucide-react" +import { BacklogView } from "@/components/BacklogView" +import { Plus, MessageSquare, Calendar, Tag, Trash2, Edit2, X, Check, MoreHorizontal, LayoutGrid, Flag, ListTodo } from "lucide-react" const typeColors: Record = { idea: "bg-purple-500", @@ -71,7 +72,7 @@ export default function Home() { }) const [newComment, setNewComment] = useState("") const [editingTask, setEditingTask] = useState(null) - const [viewMode, setViewMode] = useState<'kanban' | 'sprint'>('kanban') + const [viewMode, setViewMode] = useState<'kanban' | 'sprint' | 'backlog'>('kanban') // Sync from server on mount useEffect(() => { @@ -267,6 +268,17 @@ export default function Home() { Sprint + + + + {/* Stats */} +
+ + {backlogTasks.length} items in backlog + + + + + {backlogTasks.filter((t) => t.priority === "urgent").length} + {" "} + urgent + + + + + {backlogTasks.filter((t) => t.priority === "high").length} + {" "} + high priority + +
+ + {/* Backlog List */} + {sortedTasks.length === 0 ? ( +
+ {searchQuery || filterType !== "all" || filterPriority !== "all" ? ( +

No items match your filters

+ ) : ( + <> +

Backlog is empty

+ + + )} +
+ ) : ( +
+ t.id)} + strategy={verticalListSortingStrategy} + > + {sortedTasks.map((task) => ( + selectTask(task.id)} + onAssignToSprint={(sprintId) => + handleAssignToSprint(task.id, sprintId) + } + /> + ))} + +
+ )} + + {/* Sprint Planning Section */} + {projectSprints.length > 0 && ( +
+

+ Sprint Planning +

+
+ {projectSprints.map((sprint) => { + const sprintTasks = tasks.filter((t) => t.sprintId === sprint.id) + const sprintPoints = sprintTasks.length // Simple count for now + + return ( + { + // Switch to sprint view with this sprint selected + // This would need to be passed up to parent or use store + }} + > + +
+

+ {sprint.name} +

+ + {sprint.status} + +
+

+ {sprint.goal || "No goal set"} +

+
+ {sprintTasks.length} tasks + + {new Date(sprint.startDate).toLocaleDateString()} -{" "} + {new Date(sprint.endDate).toLocaleDateString()} + +
+
+
+ ) + })} +
+
+ )} + + + + {activeTask ? : null} + + + ) +}