import React, { memo, useState, useCallback } from 'react'; import { useAppSelector } from '@/hooks/useAppSelector'; import { useAppDispatch } from '@/hooks/useAppDispatch'; import { selectTaskById, createSubtask, selectSubtaskLoading } from '@/features/task-management/task-management.slice'; import TaskRow from './TaskRow'; import SubtaskLoadingSkeleton from './SubtaskLoadingSkeleton'; import { Task } from '@/types/task-management.types'; import { Input, Button } from 'antd'; import { PlusOutlined } from '@ant-design/icons'; import { useSocket } from '@/socket/socketContext'; import { SocketEvents } from '@/shared/socket-events'; import { useTranslation } from 'react-i18next'; import { useAuthService } from '@/hooks/useAuth'; interface TaskRowWithSubtasksProps { taskId: string; projectId: string; visibleColumns: Array<{ id: string; width: string; isSticky?: boolean; }>; updateTaskCustomColumnValue?: (taskId: string, columnKey: string, value: string) => void; } interface AddSubtaskRowProps { parentTaskId: string; projectId: string; visibleColumns: Array<{ id: string; width: string; isSticky?: boolean; }>; onSubtaskAdded: () => void; } const AddSubtaskRow: React.FC = memo(({ parentTaskId, projectId, visibleColumns, onSubtaskAdded }) => { const [isAdding, setIsAdding] = useState(false); const [subtaskName, setSubtaskName] = useState(''); const { socket, connected } = useSocket(); const { t } = useTranslation('task-list-table'); const dispatch = useAppDispatch(); // Get session data for reporter_id and team_id const currentSession = useAuthService().getCurrentSession(); const handleAddSubtask = useCallback(() => { if (!subtaskName.trim() || !currentSession) return; // Create optimistic subtask immediately for better UX dispatch(createSubtask({ parentTaskId, name: subtaskName.trim(), projectId })); // Emit socket event for server-side creation if (connected && socket) { socket.emit( SocketEvents.QUICK_TASK.toString(), JSON.stringify({ name: subtaskName.trim(), project_id: projectId, parent_task_id: parentTaskId, reporter_id: currentSession.id, team_id: currentSession.team_id, }) ); } setSubtaskName(''); setIsAdding(false); onSubtaskAdded(); }, [subtaskName, dispatch, parentTaskId, projectId, connected, socket, currentSession, onSubtaskAdded]); const handleCancel = useCallback(() => { setSubtaskName(''); setIsAdding(false); }, []); const renderColumn = useCallback((columnId: string, width: string) => { const baseStyle = { width }; switch (columnId) { case 'dragHandle': return
; case 'checkbox': return
; case 'taskKey': return
; case 'description': return
; case 'title': return (
{/* Match subtask indentation pattern - tighter spacing */}
{!isAdding ? ( ) : ( setSubtaskName(e.target.value)} onPressEnter={handleAddSubtask} onBlur={handleCancel} placeholder="Type subtask name and press Enter to save" className="w-full h-full border-none shadow-none bg-transparent" style={{ height: '100%', minHeight: '32px', padding: '0', fontSize: '14px' }} autoFocus /> )}
); default: return
; } }, [isAdding, subtaskName, handleAddSubtask, handleCancel, t]); return (
{visibleColumns.map((column, index) => ( {renderColumn(column.id, column.width)} ))}
); }); AddSubtaskRow.displayName = 'AddSubtaskRow'; const TaskRowWithSubtasks: React.FC = memo(({ taskId, projectId, visibleColumns, updateTaskCustomColumnValue }) => { const task = useAppSelector(state => selectTaskById(state, taskId)); const isLoadingSubtasks = useAppSelector(state => selectSubtaskLoading(state, taskId)); const dispatch = useAppDispatch(); const handleSubtaskAdded = useCallback(() => { // Refresh subtasks after adding a new one // The socket event will handle the real-time update }, []); if (!task) { return null; } return ( <> {/* Main task row */} {/* Subtasks and add subtask row when expanded */} {task.show_sub_tasks && ( <> {/* Show loading skeleton while fetching subtasks */} {isLoadingSubtasks && ( <> )} {/* Render existing subtasks when not loading */} {!isLoadingSubtasks && task.sub_tasks?.map((subtask: Task) => (
))} {/* Add subtask row - only show when not loading */} {!isLoadingSubtasks && (
)} )} ); }); TaskRowWithSubtasks.displayName = 'TaskRowWithSubtasks'; export default TaskRowWithSubtasks;