import React, { useCallback, useMemo, useState } from 'react'; import { useSortable, defaultAnimateLayoutChanges } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; import { useAppSelector } from '@/hooks/useAppSelector'; import './EnhancedKanbanTaskCard.css'; import Flex from 'antd/es/flex'; import Tag from 'antd/es/tag'; import Tooltip from 'antd/es/tooltip'; import Progress from 'antd/es/progress'; import Button from 'antd/es/button'; import { useAppDispatch } from '@/hooks/useAppDispatch'; import { setShowTaskDrawer, setSelectedTaskId } from '@/features/task-drawer/task-drawer.slice'; import PrioritySection from '../board/taskCard/priority-section/priority-section'; import Typography from 'antd/es/typography'; import CustomAvatarGroup from '../board/custom-avatar-group'; import CustomDueDatePicker from '../board/custom-due-date-picker'; import { themeWiseColor } from '@/utils/themeWiseColor'; import { ForkOutlined } from '@ant-design/icons'; import { Dayjs } from 'dayjs'; import dayjs from 'dayjs'; import { CaretDownFilled, CaretRightFilled } from '@ant-design/icons'; import { fetchBoardSubTasks } from '@/features/enhanced-kanban/enhanced-kanban.slice'; import { Divider } from 'antd'; import { List } from 'antd'; import { Skeleton } from 'antd'; import { PlusOutlined } from '@ant-design/icons'; import BoardSubTaskCard from '@/pages/projects/projectView/board/board-section/board-sub-task-card/board-sub-task-card'; import BoardCreateSubtaskCard from '@/pages/projects/projectView/board/board-section/board-sub-task-card/board-create-sub-task-card'; import { useTranslation } from 'react-i18next'; interface EnhancedKanbanTaskCardProps { task: IProjectTask; sectionId: string; isActive?: boolean; isDragOverlay?: boolean; isDropTarget?: boolean; } // Priority and status colors - moved outside component to avoid recreation const PRIORITY_COLORS = { critical: '#ff4d4f', high: '#ff7a45', medium: '#faad14', low: '#52c41a', } as const; const EnhancedKanbanTaskCard: React.FC = React.memo(({ task, sectionId, isActive = false, isDragOverlay = false, isDropTarget = false }) => { const dispatch = useAppDispatch(); const { t } = useTranslation('kanban-board'); const themeMode = useAppSelector(state => state.themeReducer.mode); const [showNewSubtaskCard, setShowNewSubtaskCard] = useState(false); const [dueDate, setDueDate] = useState( task?.end_date ? dayjs(task?.end_date) : null ); const [isSubTaskShow, setIsSubTaskShow] = useState(false); const projectId = useAppSelector(state => state.projectReducer.projectId); const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: task.id!, data: { type: 'task', task, }, disabled: isDragOverlay, animateLayoutChanges: defaultAnimateLayoutChanges, }); const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1, backgroundColor: themeMode === 'dark' ? '#292929' : '#fafafa', }; const handleCardClick = useCallback((e: React.MouseEvent, id: string) => { // Prevent the event from propagating to parent elements e.stopPropagation(); // Don't handle click if we're dragging if (isDragging) return; dispatch(setSelectedTaskId(id)); dispatch(setShowTaskDrawer(true)); }, [dispatch, isDragging]); const renderLabels = useMemo(() => { if (!task?.labels?.length) return null; return ( <> {task.labels.slice(0, 2).map((label: any) => ( {label.name} ))} {task.labels.length > 2 && + {task.labels.length - 2}} ); }, [task.labels, themeMode]); const handleSubTaskExpand = useCallback(() => { console.log('handleSubTaskExpand', task, projectId); if (task && task.id && projectId) { if (task.show_sub_tasks) { // If subtasks are already loaded, just toggle visibility setIsSubTaskShow(prev => !prev); } else { // If subtasks need to be fetched, show the section first with loading state setIsSubTaskShow(true); dispatch(fetchBoardSubTasks({ taskId: task.id, projectId })); } } }, [task, projectId, dispatch]); const handleSubtaskButtonClick = useCallback((e: React.MouseEvent) => { e.stopPropagation(); handleSubTaskExpand(); }, [handleSubTaskExpand]); const handleAddSubtaskClick = useCallback((e: React.MouseEvent) => { e.stopPropagation(); setShowNewSubtaskCard(true); }, []); return (
handleCardClick(e, task.id || '')}> {renderLabels} = 100 ? 9 : 7} /> {/* Action Icons */}
{task.name} {task && } {/* Subtask Section */} {isSubTaskShow && ( {task.sub_tasks_loading && ( )} {!task.sub_tasks_loading && task?.sub_tasks && task?.sub_tasks.map((subtask: any) => ( ))} {showNewSubtaskCard && ( )} )}
); }); export default EnhancedKanbanTaskCard;