From 6ba1ff57b283706167829613c4f5834c75cc6fd0 Mon Sep 17 00:00:00 2001 From: chamiakJ Date: Sun, 6 Jul 2025 15:42:12 +0530 Subject: [PATCH] refactor(task-list): streamline task addition and socket handling - Removed local socket listener from AddTaskRow, delegating task addition to the global socket handler for real-time updates. - Simplified the handleTaskAdded function in TaskListV2, eliminating the need for refetching tasks upon addition. - Updated useTaskSocketHandlers to handle task data more efficiently, ensuring proper integration with the Redux store. --- .../components/task-list-v2/TaskListV2.tsx | 7 +- .../task-list-v2/components/AddTaskRow.tsx | 77 +------------------ .../src/hooks/useTaskSocketHandlers.ts | 14 ++-- 3 files changed, 15 insertions(+), 83 deletions(-) diff --git a/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx b/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx index 3fe947e7..563d377a 100644 --- a/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx +++ b/worklenz-frontend/src/components/task-list-v2/TaskListV2.tsx @@ -271,10 +271,9 @@ const TaskListV2: React.FC = () => { // Add callback for task added const handleTaskAdded = useCallback(() => { - if (urlProjectId) { - dispatch(fetchTasksV3(urlProjectId)); - } - }, [dispatch, urlProjectId]); + // Task is now added in real-time via socket, no need to refetch + // The global socket handler will handle the real-time update + }, []); // Memoized values for GroupedVirtuoso const virtuosoGroups = useMemo(() => { diff --git a/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx b/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx index b7060078..a023f7f4 100644 --- a/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx +++ b/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx @@ -1,14 +1,10 @@ -import React, { useState, useCallback, memo, useEffect } from 'react'; +import React, { useState, useCallback, memo } from 'react'; import { Input } from 'antd'; import { PlusOutlined } from '@ant-design/icons'; import { useTranslation } from 'react-i18next'; import { useSocket } from '@/socket/socketContext'; import { SocketEvents } from '@/shared/socket-events'; import { useAuthService } from '@/hooks/useAuth'; -import { useAppDispatch } from '@/hooks/useAppDispatch'; -import { addTaskToGroup } from '@/features/task-management/task-management.slice'; -import { Task } from '@/types/task-management.types'; -import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; interface AddTaskRowProps { groupId: string; @@ -35,77 +31,12 @@ const AddTaskRow: React.FC = memo(({ const [taskName, setTaskName] = useState(''); const { socket, connected } = useSocket(); const { t } = useTranslation('task-list-table'); - const dispatch = useAppDispatch(); // Get session data for reporter_id and team_id const currentSession = useAuthService().getCurrentSession(); - // Listen for task creation completion and add to Redux store immediately - useEffect(() => { - if (!socket) return; - - const handleTaskCreated = (data: IProjectTask) => { - if (data) { - // Transform backend response to Task format for real-time addition - const task: Task = { - id: data.id || '', - task_key: data.task_key || '', - title: data.name || '', - description: data.description || '', - status: (data.status_category?.is_todo - ? 'todo' - : data.status_category?.is_doing - ? 'doing' - : data.status_category?.is_done - ? 'done' - : 'todo') as 'todo' | 'doing' | 'done', - priority: (data.priority_value === 3 - ? 'critical' - : data.priority_value === 2 - ? 'high' - : data.priority_value === 1 - ? 'medium' - : 'low') as 'critical' | 'high' | 'medium' | 'low', - phase: data.phase_name || 'Development', - progress: data.complete_ratio || 0, - assignees: data.assignees?.map(a => a.team_member_id) || [], - assignee_names: data.names || [], - labels: - data.labels?.map(l => ({ - id: l.id || '', - name: l.name || '', - color: l.color_code || '#1890ff', - end: l.end, - names: l.names, - })) || [], - dueDate: data.end_date, - startDate: data.start_date, - timeTracking: { - estimated: (data.total_hours || 0) + (data.total_minutes || 0) / 60, - logged: (data.time_spent?.hours || 0) + (data.time_spent?.minutes || 0) / 60, - }, - created_at: data.created_at || new Date().toISOString(), - updated_at: data.updated_at || new Date().toISOString(), - order: data.sort_order || 0, - sub_tasks: [], - sub_tasks_count: 0, - show_sub_tasks: false, - }; - - // Add task to the correct group in Redux store for immediate UI update - dispatch(addTaskToGroup({ task, groupId })); - - // Optional: Call onTaskAdded for any additional UI updates - onTaskAdded(); - } - }; - - socket.on(SocketEvents.QUICK_TASK.toString(), handleTaskCreated); - - return () => { - socket.off(SocketEvents.QUICK_TASK.toString(), handleTaskCreated); - }; - }, [socket, onTaskAdded, dispatch, groupId]); + // The global socket handler (useTaskSocketHandlers) will handle task addition + // No need for local socket listener to avoid duplicate additions const handleAddTask = useCallback(() => { if (!taskName.trim() || !currentSession) return; @@ -147,7 +78,7 @@ const AddTaskRow: React.FC = memo(({ } catch (error) { console.error('Error creating task:', error); } - }, [taskName, projectId, groupType, groupValue, socket, connected, currentSession, onTaskAdded]); + }, [taskName, projectId, groupType, groupValue, socket, connected, currentSession]); const handleCancel = useCallback(() => { setTaskName(''); diff --git a/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts b/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts index d0ec6a15..7542076e 100644 --- a/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts +++ b/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts @@ -575,7 +575,9 @@ export const useTaskSocketHandlers = () => { ); const handleNewTaskReceived = useCallback( - (data: IProjectTask) => { + (response: any) => { + // Handle array format response [index, taskData] + const data = Array.isArray(response) ? response[1] : response; if (!data) return; if (data.parent_task_id) { // Handle subtask creation @@ -600,10 +602,10 @@ export const useTaskSocketHandlers = () => { : 'low') as 'critical' | 'high' | 'medium' | 'low', phase: data.phase_name || 'Development', progress: data.complete_ratio || 0, - assignees: data.assignees?.map(a => a.team_member_id) || [], + assignees: data.assignees?.map((a: any) => a.team_member_id) || [], assignee_names: data.names || [], labels: - data.labels?.map(l => ({ + data.labels?.map((l: any) => ({ id: l.id || '', name: l.name || '', color: l.color_code || '#1890ff', @@ -654,10 +656,10 @@ export const useTaskSocketHandlers = () => { : 'low') as 'critical' | 'high' | 'medium' | 'low', phase: data.phase_name || 'Development', progress: data.complete_ratio || 0, - assignees: data.assignees?.map(a => a.team_member_id) || [], + assignees: data.assignees?.map((a: any) => a.team_member_id) || [], assignee_names: data.names || [], labels: - data.labels?.map(l => ({ + data.labels?.map((l: any) => ({ id: l.id || '', name: l.name || '', color: l.color_code || '#1890ff', @@ -697,7 +699,7 @@ export const useTaskSocketHandlers = () => { } // Use addTaskToGroup with the actual group UUID - dispatch(addTaskToGroup({ task, groupId })); + dispatch(addTaskToGroup({ task, groupId: groupId || '' })); // Also update enhanced kanban slice for regular task creation dispatch(