import React, { useState } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, PointerSensor, useSensor, useSensors, closestCorners, useDroppable } from '@dnd-kit/core' import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable' import { useSortable } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' import { HiPlus, HiXMark, HiClock, HiChatBubbleLeftRight, HiPaperClip, HiTrash } from 'react-icons/hi2' import dayjs from 'dayjs' import 'dayjs/locale/tr' import { mockTasks, Task } from '../../../mocks/mockIntranetData' import { Badge } from '@/components/ui' dayjs.locale('tr') type TaskStatus = 'todo' | 'in-progress' | 'review' | 'done' // Droppable Column Component interface DroppableColumnProps { id: TaskStatus children: React.ReactNode } const DroppableColumn: React.FC = ({ id, children }) => { const { setNodeRef } = useDroppable({ id }) return (
{children}
) } // Sortable Task Card Component interface SortableTaskCardProps { task: Task onTaskClick: (task: Task) => void getPriorityColor: (priority: string) => string getPriorityLabel: (priority: string) => string isOverdue: (date: Date | string) => boolean } const SortableTaskCard: React.FC = ({ task, onTaskClick, getPriorityColor, getPriorityLabel, isOverdue }) => { const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: task.id }) const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1 } const overdue = isOverdue(task.dueDate) && task.status !== 'done' return (
{ if (!(e.target as HTMLElement).closest('[data-no-click]')) { onTaskClick(task) } }} >
{getPriorityLabel(task.priority)} {overdue && ( ⚠️ Gecikmiş )}

{task.title}

{task.description}

📁 {task.project}
{task.labels.length > 0 && (
{task.labels.map((label, idx) => ( {label} ))}
)}
{dayjs(task.dueDate).format('DD MMM')}
{task.comments > 0 && (
{task.comments}
)} {task.attachments && task.attachments.length > 0 && (
{task.attachments.length}
)}
{task.assignedTo.slice(0, 3).map((assignee, idx) => ( {assignee.fullName} ))} {task.assignedTo.length > 3 && (
+{task.assignedTo.length - 3}
)}
) } const TasksModule: React.FC = () => { const [tasks, setTasks] = useState(mockTasks) const [selectedTask, setSelectedTask] = useState(null) const [activeId, setActiveId] = useState(null) const [showNewTaskModal, setShowNewTaskModal] = useState(false) const [newTaskColumn, setNewTaskColumn] = useState('todo') const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 8, }, }) ) const columns: { id: TaskStatus; title: string; icon: string; color: string }[] = [ { id: 'todo', title: 'Yapılacak', icon: '📋', color: 'gray' }, { id: 'in-progress', title: 'Devam Ediyor', icon: '⚙️', color: 'blue' }, { id: 'review', title: 'İncelemede', icon: '👀', color: 'yellow' }, { id: 'done', title: 'Tamamlandı', icon: '✅', color: 'green' } ] const handleDragStart = (event: DragStartEvent) => { setActiveId(event.active.id as string) } const handleDragEnd = (event: DragEndEvent) => { const { active, over } = event setActiveId(null) if (!over) return const taskId = active.id as string // over.id could be either a column id or a task id // If it's a column id (from DroppableColumn), use it directly // If it's a task id, find that task's column let newStatus: TaskStatus const overColumn = columns.find(col => col.id === over.id) if (overColumn) { newStatus = overColumn.id } else { // over.id is a task, find its column const overTask = tasks.find(t => t.id === over.id) if (!overTask) return newStatus = overTask.status } // Update task status setTasks(prevTasks => prevTasks.map(task => task.id === taskId ? { ...task, status: newStatus } : task ) ) if (selectedTask?.id === taskId) { setSelectedTask(prev => prev ? { ...prev, status: newStatus } : null) } } const handleStatusChange = (taskId: string, newStatus: TaskStatus) => { setTasks(prevTasks => prevTasks.map(task => task.id === taskId ? { ...task, status: newStatus } : task ) ) if (selectedTask?.id === taskId) { setSelectedTask(prev => prev ? { ...prev, status: newStatus } : null) } } const handleAddTask = (status: TaskStatus) => { setNewTaskColumn(status) setShowNewTaskModal(true) } const handleCreateTask = (title: string, description: string) => { const newTask: Task = { id: `task-${Date.now()}`, title, description, project: 'Genel', assignedTo: [mockTasks[0].assignedTo[0]], // Default assignee assignedBy: mockTasks[0].assignedBy, priority: 'medium', status: newTaskColumn, dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days from now createdAt: new Date(), labels: [], comments: 0 } setTasks(prev => [...prev, newTask]) setShowNewTaskModal(false) } const handleDeleteTask = (taskId: string) => { if (window.confirm('Bu görevi silmek istediğinizden emin misiniz?')) { setTasks(prevTasks => prevTasks.filter(task => task.id !== taskId)) setSelectedTask(null) } } const getTasksByStatus = (status: TaskStatus) => { return tasks.filter((task: Task) => task.status === status) } const getPriorityColor = (priority: string) => { const colors = { low: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 border-gray-200 dark:border-gray-600', medium: 'bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-300 border-blue-200 dark:border-blue-700', high: 'bg-orange-100 dark:bg-orange-900/30 text-orange-600 dark:text-orange-300 border-orange-200 dark:border-orange-700', urgent: 'bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-300 border-red-200 dark:border-red-700' } return colors[priority as keyof typeof colors] } const getPriorityLabel = (priority: string) => { const labels = { low: 'Düşük', medium: 'Orta', high: 'Yüksek', urgent: '🔥 Acil' } return labels[priority as keyof typeof labels] } const isOverdue = (dueDate: Date | string) => { return dayjs(dueDate).isBefore(dayjs(), 'day') } return (
{/* Header */}

Görev & Proje Yönetimi

Görevleri Kanban board ile yönetin

Toplam: {tasks.length} görev
{/* Kanban Board */}
{columns.map(column => { const columnTasks = getTasksByStatus(column.id) return ( t.id)} strategy={verticalListSortingStrategy} >
{/* Column Header */}
{column.icon}

{column.title}

{/* Tasks */}
{columnTasks.map(task => ( ))}
{/* Add Task Button */}
) })}
{/* DragOverlay */} {activeId ? (
{(() => { const task = tasks.find(t => t.id === activeId) if (!task) return null return (

{task.title}

) })()}
) : null}
{/* New Task Modal */} {showNewTaskModal && ( <> setShowNewTaskModal(false)} />
e.stopPropagation()} >

Yeni Görev Oluştur

{ e.preventDefault() const formData = new FormData(e.currentTarget) const title = formData.get('title') as string const description = formData.get('description') as string if (title && description) { handleCreateTask(title, description) } }} className="p-4 sm:p-6 space-y-4" >