From aea54516c976f5da8b739efa63ccd060aec3efbe Mon Sep 17 00:00:00 2001 From: Hammer Date: Wed, 28 Jan 2026 23:46:07 +0000 Subject: [PATCH] feat: task detail panel with progress notes --- frontend/src/App.tsx | 27 ++++++++++++++++++++++++++- frontend/src/index.css | 15 +++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index bdd95cc..80c491d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,11 +1,12 @@ import { useState, useMemo } from "react"; import { useTasks } from "./hooks/useTasks"; import { TaskCard } from "./components/TaskCard"; +import { TaskDetailPanel } from "./components/TaskDetailPanel"; import { CreateTaskModal } from "./components/CreateTaskModal"; import { LoginPage } from "./components/LoginPage"; import { useSession, signOut } from "./lib/auth-client"; import { updateTask, reorderTasks, createTask } from "./lib/api"; -import type { TaskStatus } from "./lib/types"; +import type { Task, TaskStatus } from "./lib/types"; // Token stored in localStorage for bearer-token admin operations function getToken(): string { @@ -16,6 +17,7 @@ function Dashboard() { const { tasks, loading, error, refresh } = useTasks(5000); const [showCreate, setShowCreate] = useState(false); const [showCompleted, setShowCompleted] = useState(false); + const [selectedTask, setSelectedTask] = useState(null); const [tokenInput, setTokenInput] = useState(""); const [showTokenInput, setShowTokenInput] = useState(false); const session = useSession(); @@ -23,6 +25,12 @@ function Dashboard() { const token = getToken(); const hasToken = !!token; + // Keep selected task in sync with refreshed data + const selectedTaskData = useMemo(() => { + if (!selectedTask) return null; + return tasks.find((t) => t.id === selectedTask.id) || null; + }, [tasks, selectedTask]); + const activeTasks = useMemo(() => tasks.filter((t) => t.status === "active"), [tasks]); const queuedTasks = useMemo(() => tasks.filter((t) => t.status === "queued"), [tasks]); const blockedTasks = useMemo(() => tasks.filter((t) => t.status === "blocked"), [tasks]); @@ -195,6 +203,7 @@ function Dashboard() { task={task} onStatusChange={handleStatusChange} isActive + onClick={() => setSelectedTask(task)} /> ))} @@ -213,6 +222,7 @@ function Dashboard() { key={task.id} task={task} onStatusChange={handleStatusChange} + onClick={() => setSelectedTask(task)} /> ))} @@ -239,6 +249,7 @@ function Dashboard() { onMoveDown={() => handleMoveDown(i)} isFirst={i === 0} isLast={i === queuedTasks.length - 1} + onClick={() => setSelectedTask(task)} /> ))} @@ -260,6 +271,7 @@ function Dashboard() { key={task.id} task={task} onStatusChange={handleStatusChange} + onClick={() => setSelectedTask(task)} /> ))} @@ -267,6 +279,19 @@ function Dashboard() { + {/* Task Detail Panel */} + {selectedTaskData && ( + setSelectedTask(null)} + onStatusChange={(id, status) => { + handleStatusChange(id, status); + setSelectedTask(null); + }} + hasToken={hasToken} + /> + )} + {/* Footer */}