- Refactored TaskRow to simplify state management and enhance readability by extracting logic into custom hooks. - Introduced new components for rendering task columns, including DatePickerColumn, TitleColumn, and various column types for better modularity. - Improved task name editing functionality with better state handling and click outside detection. - Streamlined date handling and formatting within the task row for improved user experience.
141 lines
3.7 KiB
TypeScript
141 lines
3.7 KiB
TypeScript
import React, { memo, useMemo } from 'react';
|
|
import { useSortable } from '@dnd-kit/sortable';
|
|
import { CSS } from '@dnd-kit/utilities';
|
|
import { Task } from '@/types/task-management.types';
|
|
import { useAppSelector } from '@/hooks/useAppSelector';
|
|
import { selectTaskById } from '@/features/task-management/task-management.slice';
|
|
import { selectIsTaskSelected } from '@/features/task-management/selection.slice';
|
|
import { useTaskRowState } from './hooks/useTaskRowState';
|
|
import { useTaskRowActions } from './hooks/useTaskRowActions';
|
|
import { useTaskRowColumns } from './hooks/useTaskRowColumns';
|
|
|
|
interface TaskRowProps {
|
|
taskId: string;
|
|
projectId: string;
|
|
visibleColumns: Array<{
|
|
id: string;
|
|
width: string;
|
|
isSticky?: boolean;
|
|
key?: string;
|
|
custom_column?: boolean;
|
|
custom_column_obj?: any;
|
|
isCustom?: boolean;
|
|
}>;
|
|
isSubtask?: boolean;
|
|
isFirstInGroup?: boolean;
|
|
updateTaskCustomColumnValue?: (taskId: string, columnKey: string, value: string) => void;
|
|
}
|
|
|
|
const TaskRow: React.FC<TaskRowProps> = memo(({
|
|
taskId,
|
|
projectId,
|
|
visibleColumns,
|
|
isSubtask = false,
|
|
isFirstInGroup = false,
|
|
updateTaskCustomColumnValue
|
|
}) => {
|
|
// Get task data and selection state from Redux
|
|
const task = useAppSelector(state => selectTaskById(state, taskId));
|
|
const isSelected = useAppSelector(state => selectIsTaskSelected(state, taskId));
|
|
const themeMode = useAppSelector(state => state.themeReducer.mode);
|
|
const isDarkMode = themeMode === 'dark';
|
|
|
|
// Early return if task is not found
|
|
if (!task) {
|
|
return null;
|
|
}
|
|
|
|
// Use extracted hooks for state management
|
|
const {
|
|
activeDatePicker,
|
|
setActiveDatePicker,
|
|
editTaskName,
|
|
setEditTaskName,
|
|
taskName,
|
|
setTaskName,
|
|
taskDisplayName,
|
|
convertedTask,
|
|
formattedDates,
|
|
dateValues,
|
|
labelsAdapter,
|
|
} = useTaskRowState(task);
|
|
|
|
const {
|
|
handleCheckboxChange,
|
|
handleTaskNameSave,
|
|
handleTaskNameEdit,
|
|
} = useTaskRowActions({
|
|
task,
|
|
taskId,
|
|
taskName,
|
|
editTaskName,
|
|
setEditTaskName,
|
|
});
|
|
|
|
// Drag and drop functionality - only enable for parent tasks
|
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
id: task.id,
|
|
data: {
|
|
type: 'task',
|
|
task,
|
|
},
|
|
disabled: isSubtask, // Disable drag and drop for subtasks
|
|
});
|
|
|
|
// Use extracted column renderer hook
|
|
const { renderColumn } = useTaskRowColumns({
|
|
task,
|
|
projectId,
|
|
isSubtask,
|
|
isSelected,
|
|
isDarkMode,
|
|
visibleColumns,
|
|
updateTaskCustomColumnValue,
|
|
taskDisplayName,
|
|
convertedTask,
|
|
formattedDates,
|
|
dateValues,
|
|
labelsAdapter,
|
|
activeDatePicker,
|
|
setActiveDatePicker,
|
|
editTaskName,
|
|
taskName,
|
|
setEditTaskName,
|
|
setTaskName,
|
|
handleCheckboxChange,
|
|
handleTaskNameSave,
|
|
handleTaskNameEdit,
|
|
attributes,
|
|
listeners,
|
|
});
|
|
|
|
// Memoize style object to prevent unnecessary re-renders
|
|
const style = useMemo(() => ({
|
|
transform: CSS.Transform.toString(transform),
|
|
transition,
|
|
opacity: isDragging ? 0.5 : 1,
|
|
}), [transform, transition, isDragging]);
|
|
|
|
return (
|
|
<div
|
|
ref={setNodeRef}
|
|
style={{ ...style, height: '40px' }}
|
|
className={`flex items-center min-w-max px-1 border-b border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 ${
|
|
isFirstInGroup ? 'border-t border-gray-200 dark:border-gray-700' : ''
|
|
} ${
|
|
isDragging ? 'shadow-lg border border-blue-300' : ''
|
|
}`}
|
|
>
|
|
{visibleColumns.map((column, index) => (
|
|
<React.Fragment key={column.id}>
|
|
{renderColumn(column.id, column.width, column.isSticky, index)}
|
|
</React.Fragment>
|
|
))}
|
|
</div>
|
|
);
|
|
});
|
|
|
|
TaskRow.displayName = 'TaskRow';
|
|
|
|
export default TaskRow;
|