Chores: claim from the pool; admin picks who appears on the family board
build-container / build (push) Successful in 4m21s

- "Anyone" chores get Take it / Put back; a claimed chore is that person's for the day
- Per-person "Show on the family board" switch controls board tiles and family chore progress
- Tests and README updated

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-26 13:23:59 -04:00
1 parent eef1adaa73
commit 870c7129b9
11 files changed
+39 -18

No files matched your search

+6
View File
@@ -30,6 +30,12 @@ const hub = http.createServer((req, res) => users.runAs(P[req.headers['x-user']
const once = await j(await post('/', { title: 'Fix the gate', repeat: 'once', date: chores.addDays(today, -2), assign: 'anyone', points: 8 })); let ob = (await board('b')).find(x => x.title === 'Fix the gate'); assert.equal(ob.overdue, true); await post('/done', { chore: once.id, date: today }, 'b'); ob = (await board('b')).find(x => x.title === 'Fix the gate'); assert.equal(ob.done.byName, 'Bob'); assert.equal(ob.overdue, false);
// points
const sm = await j(await call('/summary?range=week', {}, 'a')); const bob = sm.people.find(x => x.name === 'Bob'), cy = sm.people.find(x => x.name === 'Cy'); assert.equal(bob.points, 3 + 8, 'Bob: dishes 3 and the gate 8'); assert.equal(cy.points, 3, 'Cy: dishes ticked by an admin counts for Cy'); assert.equal(sm.people[0].name, 'Bob', 'most points first'); assert.equal(bob.perDay.length, 7); assert.equal(bob.perDay.at(-1), 2);
// taking a chore from the pool
const sweep = await j(await post('/', { title: 'Sweep', repeat: 'daily', assign: 'anyone', points: 2 })); let sw = (await board('b')).find(x => x.title === 'Sweep'); assert.equal(sw.claimable, true); assert.equal(sw.user, null);
assert.equal((await post('/claim', { chore: sweep.id, date: today }, 'b')).status, 200); sw = (await board('b')).find(x => x.title === 'Sweep'); assert.equal(sw.user, P.b.id, 'it is now Bob\'s'); assert.equal(sw.claimed, true); assert.equal(sw.claimable, false);
assert.equal((await post('/claim', { chore: sweep.id, date: today }, 'c')).status, 409, 'someone else cannot take it too'); assert.equal((await post('/done', { chore: sweep.id, date: today }, 'c')).status, 403, 'or tick it off');
assert.equal((await post('/claim', { chore: sweep.id, date: today, undo: true }, 'c')).status, 403, 'or put it back'); assert.equal((await post('/claim', { chore: sweep.id, date: today, undo: true }, 'b')).status, 200); assert.equal((await board('b')).find(x => x.title === 'Sweep').claimable, true, 'put back in the pool');
await post('/claim', { chore: sweep.id, date: today }, 'c'); assert.equal((await post('/done', { chore: sweep.id, date: today }, 'c')).status, 200); sw = (await board('b')).find(x => x.title === 'Sweep'); assert.ok(sw.done && sw.user === P.c.id, 'done by the one who took it'); assert.equal((await post('/claim', { chore: sweep.id, date: today, undo: true }, 'c')).status, 200); assert.equal((await post('/claim', { chore: dishes.id, date: today }, 'b')).status, 400, 'only pool chores');
// delete removes its history
assert.equal((await call('/' + once.id, { method: 'DELETE' }, 'b')).status, 403); assert.equal((await call('/' + once.id, { method: 'DELETE' })).status, 200); assert.equal((await j(await call('/summary', {}, 'a'))).people.find(x => x.name === 'Bob').points, 3);
assert.equal((await call('/?date=nope')).status, 400);