feat(task-management): enhance task list with new components and improved state management

- Introduced TaskListV2 and TaskGroupHeader components for a more organized task display.
- Implemented virtualized rendering using react-virtuoso for efficient task list handling.
- Updated Redux state management to include new selectors and improved task grouping logic.
- Added task filtering capabilities with TaskListFilters component for better user experience.
- Enhanced task selection handling and integrated drag-and-drop functionality for task rows.
- Updated package dependencies to include new libraries for icons and forms.
This commit is contained in:
chamikaJ
2025-07-03 15:31:54 +05:30
parent e26f16bbc2
commit d15c00c29b
19 changed files with 1316 additions and 602 deletions

View File

@@ -1,121 +1,71 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { SelectionState } from '@/types/task-management.types';
import { TaskSelection } from '@/types/task-management.types';
import { RootState } from '@/app/store';
const initialState: SelectionState = {
const initialState: TaskSelection = {
selectedTaskIds: [],
lastSelectedId: null,
lastSelectedTaskId: null,
};
const selectionSlice = createSlice({
name: 'selection',
name: 'taskManagementSelection',
initialState,
reducers: {
toggleTaskSelection: (state, action: PayloadAction<string>) => {
const taskId = action.payload;
const index = state.selectedTaskIds.indexOf(taskId);
if (index === -1) {
state.selectedTaskIds.push(taskId);
} else {
state.selectedTaskIds.splice(index, 1);
}
state.lastSelectedId = taskId;
},
selectTask: (state, action: PayloadAction<string>) => {
const taskId = action.payload;
if (!state.selectedTaskIds.includes(taskId)) {
state.selectedTaskIds.push(taskId);
}
state.lastSelectedId = taskId;
state.lastSelectedTaskId = taskId;
},
deselectTask: (state, action: PayloadAction<string>) => {
const taskId = action.payload;
state.selectedTaskIds = state.selectedTaskIds.filter(id => id !== taskId);
if (state.lastSelectedId === taskId) {
state.lastSelectedId = state.selectedTaskIds[state.selectedTaskIds.length - 1] || null;
if (state.lastSelectedTaskId === taskId) {
state.lastSelectedTaskId = state.selectedTaskIds[state.selectedTaskIds.length - 1] || null;
}
},
selectMultipleTasks: (state, action: PayloadAction<string[]>) => {
toggleTaskSelection: (state, action: PayloadAction<string>) => {
const taskId = action.payload;
const index = state.selectedTaskIds.indexOf(taskId);
if (index === -1) {
state.selectedTaskIds.push(taskId);
state.lastSelectedTaskId = taskId;
} else {
state.selectedTaskIds.splice(index, 1);
state.lastSelectedTaskId = state.selectedTaskIds[state.selectedTaskIds.length - 1] || null;
}
},
selectRange: (state, action: PayloadAction<string[]>) => {
const taskIds = action.payload;
// Add new task IDs that aren't already selected
taskIds.forEach(id => {
if (!state.selectedTaskIds.includes(id)) {
state.selectedTaskIds.push(id);
}
});
state.lastSelectedId = taskIds[taskIds.length - 1] || state.lastSelectedId;
const uniqueIds = Array.from(new Set([...state.selectedTaskIds, ...taskIds]));
state.selectedTaskIds = uniqueIds;
state.lastSelectedTaskId = taskIds[taskIds.length - 1];
},
selectRangeTasks: (
state,
action: PayloadAction<{ startId: string; endId: string; allTaskIds: string[] }>
) => {
const { startId, endId, allTaskIds } = action.payload;
const startIndex = allTaskIds.indexOf(startId);
const endIndex = allTaskIds.indexOf(endId);
if (startIndex !== -1 && endIndex !== -1) {
const [start, end] =
startIndex <= endIndex ? [startIndex, endIndex] : [endIndex, startIndex];
const rangeIds = allTaskIds.slice(start, end + 1);
// Add range IDs that aren't already selected
rangeIds.forEach(id => {
if (!state.selectedTaskIds.includes(id)) {
state.selectedTaskIds.push(id);
}
});
state.lastSelectedId = endId;
}
},
selectAllTasks: (state, action: PayloadAction<string[]>) => {
state.selectedTaskIds = action.payload;
state.lastSelectedId = action.payload[action.payload.length - 1] || null;
},
clearSelection: state => {
state.selectedTaskIds = [];
state.lastSelectedId = null;
state.lastSelectedTaskId = null;
},
setSelection: (state, action: PayloadAction<string[]>) => {
state.selectedTaskIds = action.payload;
state.lastSelectedId = action.payload[action.payload.length - 1] || null;
resetSelection: state => {
state.selectedTaskIds = [];
state.lastSelectedTaskId = null;
},
resetSelection: () => initialState,
},
});
export const {
toggleTaskSelection,
selectTask,
deselectTask,
selectMultipleTasks,
selectRangeTasks,
selectAllTasks,
toggleTaskSelection,
selectRange,
clearSelection,
setSelection,
resetSelection,
} = selectionSlice.actions;
// Selectors
export const selectSelectedTaskIds = (state: RootState) =>
state.taskManagementSelection.selectedTaskIds;
export const selectLastSelectedId = (state: RootState) =>
state.taskManagementSelection.lastSelectedId;
export const selectHasSelection = (state: RootState) =>
state.taskManagementSelection.selectedTaskIds.length > 0;
export const selectSelectionCount = (state: RootState) =>
state.taskManagementSelection.selectedTaskIds.length;
export const selectIsTaskSelected = (taskId: string) => (state: RootState) =>
export const selectSelectedTaskIds = (state: RootState) => state.taskManagementSelection.selectedTaskIds;
export const selectLastSelectedTaskId = (state: RootState) => state.taskManagementSelection.lastSelectedTaskId;
export const selectIsTaskSelected = (state: RootState, taskId: string) =>
state.taskManagementSelection.selectedTaskIds.includes(taskId);
export default selectionSlice.reducer;