feat(task-management): enhance Checkbox component and task selection functionality

- Added `indeterminate` state to Checkbox component for better visual representation of partial selections.
- Updated TaskGroup and VirtualizedTaskList components to utilize the new Checkbox features, allowing for group selection with indeterminate states.
- Implemented custom debounce function for saving task fields to localStorage, improving performance during user interactions.
- Enhanced task row styling for better visibility and user experience, particularly in dark mode.
This commit is contained in:
chamikaJ
2025-06-25 10:48:01 +05:30
parent a25fcf209a
commit cf5919a3a0
7 changed files with 367 additions and 120 deletions

View File

@@ -10,6 +10,7 @@ import { RootState } from '@/app/store';
import TaskRow from './task-row';
import AddTaskListRow from '@/pages/projects/projectView/taskList/task-list-table/task-list-table-rows/add-task-list-row';
import { TaskListField } from '@/features/task-management/taskListFields.slice';
import { Checkbox } from '@/components';
const { Text } = Typography;
@@ -136,6 +137,19 @@ const TaskGroup: React.FC<TaskGroupProps> = React.memo(({
};
}, [groupTasks]);
// Calculate selection state for the group checkbox
const { isAllSelected, isIndeterminate } = useMemo(() => {
if (groupTasks.length === 0) {
return { isAllSelected: false, isIndeterminate: false };
}
const selectedTasksInGroup = groupTasks.filter(task => selectedTaskIds.includes(task.id));
const isAllSelected = selectedTasksInGroup.length === groupTasks.length;
const isIndeterminate = selectedTasksInGroup.length > 0 && selectedTasksInGroup.length < groupTasks.length;
return { isAllSelected, isIndeterminate };
}, [groupTasks, selectedTaskIds]);
// Get group color based on grouping type - memoized
const groupColor = useMemo(() => {
if (group.color) return group.color;
@@ -163,6 +177,25 @@ const TaskGroup: React.FC<TaskGroupProps> = React.memo(({
onAddTask?.(group.id);
}, [onAddTask, group.id]);
// Handle select all tasks in group
const handleSelectAllInGroup = useCallback((checked: boolean) => {
if (checked) {
// Select all tasks in the group
groupTasks.forEach(task => {
if (!selectedTaskIds.includes(task.id)) {
onSelectTask?.(task.id, true);
}
});
} else {
// Deselect all tasks in the group
groupTasks.forEach(task => {
if (selectedTaskIds.includes(task.id)) {
onSelectTask?.(task.id, false);
}
});
}
}, [groupTasks, selectedTaskIds, onSelectTask]);
// Memoized style object
const containerStyle = useMemo(() => ({
backgroundColor: isOver
@@ -212,7 +245,18 @@ const TaskGroup: React.FC<TaskGroupProps> = React.memo(({
className="task-table-cell task-table-header-cell"
style={{ width: col.width }}
>
{col.label && <Text className="column-header-text">{col.label}</Text>}
{col.key === 'select' ? (
<div className="flex items-center justify-center h-full">
<Checkbox
checked={isAllSelected}
onChange={handleSelectAllInGroup}
isDarkMode={isDarkMode}
indeterminate={isIndeterminate}
/>
</div>
) : (
col.label && <Text className="column-header-text">{col.label}</Text>
)}
</div>
))}
</div>
@@ -451,6 +495,7 @@ const TaskGroup: React.FC<TaskGroupProps> = React.memo(({
align-items: center;
padding: 0 12px;
border-right: 1px solid var(--task-border-secondary, #f0f0f0);
border-bottom: 1px solid var(--task-border-secondary, #f0f0f0);
font-size: 12px;
white-space: nowrap;
height: 40px;
@@ -465,6 +510,49 @@ const TaskGroup: React.FC<TaskGroupProps> = React.memo(({
border-right: none;
}
/* Add row border styling for task rows */
.task-group-tasks > div {
border-bottom: 1px solid var(--task-border-secondary, #f0f0f0);
transition: border-color 0.3s ease;
}
.task-group-tasks > div:last-child {
border-bottom: none;
}
/* Ensure fixed columns also have bottom borders */
.fixed-columns-row > div {
border-bottom: 1px solid var(--task-border-secondary, #f0f0f0);
transition: border-color 0.3s ease;
}
.scrollable-columns-row > div {
border-bottom: 1px solid var(--task-border-secondary, #f0f0f0);
transition: border-color 0.3s ease;
}
/* Dark mode border adjustments */
.dark .task-table-cell,
[data-theme="dark"] .task-table-cell {
border-right-color: var(--task-border-secondary, #374151);
border-bottom-color: var(--task-border-secondary, #374151);
}
.dark .task-group-tasks > div,
[data-theme="dark"] .task-group-tasks > div {
border-bottom-color: var(--task-border-secondary, #374151);
}
.dark .fixed-columns-row > div,
[data-theme="dark"] .fixed-columns-row > div {
border-bottom-color: var(--task-border-secondary, #374151);
}
.dark .scrollable-columns-row > div,
[data-theme="dark"] .scrollable-columns-row > div {
border-bottom-color: var(--task-border-secondary, #374151);
}
.drag-over {
background-color: var(--task-drag-over-bg, #f0f8ff) !important;
border-color: var(--task-drag-over-border, #40a9ff) !important;