Children pick a weekly reward goal, with a Monday reminder

A child chooses the reward they are aiming for (an admin can choose for them); the goal belongs to one week and starts empty each Monday. A child with none gets one daytime reminder that week, settled when they pick. Shown on Chores and the family board.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-27 09:13:32 -04:00
1 parent c97b62004e
commit 714680a94e
7 files changed
+73 -11

No files matched your search

+10
View File
@@ -10,6 +10,7 @@ const tasks = require('./tasks');
const cal = require('./cal');
const mail = require('./mail');
const inbox = require('./inbox');
const chores = require('./chores');
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, 'data');
const readBody = req => new Promise((ok, no) => { const c = []; let n = 0; req.on('data', d => { n += d.length; if (n > 20000) { no(new Error('Too large')); req.destroy(); } else c.push(d); }); req.on('end', () => ok(Buffer.concat(c).toString())); req.on('error', no); });
@@ -46,6 +47,14 @@ async function send(dir, st, uid, payload) {
if (changed) { st.subs = st.subs.filter(s => !s.dead); save(dir, st); }
}
/** A child with no reward goal for this week gets one reminder (in the Notifications list, and on their devices if they have any), in the daytime by their own clock. */
async function goalReminder(u, dir, st, now) {
const lt = localNow(st.subs.length ? st.tz : Intl.DateTimeFormat().resolvedOptions().timeZone, now); if (lt.hm < '08:00' || lt.hm >= '20:00') return;
const wk = chores.goalNeeded(u.id, lt.day); if (!wk) return;
chores.goalReminded(u.id, wk);
await send(dir, st, u.id, { title: 'Pick your reward for this week', body: 'What are you aiming for? Choose a reward on the Chores page.', url: '#/chores', tag: 'goal:' + wk });
}
let lastEvents = 0;
let lastDigest = 0;
/** One pass over everyone: runs every minute. */
@@ -56,6 +65,7 @@ async function tick(now = new Date(), force = false) {
for (const u of users.all()) {
if (u.disabled) continue;
const dir = users.dirOf(u.id), st = load(dir);
await goalReminder(u, dir, st, now).catch(e => console.warn('[push] goal reminder failed:', e.message));
if (!st.subs.length) continue;
await users.runAs(u, async () => {
const lt = localNow(st.tz, now); let dirty = false;