// "Tüm Görevler" view: all tasks across projects with grouping + filters. const LSIcons = window.Icons; const { COLUMNS: LSCOLS, relativeDate: lsRel, formatDate: lsFmt, isOverdue: lsOverdue, parseDateKey: lsDate } = window.PMStore; const { Tag: LSTag, Priority: LSPriority, StatusPill: LSStatus, Checkbox: LSCheckbox, PRIORITY_META: LS_PRIO, STATUS_META: LS_STATUS } = window.UI; function ListView({ state, onSelectTask, onToggleDone, onDeleteTask, query, scope = 'all' }) { const [filterStatus, setFilterStatus] = React.useState('all'); const [filterPriority, setFilterPriority] = React.useState('all'); const [filterProject, setFilterProject] = React.useState(scope === 'project' ? state.activeProjectId : 'all'); const [groupBy, setGroupBy] = React.useState(scope === 'project' ? 'status' : 'project'); const [sortBy, setSortBy] = React.useState('due'); React.useEffect(() => { if (scope === 'project') setFilterProject(state.activeProjectId); }, [scope, state.activeProjectId]); const tagById = Object.fromEntries(state.tags.map(t => [t.id, t])); const projById = Object.fromEntries(state.projects.map(p => [p.id, p])); let tasks = state.tasks.filter(t => { if (filterProject !== 'all' && t.projectId !== filterProject) return false; if (filterStatus !== 'all' && t.status !== filterStatus) return false; if (filterPriority !== 'all' && t.priority !== filterPriority) return false; if (query) { const q = query.toLowerCase(); if (!t.title.toLowerCase().includes(q) && !(t.description||'').toLowerCase().includes(q) && !t.tags.some(tid => (tagById[tid]?.name || '').toLowerCase().includes(q))) return false; } return true; }); // Sort within groups const sortFn = (a, b) => { if (sortBy === 'due') { if (!a.due && !b.due) return 0; if (!a.due) return 1; if (!b.due) return -1; return lsDate(a.due) - lsDate(b.due); } if (sortBy === 'priority') { const order = { high: 0, medium: 1, low: 2 }; return order[a.priority] - order[b.priority]; } if (sortBy === 'title') return a.title.localeCompare(b.title, 'tr'); return 0; }; tasks = [...tasks].sort(sortFn); // Group const groups = groupTasks(tasks, groupBy, state); const total = tasks.length; const doneTotal = tasks.filter(t => t.status === 'done').length; return (
{/* Summary header */}
{total} {' '}görev {total > 0 && <> · {doneTotal} tamamlandı · {total - doneTotal} aktif}
Grupla Sırala
Durum setFilterStatus('all')}>Hepsi {LSCOLS.map(c => ( setFilterStatus(c.id)} dot={c.color}>{c.label} ))}
Öncelik setFilterPriority('all')}>Hepsi setFilterPriority('high')}>Yüksek setFilterPriority('medium')}>Orta setFilterPriority('low')}>Düşük {scope !== 'project' && ( <>
Proje setFilterProject('all')}>Hepsi {state.projects.map(p => ( setFilterProject(p.id)} dot={p.color}>{p.name} ))} )}
{tasks.length === 0 ? (
Görev bulunamadı
Filtreleri temizleyin veya yeni görev ekleyin.
) : (
Görev Proje Durum Teslim Öncelik
{groups.map(grp => ( {groupBy !== 'none' && (
{grp.dot && } {grp.label} {grp.tasks.length}
)} {grp.tasks.map(t => { const proj = projById[t.projectId]; const overdueT = lsOverdue(t.due, t.status); const taskTags = (t.tags || []).map(id => tagById[id]).filter(Boolean); return (
onSelectTask(t.id)}> onToggleDone(t.id)} />
{t.title}
{taskTags.length > 0 && (
{taskTags.slice(0, 4).map(tag => )}
)}
{proj && <> {proj.name} }
{t.due ? lsRel(t.due) : '—'}
e.stopPropagation()}>
); })}
))}
)}
); } function groupTasks(tasks, groupBy, state) { if (groupBy === 'none') { return [{ id: 'all', label: 'Tümü', tasks }]; } if (groupBy === 'project') { const map = new Map(); state.projects.forEach(p => map.set(p.id, { id: p.id, label: p.name, dot: p.color, tasks: [] })); tasks.forEach(t => map.get(t.projectId)?.tasks.push(t)); return [...map.values()].filter(g => g.tasks.length > 0); } if (groupBy === 'status') { const map = new Map(); LSCOLS.forEach(c => map.set(c.id, { id: c.id, label: c.label, dot: c.color, tasks: [] })); tasks.forEach(t => map.get(t.status)?.tasks.push(t)); return [...map.values()].filter(g => g.tasks.length > 0); } if (groupBy === 'priority') { const labels = { high: 'Yüksek Öncelik', medium: 'Orta Öncelik', low: 'Düşük Öncelik' }; const dots = { high: '#b91c1c', medium: '#b45309', low: '#1d4ed8' }; const map = new Map(); ['high','medium','low'].forEach(p => map.set(p, { id: p, label: labels[p], dot: dots[p], tasks: [] })); tasks.forEach(t => map.get(t.priority)?.tasks.push(t)); return [...map.values()].filter(g => g.tasks.length > 0); } if (groupBy === 'due') { const today = new Date(); today.setHours(0,0,0,0); const week = new Date(today); week.setDate(week.getDate() + 7); const buckets = { overdue: { id: 'overdue', label: 'Gecikmiş', dot: '#b91c1c', tasks: [] }, today: { id: 'today', label: 'Bugün', dot: '#b45309', tasks: [] }, week: { id: 'week', label: 'Bu Hafta', dot: '#1d4ed8', tasks: [] }, later: { id: 'later', label: 'Daha Sonra', dot: '#6d28d9', tasks: [] }, none: { id: 'none', label: 'Tarihsiz', dot: '#94a3b8', tasks: [] }, }; tasks.forEach(t => { if (!t.due) return buckets.none.tasks.push(t); const d = lsDate(t.due); d.setHours(0,0,0,0); if (d < today && t.status !== 'done') return buckets.overdue.tasks.push(t); if (d.getTime() === today.getTime()) return buckets.today.tasks.push(t); if (d < week) return buckets.week.tasks.push(t); return buckets.later.tasks.push(t); }); return Object.values(buckets).filter(g => g.tasks.length > 0); } return [{ id: 'all', label: 'Tümü', tasks }]; } function Chip({ active, onClick, children, dot }) { return ( ); } window.ListView = ListView;