import React, { useState } from 'react'; import { useApp } from '../contexts/AppContext'; import { Task, UserStory } from '../types'; import { TaskCard } from './TaskCard'; import { CreateTaskDialog } from './CreateTaskDialog'; import { EditTaskDialog } from './EditTaskDialog'; import { CommentDialog } from './CommentDialog'; import { Card } from './ui/card'; import { Button } from './ui/button'; import { Badge } from './ui/badge'; import { Plus } from 'lucide-react'; import { DndProvider, useDrag, useDrop } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; interface DraggableTaskProps { task: Task; onEdit: (task: Task) => void; onComment: (task: Task) => void; } const DraggableTask: React.FC = ({ task, onEdit, onComment }) => { const [{ isDragging }, drag] = useDrag(() => ({ type: 'TASK', item: { id: task.id }, collect: (monitor) => ({ isDragging: monitor.isDragging(), }), })); return (
); }; interface ColumnProps { title: string; status: Task['status']; tasks: Task[]; onDrop: (taskId: string, newStatus: Task['status']) => void; onEdit: (task: Task) => void; onComment: (task: Task) => void; } const Column: React.FC = ({ title, status, tasks, onDrop, onEdit, onComment }) => { const [{ isOver }, drop] = useDrop(() => ({ accept: 'TASK', drop: (item: { id: string }) => onDrop(item.id, status), collect: (monitor) => ({ isOver: monitor.isOver(), }), })); return (

{title} {tasks.length}

{tasks.map(task => ( ))}
); }; export const KanbanBoard: React.FC = () => { const { tasks, userStories, activeSprint, updateTask } = useApp(); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [selectedUserStoryId, setSelectedUserStoryId] = useState(null); const [editDialogOpen, setEditDialogOpen] = useState(false); const [selectedTask, setSelectedTask] = useState(null); const [commentDialogOpen, setCommentDialogOpen] = useState(false); const sprintUserStories = userStories.filter( story => story.sprintId === activeSprint?.id ); const handleCreateTask = (userStoryId: string) => { setSelectedUserStoryId(userStoryId); setCreateDialogOpen(true); }; const handleEditTask = (task: Task) => { setSelectedTask(task); setEditDialogOpen(true); }; const handleCommentTask = (task: Task) => { setSelectedTask(task); setCommentDialogOpen(true); }; const handleDrop = (taskId: string, newStatus: Task['status']) => { updateTask(taskId, { status: newStatus }); }; if (!activeSprint) { return (

No Active Sprint

Please activate a sprint from the Sprint Management page.

); } return (

{activeSprint.name}

{activeSprint.goal}

{sprintUserStories.map(story => { const storyTasks = tasks.filter(task => task.userStoryId === story.id); return (

{story.title}

{story.storyPoints} pts
t.status === 'todo')} onDrop={handleDrop} onEdit={handleEditTask} onComment={handleCommentTask} /> t.status === 'in-progress')} onDrop={handleDrop} onEdit={handleEditTask} onComment={handleCommentTask} /> t.status === 'blocked')} onDrop={handleDrop} onEdit={handleEditTask} onComment={handleCommentTask} /> t.status === 'done')} onDrop={handleDrop} onEdit={handleEditTask} onComment={handleCommentTask} />
); })} {sprintUserStories.length === 0 && (
No user stories in this sprint. Add user stories from the backlog.
)}
); };