// Kanban view: 4 columns with HTML5 drag-and-drop. Filtered by activeProjectId. const KBIcons = window.Icons; const { COLUMNS: KBCOLS, taskProgress: kbProgress, relativeDate: kbRel, isOverdue: kbOverdue } = window.PMStore; const { Tag: KBTag, Priority: KBPriority } = window.UI; function Kanban({ state, onSelectTask, onUpdateTask, onDeleteTask, onAddTask, query }) { const [dragTaskId, setDragTaskId] = React.useState(null); const [dragOverCol, setDragOverCol] = React.useState(null); const tagById = Object.fromEntries(state.tags.map(t => [t.id, t])); const activeProject = state.projects.find(p => p.id === state.activeProjectId); const filtered = state.tasks.filter(t => { if (t.projectId !== state.activeProjectId) return false; if (!query) return true; const q = query.toLowerCase(); return t.title.toLowerCase().includes(q) || (t.description||'').toLowerCase().includes(q) || t.tags.some(tid => (tagById[tid]?.name || '').toLowerCase().includes(q)); }); const tasksByCol = Object.fromEntries(KBCOLS.map(c => [c.id, []])); filtered.forEach(t => { (tasksByCol[t.status] || tasksByCol.todo).push(t); }); const handleDrop = (e, colId) => { e.preventDefault(); if (dragTaskId) { onUpdateTask(dragTaskId, { status: colId }); } setDragTaskId(null); setDragOverCol(null); }; if (!activeProject) { return (
Proje seçilmedi
Soldaki listeden bir proje seçin.
); } return (
{KBCOLS.map(col => (
{col.label} {tasksByCol[col.id].length}
{ e.preventDefault(); setDragOverCol(col.id); }} onDragLeave={(e) => { if (e.currentTarget === e.target) setDragOverCol(null); }} onDrop={(e) => handleDrop(e, col.id)} > {tasksByCol[col.id].map(t => ( setDragTaskId(t.id)} onDragEnd={() => { setDragTaskId(null); setDragOverCol(null); }} onClick={() => onSelectTask(t.id)} onUpdateStatus={(status) => onUpdateTask(t.id, { status })} onDelete={() => onDeleteTask(t.id)} /> ))} {tasksByCol[col.id].length === 0 && (
Henüz görev yok
)}
))}
); } function TaskCard({ task, tagById, dragging, onDragStart, onDragEnd, onClick, onUpdateStatus, onDelete }) { const pct = kbProgress(task); const overdueT = kbOverdue(task.due, task.status); const taskTags = (task.tags || []).map(id => tagById[id]).filter(Boolean); const subtaskDone = (task.subtasks || []).filter(s => s.done).length; const subtaskTotal = (task.subtasks || []).length; return (
{ e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/plain', task.id); onDragStart(); }} onDragEnd={onDragEnd} onClick={onClick} >
e.stopPropagation()}>
{taskTags.length > 0 && (
{taskTags.slice(0, 3).map(tag => )}
)}
{task.title}
{subtaskTotal > 0 && ( <>
)}
{task.due && ( {kbRel(task.due)} )} {subtaskTotal > 0 && ( {subtaskDone}/{subtaskTotal} )}
e.stopPropagation()}> Durum
); } window.Kanban = Kanban;