// "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;