From efbfe77deb89a1f06bd0282a77ba7de8e59fea9b Mon Sep 17 00:00:00 2001 From: shancds Date: Thu, 26 Jun 2025 12:02:21 +0530 Subject: [PATCH] feat(enhanced-kanban): integrate status categories fetching and improve task card behavior - Added fetching of status categories in EnhancedKanbanBoard to ensure data availability. - Enhanced task creation flow in EnhancedKanbanCreateTaskCard by resetting input state and managing focus more effectively. - Improved cleanup in useEffect hooks to prevent memory leaks and ensure proper resource management. - Streamlined imports and updated logic in DeleteStatusDrawer for better task group fetching and error handling. --- .../enhanced-kanban/EnhancedKanbanBoard.tsx | 14 +++++--- .../EnhancedKanbanCreateTaskCard.tsx | 33 ++++++++++++++++--- .../delete-status-drawer.tsx | 17 +++++----- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoard.tsx b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoard.tsx index 6189ca14..998713ff 100644 --- a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoard.tsx +++ b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoard.tsx @@ -45,6 +45,7 @@ import alertService from '@/services/alerts/alertService'; import { IGroupBy } from '@/features/enhanced-kanban/enhanced-kanban.slice'; import EnhancedKanbanCreateSection from './EnhancedKanbanCreateSection'; import ImprovedTaskFilters from '../task-management/improved-task-filters'; +import { fetchStatusesCategories } from '@/features/taskAttributes/taskStatusSlice'; // Import the TaskListFilters component const TaskListFilters = React.lazy(() => import('@/pages/projects/projectView/taskList/task-list-filters/task-list-filters')); @@ -66,7 +67,7 @@ const EnhancedKanbanBoard: React.FC = ({ projectId, cl const { teamId } = useAppSelector((state: RootState) => state.auth); const groupBy = useSelector((state: RootState) => state.enhancedKanbanReducer.groupBy); const project = useAppSelector((state: RootState) => state.projectReducer.project); - + const { statusCategories, status: existingStatuses } = useAppSelector((state) => state.taskStatusReducer); // Local state for drag overlay const [activeTask, setActiveTask] = useState(null); const [activeGroup, setActiveGroup] = useState(null); @@ -86,6 +87,9 @@ const EnhancedKanbanBoard: React.FC = ({ projectId, cl if (projectId) { dispatch(fetchEnhancedKanbanGroups(projectId) as any); } + if (!statusCategories.length) { + dispatch(fetchStatusesCategories() as any); + } }, [dispatch, projectId]); // Get all task IDs for sortable context @@ -385,10 +389,10 @@ const EnhancedKanbanBoard: React.FC = ({ projectId, cl <> {/* Task Filters */}
- Loading filters...
}> - - - + Loading filters...}> + + +
{/* Performance Monitor - only show for large datasets */} {/* {performanceMetrics.totalTasks > 100 && } */} diff --git a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateTaskCard.tsx b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateTaskCard.tsx index 828c45eb..8c946f9b 100644 --- a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateTaskCard.tsx +++ b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanCreateTaskCard.tsx @@ -38,9 +38,11 @@ const EnhancedKanbanCreateTaskCard: React.FC const groupBy = useAppSelector(state => state.enhancedKanbanReducer.groupBy); useEffect(() => { - setTimeout(() => { + const timer = setTimeout(() => { inputRef.current?.focus(); }, 100); + + return () => clearTimeout(timer); }, []); const createRequestBody = (): ITaskCreateRequest | null => { @@ -66,18 +68,30 @@ const EnhancedKanbanCreateTaskCard: React.FC }, 100); }; + const resetForNextTask = () => { + setNewTaskName(''); + setCreatingTask(false); + // Keep the card visible for creating the next task + setTimeout(() => { + inputRef.current?.focus(); + }, 100); + }; + const handleAddTask = async () => { if (creatingTask || !projectId || !currentSession || newTaskName.trim() === '') return; - setCreatingTask(true); + const body = createRequestBody(); - if (!body) return; + if (!body) { + setCreatingTask(true); + setShowNewCard(true); + return; + } // Real-time socket event handler const eventHandler = (task: IProjectTask) => { - setCreatingTask(false); dispatch(addTaskToGroup({ sectionId, task: { ...task, id: task.id || nanoid(), name: task.name || newTaskName.trim() } })); socket?.off(SocketEvents.QUICK_TASK.toString(), eventHandler); - resetForm(); + resetForNextTask(); }; socket?.once(SocketEvents.QUICK_TASK.toString(), eventHandler); socket?.emit(SocketEvents.QUICK_TASK.toString(), JSON.stringify(body)); @@ -89,6 +103,13 @@ const EnhancedKanbanCreateTaskCard: React.FC setCreatingTask(false); }; + const handleBlur = () => { + if (newTaskName.trim() === '') { + setCreatingTask(false); + setShowNewCard(false); + } + }; + return ( > setNewTaskName(e.target.value)} onPressEnter={handleAddTask} + onBlur={handleBlur} placeholder={t('newTaskNamePlaceholder')} style={{ width: '100%', diff --git a/worklenz-frontend/src/components/project-task-filters/delete-status-drawer/delete-status-drawer.tsx b/worklenz-frontend/src/components/project-task-filters/delete-status-drawer/delete-status-drawer.tsx index 48e7ea73..48a5a635 100644 --- a/worklenz-frontend/src/components/project-task-filters/delete-status-drawer/delete-status-drawer.tsx +++ b/worklenz-frontend/src/components/project-task-filters/delete-status-drawer/delete-status-drawer.tsx @@ -7,18 +7,19 @@ import { fetchStatuses, fetchStatusesCategories } from '@/features/taskAttribute import { useMixpanelTracking } from '@/hooks/useMixpanelTracking'; import useTabSearchParam from '@/hooks/useTabSearchParam'; import { fetchTaskGroups } from '@/features/tasks/tasks.slice'; -import { fetchBoardTaskGroups } from '@/features/board/board-slice'; + import { deleteStatusToggleDrawer } from '@/features/projects/status/DeleteStatusSlice'; import { Drawer, Alert, Card, Select, Button, Typography, Badge } from 'antd'; import { DownOutlined } from '@ant-design/icons'; import { useSelector } from 'react-redux'; import { - deleteSection, - IGroupBy, + deleteSection, + IGroupBy, } from '@features/board/board-slice'; import { statusApiService } from '@/api/taskAttributes/status/status.api.service'; import { phasesApiService } from '@/api/taskAttributes/phases/phases.api.service'; import logger from '@/utils/errorLogger'; +import { fetchEnhancedKanbanGroups } from '@/features/enhanced-kanban/enhanced-kanban.slice'; const { Title, Text } = Typography; const { Option } = Select; @@ -43,8 +44,8 @@ const DeleteStatusDrawer: React.FC = () => { const refreshTasks = useCallback(() => { if (!projectId) return; - const fetchAction = projectView === 'list' ? fetchTaskGroups : fetchBoardTaskGroups; - dispatch(fetchAction(projectId)); + const fetchAction = projectView === 'list' ? fetchTaskGroups : fetchEnhancedKanbanGroups; + dispatch(fetchAction(projectId) as any); }, [projectId, projectView, dispatch]); const handleDrawerOpenChange = () => { @@ -71,7 +72,7 @@ const DeleteStatusDrawer: React.FC = () => { dispatch(fetchStatuses(projectId)); refreshTasks(); dispatch(fetchStatusesCategories()); - } else{ + } else { console.error('Error deleting status', res); } } else if (groupBy === IGroupBy.PHASE) { @@ -83,7 +84,7 @@ const DeleteStatusDrawer: React.FC = () => { } catch (error) { logger.error('Error deleting section', error); - }finally { + } finally { setDeletingStatus(false); } }; @@ -98,7 +99,7 @@ const DeleteStatusDrawer: React.FC = () => { open={isDelteStatusDrawerOpen} afterOpenChange={handleDrawerOpenChange} > - + {selectedForDelete?.name}