From 58bda51ef5994821d49214fab47ac2bc065e33fd Mon Sep 17 00:00:00 2001 From: sean-eskerium Date: Wed, 20 Aug 2025 11:10:36 -0400 Subject: [PATCH] UI improvement, Add delete confirm, --- .../src/components/project-tasks/TasksTab.tsx | 103 +++++++++++++++++- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/archon-ui-main/src/components/project-tasks/TasksTab.tsx b/archon-ui-main/src/components/project-tasks/TasksTab.tsx index 5002f359..60f862ad 100644 --- a/archon-ui-main/src/components/project-tasks/TasksTab.tsx +++ b/archon-ui-main/src/components/project-tasks/TasksTab.tsx @@ -1,10 +1,11 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; -import { Table, LayoutGrid, Plus, Wifi, WifiOff, List } from 'lucide-react'; +import { Table, LayoutGrid, Plus, Wifi, WifiOff, List, Trash2 } from 'lucide-react'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { Toggle } from '../ui/Toggle'; import { projectService } from '../../services/projectService'; import { getGlobalOperationTracker } from '../../utils/operationTracker'; +import { Card } from '../ui/card'; import { useTaskSocket } from '../../hooks/useTaskSocket'; import type { CreateTaskRequest, UpdateTaskRequest, DatabaseTaskStatus } from '../../types/project'; @@ -16,6 +17,71 @@ import { EditTaskModal } from './EditTaskModal'; // Assignee utilities const ASSIGNEE_OPTIONS = ['User', 'Archon', 'AI IDE Agent'] as const; +// Delete confirmation modal component +interface DeleteConfirmModalProps { + onConfirm: () => void; + onCancel: () => void; + title: string; + message: string; + confirmText?: string; +} + +const DeleteConfirmModal = ({ + onConfirm, + onCancel, + title, + message, + confirmText = 'Archive' +}: DeleteConfirmModalProps) => { + return ( +
+
+ +
+
+
+ +
+
+

+ {title} +

+

+ This action cannot be undone +

+
+
+ +

+ {message} +

+ +
+ + +
+
+
+
+ ); +}; + // Mapping functions for status conversion const mapUIStatusToDBStatus = (uiStatus: Task['status']): DatabaseTaskStatus => { switch (uiStatus) { @@ -71,6 +137,8 @@ export const TasksTab = ({ const [isLoadingFeatures, setIsLoadingFeatures] = useState(false); const [isSavingTask, setIsSavingTask] = useState(false); const [isWebSocketConnected, setIsWebSocketConnected] = useState(false); + const [taskToDelete, setTaskToDelete] = useState(null); + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); // Track recently deleted tasks to prevent race conditions const [recentlyDeletedIds, setRecentlyDeletedIds] = useState>(new Set()); @@ -480,16 +548,27 @@ export const TasksTab = ({ }; const deleteTask = async (task: Task) => { + // Set the task to delete and show confirmation modal + setTaskToDelete(task); + setShowDeleteConfirm(true); + }; + + const confirmDeleteTask = async () => { + if (!taskToDelete) return; + try { - // Delete the task - backend will emit socket event - await projectService.deleteTask(task.id); - console.log(`[TasksTab] Task ${task.id} deletion sent to backend`); + // Delete (actually archives) the task - backend will emit socket event + await projectService.deleteTask(taskToDelete.id); + console.log(`[TasksTab] Task ${taskToDelete.id} archival sent to backend`); // Don't update local state - let socket handle it } catch (error) { - console.error('Failed to delete task:', error); + console.error('Failed to archive task:', error); // Note: The toast notification for deletion is now handled by TaskBoardView and TaskTableView + } finally { + setTaskToDelete(null); + setShowDeleteConfirm(false); } }; @@ -699,6 +778,20 @@ export const TasksTab = ({ onSave={saveTask} getTasksForPrioritySelection={memoizedGetTasksForPrioritySelection} /> + + {/* Delete Confirmation Modal */} + {showDeleteConfirm && taskToDelete && ( + { + setTaskToDelete(null); + setShowDeleteConfirm(false); + }} + title="Archive Task" + message={`Are you sure you want to archive the task "${taskToDelete.title}"? You can restore it from the archived tasks view.`} + confirmText="Archive Task" + /> + )} );