refactor(enhanced-kanban): improve code readability and integrate TaskListFilters component
- Refactored EnhancedKanbanBoard and EnhancedKanbanGroup components for better code organization and readability. - Integrated TaskListFilters component to enhance task filtering capabilities within the kanban board. - Cleaned up unnecessary whitespace and improved formatting for consistency across the codebase.
This commit is contained in:
@@ -23,16 +23,18 @@ import {
|
|||||||
verticalListSortingStrategy,
|
verticalListSortingStrategy,
|
||||||
} from '@dnd-kit/sortable';
|
} from '@dnd-kit/sortable';
|
||||||
import { RootState } from '@/app/store';
|
import { RootState } from '@/app/store';
|
||||||
import {
|
import {
|
||||||
fetchEnhancedKanbanGroups,
|
fetchEnhancedKanbanGroups,
|
||||||
reorderEnhancedKanbanTasks,
|
reorderEnhancedKanbanTasks,
|
||||||
setDragState
|
setDragState
|
||||||
} from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
} from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
||||||
import EnhancedKanbanGroup from './EnhancedKanbanGroup';
|
import EnhancedKanbanGroup from './EnhancedKanbanGroup';
|
||||||
import EnhancedKanbanTaskCard from './EnhancedKanbanTaskCard';
|
import EnhancedKanbanTaskCard from './EnhancedKanbanTaskCard';
|
||||||
import PerformanceMonitor from './PerformanceMonitor';
|
import PerformanceMonitor from './PerformanceMonitor';
|
||||||
import './EnhancedKanbanBoard.css';
|
import './EnhancedKanbanBoard.css';
|
||||||
|
|
||||||
|
// Import the TaskListFilters component
|
||||||
|
const TaskListFilters = React.lazy(() => import('@/pages/projects/projectView/taskList/task-list-filters/task-list-filters'));
|
||||||
interface EnhancedKanbanBoardProps {
|
interface EnhancedKanbanBoardProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
@@ -40,14 +42,14 @@ interface EnhancedKanbanBoardProps {
|
|||||||
|
|
||||||
const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, className = '' }) => {
|
const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, className = '' }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const {
|
const {
|
||||||
taskGroups,
|
taskGroups,
|
||||||
loadingGroups,
|
loadingGroups,
|
||||||
error,
|
error,
|
||||||
dragState,
|
dragState,
|
||||||
performanceMetrics
|
performanceMetrics
|
||||||
} = useSelector((state: RootState) => state.enhancedKanbanReducer);
|
} = useSelector((state: RootState) => state.enhancedKanbanReducer);
|
||||||
|
|
||||||
// Local state for drag overlay
|
// Local state for drag overlay
|
||||||
const [activeTask, setActiveTask] = useState<any>(null);
|
const [activeTask, setActiveTask] = useState<any>(null);
|
||||||
const [activeGroup, setActiveGroup] = useState<any>(null);
|
const [activeGroup, setActiveGroup] = useState<any>(null);
|
||||||
@@ -70,12 +72,12 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
}, [dispatch, projectId]);
|
}, [dispatch, projectId]);
|
||||||
|
|
||||||
// Get all task IDs for sortable context
|
// Get all task IDs for sortable context
|
||||||
const allTaskIds = useMemo(() =>
|
const allTaskIds = useMemo(() =>
|
||||||
taskGroups.flatMap(group => group.tasks.map(task => task.id!)),
|
taskGroups.flatMap(group => group.tasks.map(task => task.id!)),
|
||||||
[taskGroups]
|
[taskGroups]
|
||||||
);
|
);
|
||||||
const allGroupIds = useMemo(() =>
|
const allGroupIds = useMemo(() =>
|
||||||
taskGroups.map(group => group.id),
|
taskGroups.map(group => group.id),
|
||||||
[taskGroups]
|
[taskGroups]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -86,13 +88,13 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
const intersections = pointerIntersections.length > 0
|
const intersections = pointerIntersections.length > 0
|
||||||
? pointerIntersections
|
? pointerIntersections
|
||||||
: rectIntersection(args);
|
: rectIntersection(args);
|
||||||
|
|
||||||
let overId = getFirstCollision(intersections, 'id');
|
let overId = getFirstCollision(intersections, 'id');
|
||||||
|
|
||||||
if (overId) {
|
if (overId) {
|
||||||
// Check if we're over a task or a group
|
// Check if we're over a task or a group
|
||||||
const overGroup = taskGroups.find(g => g.id === overId);
|
const overGroup = taskGroups.find(g => g.id === overId);
|
||||||
|
|
||||||
if (overGroup) {
|
if (overGroup) {
|
||||||
// We're over a group, check if there are tasks in it
|
// We're over a group, check if there are tasks in it
|
||||||
if (overGroup.tasks.length > 0) {
|
if (overGroup.tasks.length > 0) {
|
||||||
@@ -103,7 +105,7 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
(container: any) => container.data.current?.type === 'task'
|
(container: any) => container.data.current?.type === 'task'
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (taskIntersections.length > 0) {
|
if (taskIntersections.length > 0) {
|
||||||
overId = taskIntersections[0].id;
|
overId = taskIntersections[0].id;
|
||||||
}
|
}
|
||||||
@@ -117,11 +119,11 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
const handleDragStart = (event: DragStartEvent) => {
|
const handleDragStart = (event: DragStartEvent) => {
|
||||||
const { active } = event;
|
const { active } = event;
|
||||||
const activeId = active.id as string;
|
const activeId = active.id as string;
|
||||||
|
|
||||||
// Find the active task and group
|
// Find the active task and group
|
||||||
let foundTask = null;
|
let foundTask = null;
|
||||||
let foundGroup = null;
|
let foundGroup = null;
|
||||||
|
|
||||||
for (const group of taskGroups) {
|
for (const group of taskGroups) {
|
||||||
const task = group.tasks.find(t => t.id === activeId);
|
const task = group.tasks.find(t => t.id === activeId);
|
||||||
if (task) {
|
if (task) {
|
||||||
@@ -133,7 +135,7 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
|
|
||||||
setActiveTask(foundTask);
|
setActiveTask(foundTask);
|
||||||
setActiveGroup(foundGroup);
|
setActiveGroup(foundGroup);
|
||||||
|
|
||||||
// Update Redux drag state
|
// Update Redux drag state
|
||||||
dispatch(setDragState({
|
dispatch(setDragState({
|
||||||
activeTaskId: activeId,
|
activeTaskId: activeId,
|
||||||
@@ -144,7 +146,7 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
|
|
||||||
const handleDragOver = (event: DragOverEvent) => {
|
const handleDragOver = (event: DragOverEvent) => {
|
||||||
const { active, over } = event;
|
const { active, over } = event;
|
||||||
|
|
||||||
if (!over) {
|
if (!over) {
|
||||||
setOverId(null);
|
setOverId(null);
|
||||||
dispatch(setDragState({ overId: null }));
|
dispatch(setDragState({ overId: null }));
|
||||||
@@ -153,21 +155,21 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
|
|
||||||
const activeId = active.id as string;
|
const activeId = active.id as string;
|
||||||
const overId = over.id as string;
|
const overId = over.id as string;
|
||||||
|
|
||||||
setOverId(overId);
|
setOverId(overId);
|
||||||
|
|
||||||
// Update over ID in Redux
|
// Update over ID in Redux
|
||||||
dispatch(setDragState({ overId }));
|
dispatch(setDragState({ overId }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDragEnd = (event: DragEndEvent) => {
|
const handleDragEnd = (event: DragEndEvent) => {
|
||||||
const { active, over } = event;
|
const { active, over } = event;
|
||||||
|
|
||||||
// Reset local state
|
// Reset local state
|
||||||
setActiveTask(null);
|
setActiveTask(null);
|
||||||
setActiveGroup(null);
|
setActiveGroup(null);
|
||||||
setOverId(null);
|
setOverId(null);
|
||||||
|
|
||||||
// Reset Redux drag state
|
// Reset Redux drag state
|
||||||
dispatch(setDragState({
|
dispatch(setDragState({
|
||||||
activeTaskId: null,
|
activeTaskId: null,
|
||||||
@@ -258,8 +260,17 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
return (
|
return (
|
||||||
<div className={`enhanced-kanban-board ${className}`}>
|
<div className={`enhanced-kanban-board ${className}`}>
|
||||||
{/* Performance Monitor - only show for large datasets */}
|
{/* Performance Monitor - only show for large datasets */}
|
||||||
{performanceMetrics.totalTasks > 100 && <PerformanceMonitor />}
|
{/* {performanceMetrics.totalTasks > 100 && <PerformanceMonitor />} */}
|
||||||
|
<Card
|
||||||
|
size="small"
|
||||||
|
className="mb-4"
|
||||||
|
styles={{ body: { padding: '12px 16px' } }}
|
||||||
|
>
|
||||||
|
<React.Suspense fallback={<div>Loading filters...</div>}>
|
||||||
|
<TaskListFilters position="board" />
|
||||||
|
</React.Suspense>
|
||||||
|
</Card>
|
||||||
|
|
||||||
{loadingGroups ? (
|
{loadingGroups ? (
|
||||||
<Card>
|
<Card>
|
||||||
<div className="flex justify-center items-center py-8">
|
<div className="flex justify-center items-center py-8">
|
||||||
@@ -281,11 +292,11 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
<SortableContext items={allGroupIds} strategy={horizontalListSortingStrategy}>
|
<SortableContext items={allGroupIds} strategy={horizontalListSortingStrategy}>
|
||||||
<div className="kanban-groups-container">
|
<div className="kanban-groups-container">
|
||||||
{taskGroups.map(group => (
|
{taskGroups.map(group => (
|
||||||
<EnhancedKanbanGroup
|
<EnhancedKanbanGroup
|
||||||
key={group.id}
|
key={group.id}
|
||||||
group={group}
|
group={group}
|
||||||
activeTaskId={dragState.activeTaskId}
|
activeTaskId={dragState.activeTaskId}
|
||||||
overId={overId}
|
overId={overId as string | null}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -293,8 +304,8 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
|
|
||||||
<DragOverlay>
|
<DragOverlay>
|
||||||
{activeTask && (
|
{activeTask && (
|
||||||
<EnhancedKanbanTaskCard
|
<EnhancedKanbanTaskCard
|
||||||
task={activeTask}
|
task={activeTask}
|
||||||
isDragOverlay={true}
|
isDragOverlay={true}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ interface EnhancedKanbanGroupProps {
|
|||||||
// Performance threshold for virtualization
|
// Performance threshold for virtualization
|
||||||
const VIRTUALIZATION_THRESHOLD = 50;
|
const VIRTUALIZATION_THRESHOLD = 50;
|
||||||
|
|
||||||
const EnhancedKanbanGroup: React.FC<EnhancedKanbanGroupProps> = React.memo(({
|
const EnhancedKanbanGroup: React.FC<EnhancedKanbanGroupProps> = React.memo(({
|
||||||
group,
|
group,
|
||||||
activeTaskId,
|
activeTaskId,
|
||||||
overId
|
overId
|
||||||
}) => {
|
}) => {
|
||||||
const { setNodeRef, isOver } = useDroppable({
|
const { setNodeRef, isOver } = useDroppable({
|
||||||
id: group.id,
|
id: group.id,
|
||||||
@@ -33,7 +33,7 @@ const EnhancedKanbanGroup: React.FC<EnhancedKanbanGroupProps> = React.memo(({
|
|||||||
|
|
||||||
// Get task IDs for sortable context
|
// Get task IDs for sortable context
|
||||||
const taskIds = group.tasks.map(task => task.id!);
|
const taskIds = group.tasks.map(task => task.id!);
|
||||||
|
|
||||||
// Check if this group is the target for dropping
|
// Check if this group is the target for dropping
|
||||||
const isTargetGroup = overId === group.id;
|
const isTargetGroup = overId === group.id;
|
||||||
const isDraggingOver = isOver || isTargetGroup;
|
const isDraggingOver = isOver || isTargetGroup;
|
||||||
@@ -56,7 +56,7 @@ const EnhancedKanbanGroup: React.FC<EnhancedKanbanGroupProps> = React.memo(({
|
|||||||
|
|
||||||
// Memoize task rendering to prevent unnecessary re-renders
|
// Memoize task rendering to prevent unnecessary re-renders
|
||||||
const renderTask = useMemo(() => (task: any, index: number) => (
|
const renderTask = useMemo(() => (task: any, index: number) => (
|
||||||
<EnhancedKanbanTaskCard
|
<EnhancedKanbanTaskCard
|
||||||
key={task.id}
|
key={task.id}
|
||||||
task={task}
|
task={task}
|
||||||
isActive={task.id === activeTaskId}
|
isActive={task.id === activeTaskId}
|
||||||
@@ -68,7 +68,7 @@ const EnhancedKanbanGroup: React.FC<EnhancedKanbanGroupProps> = React.memo(({
|
|||||||
const shouldShowDropIndicators = isDraggingOver && !shouldVirtualize;
|
const shouldShowDropIndicators = isDraggingOver && !shouldVirtualize;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={setNodeRef}
|
ref={setNodeRef}
|
||||||
className={`enhanced-kanban-group ${isDraggingOver ? 'drag-over' : ''}`}
|
className={`enhanced-kanban-group ${isDraggingOver ? 'drag-over' : ''}`}
|
||||||
>
|
>
|
||||||
@@ -81,14 +81,14 @@ const EnhancedKanbanGroup: React.FC<EnhancedKanbanGroupProps> = React.memo(({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="enhanced-kanban-group-tasks" ref={groupRef}>
|
<div className="enhanced-kanban-group-tasks" ref={groupRef}>
|
||||||
{group.tasks.length === 0 && isDraggingOver && (
|
{group.tasks.length === 0 && isDraggingOver && (
|
||||||
<div className="drop-preview-empty">
|
<div className="drop-preview-empty">
|
||||||
<div className="drop-indicator">Drop here</div>
|
<div className="drop-indicator">Drop here</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{shouldVirtualize ? (
|
{shouldVirtualize ? (
|
||||||
// Use virtualization for large task lists
|
// Use virtualization for large task lists
|
||||||
<SortableContext items={taskIds} strategy={verticalListSortingStrategy}>
|
<SortableContext items={taskIds} strategy={verticalListSortingStrategy}>
|
||||||
@@ -112,21 +112,21 @@ const EnhancedKanbanGroup: React.FC<EnhancedKanbanGroupProps> = React.memo(({
|
|||||||
<div className="drop-line"></div>
|
<div className="drop-line"></div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<EnhancedKanbanTaskCard
|
<EnhancedKanbanTaskCard
|
||||||
task={task}
|
task={task}
|
||||||
isActive={task.id === activeTaskId}
|
isActive={task.id === activeTaskId}
|
||||||
isDropTarget={overId === task.id}
|
isDropTarget={overId === task.id}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Show drop indicator after last task if dropping at the end */}
|
{/* Show drop indicator after last task if dropping at the end */}
|
||||||
{shouldShowDropIndicators &&
|
{shouldShowDropIndicators &&
|
||||||
index === group.tasks.length - 1 &&
|
index === group.tasks.length - 1 &&
|
||||||
overId === group.id && (
|
overId === group.id && (
|
||||||
<div className="drop-preview-indicator">
|
<div className="drop-preview-indicator">
|
||||||
<div className="drop-line"></div>
|
<div className="drop-line"></div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</SortableContext>
|
</SortableContext>
|
||||||
|
|||||||
Reference in New Issue
Block a user