// ── Global tasks view ──
import { $, esc, api } from './util.js';
import { state } from './state.js';
const overlay = $('tasks');
const btn = $('tasks-btn');
const closeBtn = $('tasks-close');
const statusFilter = $('tasks-status-filter');
const bucketFilter = $('tasks-bucket-filter');
const list = $('tasks-list');
const summary = $('tasks-summary');
const countBadge = $('tasks-open-count');
function collectTasks() {
const all = [];
for (const card of state.cards) {
const re = /- \[([ xX])\][ \t]*([^\n\r]*)/g;
let m, idx = 0;
while ((m = re.exec(card.body || '')) !== null) {
all.push({ cardId: card.id, cardTitle: card.title || 'untitled', cardColor: card.color || '#94a3b8',
bucketId: card.bucket_id, bucketName: card.bucket_name || '', done: m[1].toLowerCase() === 'x',
text: (m[2] || '').trim() || '(empty task)', todoIndex: idx++ });
}
}
return all;
}
function filter(tasks) {
const s = statusFilter?.value || 'open', b = bucketFilter?.value || '';
return tasks.filter(t => {
if (s === 'open' && t.done) return false;
if (s === 'done' && !t.done) return false;
if (b === 'none') return !t.bucketId;
if (b && t.bucketId != b) return false;
return true;
});
}
export function refreshTasksView() {
if (!countBadge) return;
const tasks = collectTasks();
const open = tasks.filter(t => !t.done).length;
countBadge.textContent = String(open);
if (!overlay?.classList.contains('open') || !list) return;
const filtered = filter(tasks);
if (summary) summary.textContent = `open: ${open} | done: ${tasks.length - open} | showing: ${filtered.length}`;
if (!filtered.length) {
list.innerHTML = `
`;
return;
}
list.innerHTML = filtered.map(t => `
${esc(t.text)}
`).join('');
list.querySelectorAll('[data-task-toggle]').forEach(b => b.addEventListener('click', async e => {
e.preventDefault(); e.stopPropagation();
const [cardId, idx] = b.dataset.taskToggle.split(':');
await toggleTask(cardId, Number(idx));
}));
list.querySelectorAll('[data-task-open]').forEach(b => b.addEventListener('click', e => {
e.preventDefault(); e.stopPropagation();
closeTasks();
window._openDetail(b.dataset.taskOpen);
}));
}
async function toggleTask(cardId, todoIdx) {
const card = state.cards.find(c => c.id == cardId);
if (!card) return;
let idx = 0, changed = false;
const next = (card.body || '').replace(/- \[([ xX])\]/g, (m, s) => {
if (idx++ !== todoIdx) return m;
changed = true;
return `- [${s.toLowerCase() === 'x' ? ' ' : 'x'}]`;
});
if (!changed) return;
const updated = await api(`api/cards/${cardId}`, { method: 'PATCH', body: { body: next } });
if (updated?.id) { const i = state.cards.findIndex(c => c.id == updated.id); if (i !== -1) state.cards[i] = updated; }
else card.body = next;
if (state.viewingCard?.id == cardId) {
const latest = state.cards.find(c => c.id == cardId);
if (latest) { state.viewingCard = latest; /* detail re-render handled by board */ }
}
window._renderBoard();
}
export function openTasks() {
if (!overlay) return;
window._closeSearch?.();
overlay.classList.add('open');
refreshTasksView();
}
export function closeTasks() { overlay?.classList.remove('open'); }
btn?.addEventListener('click', openTasks);
closeBtn?.addEventListener('click', closeTasks);
overlay?.addEventListener('click', e => { if (e.target === overlay) closeTasks(); });
statusFilter?.addEventListener('change', refreshTasksView);
bucketFilter?.addEventListener('change', refreshTasksView);