Home: the Tasks card lists what is overdue or due this week from every list, with a tick
build-container / build (push) Successful in 10m51s

This commit is contained in:
nmemmert committed 2026-10-23 09:55:23 -04:00
1 parent 2b79160f95
commit d598501393
3 files changed
+18 -5

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
// App-shell cache only; Seafile/API traffic always goes to the network.
const CACHE = 'hub-v25';
const CACHE = 'hub-v26';
const SHARE = 'hub-share'; // files shared into the app from other apps, held until the person picks a folder
const SHELL = ['/icon.svg', '/manifest.webmanifest', '/icons/icon-192.png', '/icons/apple-touch-icon.png'];
+11 -4
View File
@@ -111,13 +111,20 @@ async function taskPoll() {
try { const s = await jfetch('/api/tasks/summary?today=' + ymd(new Date())), n = (s.overdue || 0) + (s.today || 0); if (n !== taskDue) { taskDue = n; renderNav(); } } catch {}
}
// Home: a card only when something is overdue or due today
// Home: the tasks that are overdue, due today or due this week, from every list (NE Hub and iCloud), with a tick to finish each
async function renderTasksCard(el) {
if (!el) return;
try {
const s = await jfetch('/api/tasks/summary?today=' + ymd(new Date())), n = s.overdue + s.today;
if (!n || !document.body.contains(el)) return;
el.innerHTML = `<h2>Tasks</h2><a class="row card2" href="#/tasks">${icon('check')}<span class="grow"><b>${n} task${n === 1 ? '' : 's'} need${n === 1 ? 's' : ''} attention</b><small>${s.overdue ? s.overdue + ' overdue' : ''}${s.overdue && s.today ? ' · ' : ''}${s.today ? s.today + ' due today' : ''}</small></span>${icon('chev', 'chev')}</a>`;
const r = await jfetch('/api/tasks/upcoming?today=' + ymd(new Date()));
if (!document.body.contains(el)) return; if (!r.tasks.length) { el.innerHTML = ''; return; }
const rows = r.tasks.map((t, i) => { const du = dueInfo(t.due);
return `<div class="row it"><button class="ibtn tick" data-h="${i}" aria-label="Mark done">${icon('check')}</button><a class="rmain grow" href="#/tasks" style="color:inherit"><span class="grow"><b>${esc(t.title)}</b><small><span style="color:${du.color}">${esc(du.text)}</span>${t.listName ? ' · ' + esc(t.listName) : ''}</small></span></a></div>`; }).join('');
el.innerHTML = `<h2>Tasks</h2><div class="list">${rows}</div><p style="margin:6px 2px 0"><a href="#/tasks" style="color:var(--accent)">${r.total > r.tasks.length ? 'All ' + r.total + ' coming up' : 'All tasks'}</a></p>`;
el.querySelectorAll('button[data-h]').forEach(b => b.onclick = async () => {
const t = r.tasks[+b.dataset.h]; b.disabled = true;
try { await jfetch('/api/tasks/toggle', { method: 'POST', body: JSON.stringify({ list: t.list, id: t.id, href: t.href, done: true }) }); taskPoll(); renderTasksCard(el); }
catch (err) { b.disabled = false; toast(err.message); }
});
} catch {}
}
+6
View File
@@ -152,6 +152,12 @@ async function handle(req, res) {
if (!/^\d{4}-\d{2}-\d{2}$/.test(from) || !/^\d{4}-\d{2}-\d{2}$/.test(to)) throw new Error('Bad date range');
return json(res, 200, (await allTasks()).filter(x => !x.done && !x.parent && x.due && x.due >= from && x.due <= to).slice(0, 500));
}
if (p === '/api/tasks/upcoming' && req.method === 'GET') { // for the Home card: what is overdue, due today or due in the next week, from every list
const today = q.get('today') || new Date().toISOString().slice(0, 10); if (!/^\d{4}-\d{2}-\d{2}$/.test(today)) throw new Error('Bad date');
const end = new Date(today + 'T00:00:00Z'); end.setUTCDate(end.getUTCDate() + 7); const last = end.toISOString().slice(0, 10);
const rows = (await allTasks()).filter(x => !x.done && !x.parent && x.due && x.due <= last).sort((a, b) => a.due.localeCompare(b.due) || a.title.localeCompare(b.title));
return json(res, 200, { total: rows.length, tasks: rows.slice(0, 8) });
}
if (p === '/api/tasks/summary' && req.method === 'GET') { // for the Home card: open tasks that are overdue or due today
const today = q.get('today') || new Date().toISOString().slice(0, 10), out = { overdue: 0, today: 0, open: 0 };
const count = list => list.forEach(t => { if (t.done) return; out.open++; if (t.due && t.due < today) out.overdue++; else if (t.due === today) out.today++; });