import React, { useState } from 'react' import { ChevronRight, ChevronDown, Circle, CheckCircle2, Clock, XCircle, Brain } from 'lucide-react' import { Badge } from '@/components/ui/badge' interface Task { id: string title: string status: 'todo' | 'in_progress' | 'done' | 'blocked' priority: 'low' | 'medium' | 'high' | 'urgent' project: string parent?: string children?: string[] memory_connections?: any[] level?: number } interface TaskTreeViewProps { tasks: Task[] onTaskClick?: (task: Task) => void } export function TaskTreeView({ tasks, onTaskClick }: TaskTreeViewProps) { const [expandedTasks, setExpandedTasks] = useState>(new Set()) const [expandedProjects, setExpandedProjects] = useState>(new Set()) // Group tasks by project const tasksByProject = tasks.reduce((acc, task) => { const project = task.project || 'default' if (!acc[project]) acc[project] = [] acc[project].push(task) return acc }, {} as Record) // Build parent-child relationships const taskMap = new Map(tasks.map(t => [t.id, t])) const rootTasks = tasks.filter(t => !t.parent) const getChildren = (taskId: string): Task[] => { return tasks.filter(t => t.parent === taskId) } const toggleTask = (taskId: string) => { const newExpanded = new Set(expandedTasks) if (newExpanded.has(taskId)) { newExpanded.delete(taskId) } else { newExpanded.add(taskId) } setExpandedTasks(newExpanded) } const toggleProject = (project: string) => { const newExpanded = new Set(expandedProjects) if (newExpanded.has(project)) { newExpanded.delete(project) } else { newExpanded.add(project) } setExpandedProjects(newExpanded) } const getStatusIcon = (status: Task['status']) => { switch (status) { case 'todo': return case 'in_progress': return case 'done': return case 'blocked': return } } const getPriorityColor = (priority: Task['priority']) => { switch (priority) { case 'urgent': return 'text-red-400 bg-red-500/20 border-red-500/30' case 'high': return 'text-orange-400 bg-orange-500/20 border-orange-500/30' case 'medium': return 'text-yellow-400 bg-yellow-500/20 border-yellow-500/30' case 'low': return 'text-green-400 bg-green-500/20 border-green-500/30' } } const renderTask = (task: Task, level: number = 0) => { const children = getChildren(task.id) const hasChildren = children.length > 0 const isExpanded = expandedTasks.has(task.id) const memoryCount = task.memory_connections?.length || 0 return (
0 ? 'ml-' + (level * 6) : ''} `} onClick={() => onTaskClick?.(task)} > {hasChildren && ( )} {!hasChildren &&
} {getStatusIcon(task.status)} {task.title} {memoryCount > 0 && (
{memoryCount}
)} {task.priority}
{isExpanded && hasChildren && (
{children.map(child => ( {renderTask(child, level + 1)} ))}
)}
) } return (
{Object.entries(tasksByProject).map(([project, projectTasks]) => { const isProjectExpanded = expandedProjects.has(project) ?? true const rootProjectTasks = projectTasks.filter(t => !t.parent) return (
{isProjectExpanded && (
{rootProjectTasks.map(task => ( {renderTask(task)} ))}
)}
) })}
) }