diff --git a/worklenz-frontend/src/components/task-management/task-list-board.tsx b/worklenz-frontend/src/components/task-management/task-list-board.tsx index b5433891..ca89af5e 100644 --- a/worklenz-frontend/src/components/task-management/task-list-board.tsx +++ b/worklenz-frontend/src/components/task-management/task-list-board.tsx @@ -414,14 +414,26 @@ const TaskListBoard: React.FC = ({ projectId, className = '' const handleSelectTask = useCallback( (taskId: string, selected: boolean) => { + // Create a new Set from existing selections for efficient lookup and modification + const currentSelectedIds = new Set(selectedTaskIds); + + // Update the selection state based on the checkbox action if (selected) { - // Add task to bulk selection - const task = tasks.find(t => t.id === taskId); - if (task) { - // Convert Task to IProjectTask format for bulk actions - const projectTask: IProjectTask = { + currentSelectedIds.add(taskId); + } else { + currentSelectedIds.delete(taskId); + } + + // Convert Set back to array for Redux state + const newSelectedIds = Array.from(currentSelectedIds); + + // Map selected tasks to the required format + const newSelectedTasks = tasks + .filter((t) => newSelectedIds.includes(t.id)) + .map( + (task): IProjectTask => ({ id: task.id, - name: task.title, // Always use title as the name + name: task.title, task_key: task.task_key, status: task.status, status_id: task.status, @@ -435,7 +447,7 @@ const TaskListBoard: React.FC = ({ projectId, className = '' total_minutes: task.timeTracking.logged || 0, progress: task.progress, sub_tasks_count: task.sub_tasks_count || 0, - assignees: task.assignees.map(assigneeId => ({ + assignees: task.assignees.map((assigneeId) => ({ id: assigneeId, name: '', email: '', @@ -444,23 +456,18 @@ const TaskListBoard: React.FC = ({ projectId, className = '' project_member_id: assigneeId, })), labels: task.labels, - manual_progress: false, // Default value for Task type + manual_progress: false, created_at: task.createdAt, updated_at: task.updatedAt, sort_order: task.order, - }; - dispatch(selectTasks([...selectedTasks, projectTask])); - dispatch(selectTaskIds([...selectedTaskIds, taskId])); - } - } else { - // Remove task from bulk selection - const updatedTasks = selectedTasks.filter(t => t.id !== taskId); - const updatedTaskIds = selectedTaskIds.filter(id => id !== taskId); - dispatch(selectTasks(updatedTasks)); - dispatch(selectTaskIds(updatedTaskIds)); - } + }) + ); + + // Dispatch both actions to update the Redux state + dispatch(selectTasks(newSelectedTasks)); + dispatch(selectTaskIds(newSelectedIds)); }, - [dispatch, selectedTasks, selectedTaskIds, tasks] + [dispatch, selectedTaskIds, tasks] ); const handleToggleSubtasks = useCallback( diff --git a/worklenz-frontend/src/components/task-management/task-row.tsx b/worklenz-frontend/src/components/task-management/task-row.tsx index ee91fc3f..e95e7189 100644 --- a/worklenz-frontend/src/components/task-management/task-row.tsx +++ b/worklenz-frontend/src/components/task-management/task-row.tsx @@ -55,7 +55,6 @@ import { fetchTask, } from '@/features/task-drawer/task-drawer.slice'; import useDragCursor from '@/hooks/useDragCursor'; -import TaskContextMenu from './task-context-menu/task-context-menu'; interface TaskRowProps { task: Task; @@ -430,9 +429,7 @@ const TaskRow: React.FC = React.memo( const addSubtaskInputRef = useRef(null); const wrapperRef = useRef(null); - // Context menu state - const [showContextMenu, setShowContextMenu] = useState(false); - const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 }); + // Subtask expansion state (managed by Redux) // PERFORMANCE OPTIMIZATION: Intersection Observer for lazy loading useEffect(() => { @@ -575,11 +572,6 @@ const TaskRow: React.FC = React.memo( onToggleSubtasks?.(task.id); }, [task.id, onToggleSubtasks]); - const handleContextMenu = useCallback((e: React.MouseEvent) => { - setShowContextMenu(true); - setContextMenuPosition({ x: e.clientX, y: e.clientY }); - }, []); - // Handle successful subtask creation const handleSubtaskCreated = useCallback( (newTask: any) => { @@ -1015,54 +1007,6 @@ const TaskRow: React.FC = React.memo( )} - {/* Indicators section */} - {!editTaskName && ( -
- {/* Comments indicator */} - {(task as any).comments_count > 0 && ( - - - - )} - {/* Attachments indicator */} - {(task as any).attachments_count > 0 && ( - - - - )} - {/* Dependencies indicator */} - {(task as any).has_dependencies && ( - - - - )} - {/* Subscribers indicator */} - {(task as any).has_subscribers && ( - - - - )} - {/* Recurring indicator */} - {(task as any).schedule_id && ( - - - - )} -
- )} - - )} - )} @@ -1112,8 +1056,6 @@ const TaskRow: React.FC = React.memo( )} )} - - )} {/* Right section with open button - CSS hover only */} @@ -1536,7 +1478,6 @@ const TaskRow: React.FC = React.memo( data-dnd-dragging={isDragging ? 'true' : 'false'} data-task-id={task.id} data-group-id={groupId} - onContextMenu={handleContextMenu} >
{/* All Columns - No Fixed Positioning */} @@ -1565,14 +1506,6 @@ const TaskRow: React.FC = React.memo(
- {showContextMenu && ( - setShowContextMenu(false)} - /> - )} ); }, @@ -1660,4 +1593,4 @@ const TaskRow: React.FC = React.memo( TaskRow.displayName = 'TaskRow'; -export default TaskRow; +export default TaskRow; \ No newline at end of file