feat(task-list): enhance task creation and UI components

- Improved the on_quick_task function to handle empty task names and emit null when no task is created, ensuring better user feedback.
- Updated SubtaskLoadingSkeleton and TaskRow components for improved styling and spacing, enhancing visual consistency.
- Introduced AddTaskRow component for streamlined task addition, integrating socket communication for real-time updates.
- Refactored TaskListV2 to optimize rendering and improve performance, including adjustments to column headers and task display.
- Added custom column components for enhanced task management flexibility and user interaction.
This commit is contained in:
chamiakJ
2025-07-06 14:51:22 +05:30
parent e3a9618dc9
commit a5291483f7
13 changed files with 1164 additions and 1128 deletions

View File

@@ -0,0 +1,81 @@
import { useCallback } from 'react';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { clearSelection } from '@/features/task-management/selection.slice';
export const useBulkActions = () => {
const dispatch = useAppDispatch();
const handleClearSelection = useCallback(() => {
dispatch(clearSelection());
}, [dispatch]);
const handleBulkStatusChange = useCallback(async (statusId: string) => {
// TODO: Implement bulk status change
console.log('Bulk status change:', statusId);
}, []);
const handleBulkPriorityChange = useCallback(async (priorityId: string) => {
// TODO: Implement bulk priority change
console.log('Bulk priority change:', priorityId);
}, []);
const handleBulkPhaseChange = useCallback(async (phaseId: string) => {
// TODO: Implement bulk phase change
console.log('Bulk phase change:', phaseId);
}, []);
const handleBulkAssignToMe = useCallback(async () => {
// TODO: Implement bulk assign to me
console.log('Bulk assign to me');
}, []);
const handleBulkAssignMembers = useCallback(async (memberIds: string[]) => {
// TODO: Implement bulk assign members
console.log('Bulk assign members:', memberIds);
}, []);
const handleBulkAddLabels = useCallback(async (labelIds: string[]) => {
// TODO: Implement bulk add labels
console.log('Bulk add labels:', labelIds);
}, []);
const handleBulkArchive = useCallback(async () => {
// TODO: Implement bulk archive
console.log('Bulk archive');
}, []);
const handleBulkDelete = useCallback(async () => {
// TODO: Implement bulk delete
console.log('Bulk delete');
}, []);
const handleBulkDuplicate = useCallback(async () => {
// TODO: Implement bulk duplicate
console.log('Bulk duplicate');
}, []);
const handleBulkExport = useCallback(async () => {
// TODO: Implement bulk export
console.log('Bulk export');
}, []);
const handleBulkSetDueDate = useCallback(async (date: string) => {
// TODO: Implement bulk set due date
console.log('Bulk set due date:', date);
}, []);
return {
handleClearSelection,
handleBulkStatusChange,
handleBulkPriorityChange,
handleBulkPhaseChange,
handleBulkAssignToMe,
handleBulkAssignMembers,
handleBulkAddLabels,
handleBulkArchive,
handleBulkDelete,
handleBulkDuplicate,
handleBulkExport,
handleBulkSetDueDate,
};
};

View File

@@ -0,0 +1,176 @@
import { useState, useCallback } from 'react';
import { DragEndEvent, DragOverEvent, DragStartEvent } from '@dnd-kit/core';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { reorderTasksInGroup, moveTaskBetweenGroups } from '@/features/task-management/task-management.slice';
import { Task, TaskGroup } from '@/types/task-management.types';
export const useDragAndDrop = (allTasks: Task[], groups: TaskGroup[]) => {
const dispatch = useAppDispatch();
const [activeId, setActiveId] = useState<string | null>(null);
const handleDragStart = useCallback((event: DragStartEvent) => {
setActiveId(event.active.id as string);
}, []);
const handleDragOver = useCallback(
(event: DragOverEvent) => {
const { active, over } = event;
if (!over) return;
const activeId = active.id;
const overId = over.id;
// Find the active task and the item being dragged over
const activeTask = allTasks.find(task => task.id === activeId);
if (!activeTask) return;
// Check if we're dragging over a task or a group
const overTask = allTasks.find(task => task.id === overId);
const overGroup = groups.find(group => group.id === overId);
// Find the groups
const activeGroup = groups.find(group => group.taskIds.includes(activeTask.id));
let targetGroup = overGroup;
if (overTask) {
targetGroup = groups.find(group => group.taskIds.includes(overTask.id));
}
if (!activeGroup || !targetGroup) return;
// If dragging to a different group, we need to handle cross-group movement
if (activeGroup.id !== targetGroup.id) {
console.log('Cross-group drag detected:', {
activeTask: activeTask.id,
fromGroup: activeGroup.id,
toGroup: targetGroup.id,
});
}
},
[allTasks, groups]
);
const handleDragEnd = useCallback(
(event: DragEndEvent) => {
const { active, over } = event;
setActiveId(null);
if (!over || active.id === over.id) {
return;
}
const activeId = active.id;
const overId = over.id;
// Find the active task
const activeTask = allTasks.find(task => task.id === activeId);
if (!activeTask) {
console.error('Active task not found:', activeId);
return;
}
// Find the groups
const activeGroup = groups.find(group => group.taskIds.includes(activeTask.id));
if (!activeGroup) {
console.error('Could not find active group for task:', activeId);
return;
}
// Check if we're dropping on a task or a group
const overTask = allTasks.find(task => task.id === overId);
const overGroup = groups.find(group => group.id === overId);
let targetGroup = overGroup;
let insertIndex = 0;
if (overTask) {
// Dropping on a task
targetGroup = groups.find(group => group.taskIds.includes(overTask.id));
if (targetGroup) {
insertIndex = targetGroup.taskIds.indexOf(overTask.id);
}
} else if (overGroup) {
// Dropping on a group (at the end)
targetGroup = overGroup;
insertIndex = targetGroup.taskIds.length;
}
if (!targetGroup) {
console.error('Could not find target group');
return;
}
const isCrossGroup = activeGroup.id !== targetGroup.id;
const activeIndex = activeGroup.taskIds.indexOf(activeTask.id);
console.log('Drag operation:', {
activeId,
overId,
activeTask: activeTask.name || activeTask.title,
activeGroup: activeGroup.id,
targetGroup: targetGroup.id,
activeIndex,
insertIndex,
isCrossGroup,
});
if (isCrossGroup) {
// Moving task between groups
console.log('Moving task between groups:', {
task: activeTask.name || activeTask.title,
from: activeGroup.title,
to: targetGroup.title,
newPosition: insertIndex,
});
// Move task to the target group
dispatch(
moveTaskBetweenGroups({
taskId: activeId as string,
sourceGroupId: activeGroup.id,
targetGroupId: targetGroup.id,
})
);
// Reorder task within target group at drop position
dispatch(
reorderTasksInGroup({
sourceTaskId: activeId as string,
destinationTaskId: over.id as string,
sourceGroupId: activeGroup.id,
destinationGroupId: targetGroup.id,
})
);
} else {
// Reordering within the same group
console.log('Reordering task within same group:', {
task: activeTask.name || activeTask.title,
group: activeGroup.title,
from: activeIndex,
to: insertIndex,
});
if (activeIndex !== insertIndex) {
// Reorder task within same group at drop position
dispatch(
reorderTasksInGroup({
sourceTaskId: activeId as string,
destinationTaskId: over.id as string,
sourceGroupId: activeGroup.id,
destinationGroupId: activeGroup.id,
})
);
}
}
},
[allTasks, groups, dispatch]
);
return {
activeId,
handleDragStart,
handleDragOver,
handleDragEnd,
};
};