feat(task-status-dropdown): enhance task status update and group movement handling

- Added logic to optimistically update task status in Redux for immediate feedback.
- Implemented group movement handling when tasks are updated based on their status, ensuring tasks are moved between groups as needed.
- Improved socket event emissions for real-time updates, including parent task handling.
- Refactored group selection logic to streamline target group identification based on status ID and group value.
This commit is contained in:
chamikaJ
2025-07-30 15:26:27 +05:30
parent 81e1872c1f
commit b6c056dd1a
2 changed files with 50 additions and 44 deletions

View File

@@ -8,6 +8,8 @@ import { Task } from '@/types/task-management.types';
import {
updateTask,
selectCurrentGroupingV3,
selectGroups,
moveTaskBetweenGroups,
} from '@/features/task-management/task-management.slice';
interface TaskStatusDropdownProps {
@@ -30,6 +32,7 @@ const TaskStatusDropdown: React.FC<TaskStatusDropdownProps> = ({
const statusList = useAppSelector(state => state.taskStatusReducer.status);
const currentGroupingV3 = useAppSelector(selectCurrentGroupingV3);
const groups = useAppSelector(selectGroups);
// Find current status details
const currentStatus = useMemo(() => {
@@ -44,21 +47,53 @@ const TaskStatusDropdown: React.FC<TaskStatusDropdownProps> = ({
(statusId: string, statusName: string) => {
if (!task.id || !statusId || !connected) return;
console.log('🎯 Status change initiated:', { taskId: task.id, statusId, statusName });
// Optimistic update: immediately update the task status in Redux for instant feedback
const updatedTask = {
...task,
status: statusId,
updatedAt: new Date().toISOString(),
};
dispatch(updateTask(updatedTask));
// Handle group movement if grouping by status
if (currentGroupingV3 === 'status' && groups && groups.length > 0) {
// Find current group containing the task
const currentGroup = groups.find(group => group.taskIds.includes(task.id));
// Find target group based on the new status ID
let targetGroup = groups.find(group => group.id === statusId);
// If not found by status ID, try matching with group value
if (!targetGroup) {
targetGroup = groups.find(group => group.groupValue === statusId);
}
if (currentGroup && targetGroup && currentGroup.id !== targetGroup.id) {
// Move task between groups immediately for instant feedback
dispatch(
moveTaskBetweenGroups({
taskId: task.id,
sourceGroupId: currentGroup.id,
targetGroupId: targetGroup.id,
})
);
}
}
// Emit socket event for server-side update and real-time sync
socket?.emit(
SocketEvents.TASK_STATUS_CHANGE.toString(),
JSON.stringify({
task_id: task.id,
status_id: statusId,
parent_task: null, // Assuming top-level tasks for now
team_id: projectId, // Using projectId as teamId
parent_task: task.parent_task_id || null,
team_id: projectId,
})
);
socket?.emit(SocketEvents.GET_TASK_PROGRESS.toString(), task.id);
setIsOpen(false);
},
[task.id, connected, socket, projectId]
[task, connected, socket, projectId, dispatch, currentGroupingV3, groups]
);
// Calculate dropdown position and handle outside clicks

View File

@@ -244,44 +244,18 @@ export const useTaskSocketHandlers = () => {
// Find current group containing the task
const currentGroup = groups.find(group => group.taskIds.includes(response.id));
// Find target group based on new status value with multiple matching strategies
let targetGroup = groups.find(group => group.groupValue === newStatusValue);
// Find target group based on the actual status ID from response
let targetGroup = groups.find(group => group.id === response.status_id);
// If not found, try case-insensitive matching
// If not found by status ID, try matching with group value
if (!targetGroup) {
targetGroup = groups.find(group =>
group.groupValue?.toLowerCase() === newStatusValue.toLowerCase()
);
targetGroup = groups.find(group => group.groupValue === response.status_id);
}
// If still not found, try matching with title
if (!targetGroup) {
// If still not found, try matching by status name (fallback)
if (!targetGroup && response.status) {
targetGroup = groups.find(group =>
group.title?.toLowerCase() === newStatusValue.toLowerCase()
);
}
// If still not found, try matching common status patterns
if (!targetGroup && newStatusValue === 'todo') {
targetGroup = groups.find(group =>
group.title?.toLowerCase().includes('todo') ||
group.title?.toLowerCase().includes('to do') ||
group.title?.toLowerCase().includes('pending') ||
group.groupValue?.toLowerCase().includes('todo')
);
} else if (!targetGroup && newStatusValue === 'doing') {
targetGroup = groups.find(group =>
group.title?.toLowerCase().includes('doing') ||
group.title?.toLowerCase().includes('progress') ||
group.title?.toLowerCase().includes('active') ||
group.groupValue?.toLowerCase().includes('doing')
);
} else if (!targetGroup && newStatusValue === 'done') {
targetGroup = groups.find(group =>
group.title?.toLowerCase().includes('done') ||
group.title?.toLowerCase().includes('complete') ||
group.title?.toLowerCase().includes('finish') ||
group.groupValue?.toLowerCase().includes('done')
group.title?.toLowerCase() === response.status.toLowerCase()
);
}
@@ -295,14 +269,11 @@ export const useTaskSocketHandlers = () => {
})
);
} else if (!targetGroup) {
console.log('❌ Target group not found for status:', newStatusValue);
} else if (!currentGroup) {
console.log('❌ Current group not found for task:', response.id);
} else {
console.log('🔧 No group movement needed - task already in correct group');
// Fallback: refetch tasks to ensure consistency
if (projectId) {
dispatch(fetchTasksV3(projectId));
}
}
} else {
console.log('🔧 Not grouped by status, skipping group movement');
}
}
},