From a41611a86f1ed648f6ad24370e253676f6576b6a Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Sun, 26 Oct 2025 15:37:21 -0700 Subject: [PATCH] Allow updating task status. --- frontend/app/components/TaskList.tsx | 145 +++++++++++++++++++++++++-- frontend/app/hooks/useTasks.ts | 33 +++++- 2 files changed, 171 insertions(+), 7 deletions(-) diff --git a/frontend/app/components/TaskList.tsx b/frontend/app/components/TaskList.tsx index 4c96c0b..7a73a94 100644 --- a/frontend/app/components/TaskList.tsx +++ b/frontend/app/components/TaskList.tsx @@ -6,7 +6,6 @@ import { InputLabel, Select, MenuItem, - Chip, Stack, Paper, Table, @@ -46,7 +45,7 @@ interface TaskListProps { } export function TaskList({ className, initialTasks }: TaskListProps) { - const { tasks, loading, error, deleteTask } = useTasks({ + const { tasks, loading, error, updateTask, deleteTask } = useTasks({ autoFetch: !initialTasks, initialData: initialTasks, }) @@ -217,6 +216,13 @@ export function TaskList({ className, initialTasks }: TaskListProps) { } } + const handleStatusChange = async (taskId: string, newStatus: TaskStatus) => { + const result = await updateTask(taskId, { status: newStatus }) + if (!result) { + console.error('Failed to update task status') + } + } + const isAllSelected = filteredAndSortedTasks.length > 0 && filteredAndSortedTasks.every(task => selectedTaskIds.has(task.id)) @@ -447,12 +453,139 @@ export function TaskList({ className, initialTasks }: TaskListProps) { )} - + handleStatusChange( + task.id, + e.target.value as TaskStatus + ) + } size="small" variant="outlined" - /> + MenuProps={{ + PaperProps: { + sx: { + padding: '4px', + minWidth: '100px', + '& .MuiList-root': { + padding: 0, + }, + }, + }, + }} + sx={{ + minWidth: 90, + height: '24px', + borderRadius: '16px', + backgroundColor: + getStatusColor(task.status) === 'primary' + ? 'primary.main' + : getStatusColor(task.status) === 'success' + ? 'success.main' + : 'action.disabled', + color: + getStatusColor(task.status) === 'default' + ? 'text.primary' + : 'white', + fontSize: '0.75rem', + '& .MuiOutlinedInput-notchedOutline': { + border: 'none', + }, + '&:hover .MuiOutlinedInput-notchedOutline': { + border: 'none', + }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { + border: 'none', + }, + '& .MuiSelect-select': { + padding: '2px 12px 2px 12px', + paddingRight: '24px !important', + display: 'flex', + alignItems: 'center', + height: '20px', + lineHeight: '20px', + }, + '& .MuiSelect-icon': { + right: '4px', + color: + getStatusColor(task.status) === 'default' + ? 'text.primary' + : 'white', + fontSize: '1rem', + }, + }} + > + + Todo + + + Done + + + Backlog + + Promise createTask: (data: CreateTaskRequest) => Promise + updateTask: (id: string, data: UpdateTaskRequest) => Promise deleteTask: (id: string) => Promise refreshTasks: () => Promise clearError: () => void @@ -91,6 +97,30 @@ export function useTasks( [] ) + const updateTask = useCallback( + async (id: string, data: UpdateTaskRequest): Promise => { + try { + const updatedTask = await apiClient.updateTask(id, data) + + // Update the task in the local state immediately + setState(prev => ({ + ...prev, + tasks: prev.tasks.map(task => (task.id === id ? updatedTask : task)), + })) + + return updatedTask + } catch (error) { + const apiError = error as ApiError + setState(prev => ({ + ...prev, + error: apiError.message, + })) + return null + } + }, + [] + ) + const deleteTask = useCallback(async (id: string): Promise => { try { await apiClient.deleteTask(id) @@ -176,6 +206,7 @@ export function useTasks( ...state, fetchTasks, createTask, + updateTask, deleteTask, refreshTasks, clearError,