80 lines
3.0 KiB
TypeScript
80 lines
3.0 KiB
TypeScript
import React from 'react';
|
|
import { Task } from '../types';
|
|
import TaskItem from './TaskItem';
|
|
|
|
interface TaskListProps {
|
|
tasks: Task[];
|
|
onToggleTask: (taskDbId: number) => void;
|
|
onEditTask: (task: Task) => void;
|
|
onDeleteTask: (taskDbId: number) => void;
|
|
onAddChildTask: (parentTask: Task) => void;
|
|
onAddSiblingTask: (task: Task) => void;
|
|
onStatusChange: (taskDbId: number, status: string) => void;
|
|
onDragStart?: (task: Task) => void;
|
|
onDragOver?: (e: React.DragEvent, task: Task) => void;
|
|
onDrop?: (e: React.DragEvent, task: Task) => void;
|
|
onDragEnd?: () => void;
|
|
dragOverTask?: Task | null;
|
|
onChildTaskCompleted?: (task: Task, level: number) => void;
|
|
onParentTaskCompleted?: (task: Task, level: number) => void;
|
|
}
|
|
|
|
const TaskList: React.FC<TaskListProps> = ({ tasks, onToggleTask, onEditTask, onDeleteTask, onAddChildTask, onAddSiblingTask, onStatusChange, onDragStart, onDragOver, onDrop, onDragEnd, dragOverTask, onChildTaskCompleted, onParentTaskCompleted }) => {
|
|
const collectAllTaskIds = (taskList: Task[]): Set<string> => {
|
|
const ids = new Set<string>();
|
|
const walk = (items: Task[]) => {
|
|
for (const t of items) {
|
|
if (t.status === 'done') ids.add(t.task_id);
|
|
if (t.children?.length) walk(t.children);
|
|
}
|
|
};
|
|
walk(taskList);
|
|
return ids;
|
|
};
|
|
|
|
const allCompletedIds = collectAllTaskIds(tasks);
|
|
|
|
const isTaskLocked = (task: Task): boolean => {
|
|
// Check own dependencies
|
|
if (task.dependencies.length > 0 && !task.dependencies.every(depId => allCompletedIds.has(depId))) {
|
|
return true;
|
|
}
|
|
// If has children, check if ALL children are locked (recursive)
|
|
if (task.children && task.children.length > 0) {
|
|
const allChildrenLocked = task.children.every(child => isTaskLocked(child));
|
|
if (allChildrenLocked) return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-4 sm:space-y-5">
|
|
{tasks.map((task, index) => (
|
|
<TaskItem
|
|
key={task.id}
|
|
task={task}
|
|
taskNumber={`${index + 1}`}
|
|
onToggleTask={onToggleTask}
|
|
onEditTask={onEditTask}
|
|
onDeleteTask={onDeleteTask}
|
|
onAddChildTask={onAddChildTask}
|
|
onAddSiblingTask={onAddSiblingTask}
|
|
onStatusChange={onStatusChange}
|
|
onDragStart={onDragStart}
|
|
onDragOver={onDragOver}
|
|
onDrop={onDrop}
|
|
onDragEnd={onDragEnd}
|
|
dragOverTask={dragOverTask}
|
|
isLocked={isTaskLocked(task)}
|
|
level={0}
|
|
isLastChild={index === tasks.length - 1}
|
|
onChildTaskCompleted={onChildTaskCompleted}
|
|
onParentTaskCompleted={onParentTaskCompleted}
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TaskList;
|