'use client' import { useState } from 'react' import { Task } from '@prisma/client' import { FiEdit2, FiTrash2, FiClock, FiAlertCircle, FiPlus, FiMoreHorizontal } from 'react-icons/fi' import { formatDate, isOverdue } from '@/lib/utils' interface TaskBoardProps { tasks: Task[] loading?: boolean onEdit: (task: Task) => void onDelete: (taskId: string) => void onStatusChange: (taskId: string, status: string) => void onCreateTask: (status: string) => void } const COLUMNS = [ { id: 'TODO', title: 'Chưa làm', color: 'bg-yellow-500', bgColor: 'bg-yellow-50', borderColor: 'border-yellow-200', }, { id: 'IN_PROGRESS', title: 'Đang làm', color: 'bg-blue-500', bgColor: 'bg-blue-50', borderColor: 'border-blue-200', }, { id: 'DONE', title: 'Hoàn thành', color: 'bg-green-500', bgColor: 'bg-green-50', borderColor: 'border-green-200', }, ] export function TaskBoard({ tasks, loading, onEdit, onDelete, onStatusChange, onCreateTask, }: TaskBoardProps) { const [draggedTask, setDraggedTask] = useState(null) const [dragOverColumn, setDragOverColumn] = useState(null) const getTasksByStatus = (status: string) => { return tasks.filter((task) => task.status === status) } const handleDragStart = (e: React.DragEvent, task: Task) => { setDraggedTask(task) e.dataTransfer.effectAllowed = 'move' // Add visual feedback if (e.currentTarget instanceof HTMLElement) { e.currentTarget.style.opacity = '0.5' } } const handleDragEnd = (e: React.DragEvent) => { setDraggedTask(null) setDragOverColumn(null) if (e.currentTarget instanceof HTMLElement) { e.currentTarget.style.opacity = '1' } } const handleDragOver = (e: React.DragEvent, columnId: string) => { e.preventDefault() e.dataTransfer.dropEffect = 'move' setDragOverColumn(columnId) } const handleDragLeave = () => { setDragOverColumn(null) } const handleDrop = (e: React.DragEvent, columnId: string) => { e.preventDefault() if (draggedTask && draggedTask.status !== columnId) { onStatusChange(draggedTask.id, columnId) } setDraggedTask(null) setDragOverColumn(null) } if (loading) { return (
{COLUMNS.map((column) => (
{[1, 2].map((i) => (
))}
))}
) } return (
{COLUMNS.map((column) => { const columnTasks = getTasksByStatus(column.id) const isDropTarget = dragOverColumn === column.id && draggedTask?.status !== column.id return (
handleDragOver(e, column.id)} onDragLeave={handleDragLeave} onDrop={(e) => handleDrop(e, column.id)} className={` rounded-xl p-4 min-h-[500px] transition-all ${column.bgColor} ${column.borderColor} border-2 ${isDropTarget ? 'ring-2 ring-primary-500 ring-offset-2 scale-[1.02]' : ''} `} > {/* Column Header */}

{column.title}

{columnTasks.length}
{/* Tasks */}
{columnTasks.length === 0 ? (

{isDropTarget ? 'Thả task vào đây' : 'Không có task nào'}

) : ( columnTasks.map((task) => ( )) )}
{/* Drop zone at bottom */} {columnTasks.length > 0 && isDropTarget && (

Thả task vào đây

)}
) })}
) } // Task Card Component interface TaskCardProps { task: Task onEdit: (task: Task) => void onDelete: (taskId: string) => void onDragStart: (e: React.DragEvent, task: Task) => void onDragEnd: (e: React.DragEvent) => void } function TaskCard({ task, onEdit, onDelete, onDragStart, onDragEnd }: TaskCardProps) { const [showMenu, setShowMenu] = useState(false) const taskIsOverdue = task.deadline && isOverdue(task.deadline) && task.status !== 'DONE' const handleDelete = () => { if (confirm('Bạn có chắc muốn xóa công việc này?')) { onDelete(task.id) } setShowMenu(false) } const getPriorityColor = () => { if (taskIsOverdue) return 'border-l-red-500' if (task.deadline) { const daysUntil = Math.ceil( (new Date(task.deadline).getTime() - Date.now()) / (1000 * 60 * 60 * 24) ) if (daysUntil <= 1) return 'border-l-orange-500' if (daysUntil <= 3) return 'border-l-yellow-500' } return 'border-l-gray-300' } return (
onDragStart(e, task)} onDragEnd={onDragEnd} className={` bg-white rounded-lg border-l-4 shadow-sm hover:shadow-md transition-all cursor-grab active:cursor-grabbing ${getPriorityColor()} ${taskIsOverdue ? 'bg-red-50' : ''} `} >
{/* Header */}

{task.title}

{showMenu && ( <>
setShowMenu(false)} />
)}
{/* Description */} {task.description && (

{task.description}

)} {/* Footer */}
{task.deadline ? (
{taskIsOverdue ? ( ) : ( )} {new Date(task.deadline).toLocaleDateString('vi-VN', { day: '2-digit', month: '2-digit', })}
) : ( )} {/* Task ID badge */} #{task.id.slice(-4).toUpperCase()}
) }