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"
+ />
+ )}
);