Chores: claim from the pool; admin picks who appears on the family board
build-container / build (push) Successful in 4m21s
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:
1 parent
eef1adaa73
commit
870c7129b9
11 files changed
+39
-18
No files matched your search
@@ -25,12 +25,13 @@ function checkPin(uid, pin) {
|
||||
const ymdOk = s => /^\d{4}-\d{2}-\d{2}$/.test(s || '');
|
||||
const isKid = u => !!(u.kid && u.kid.on);
|
||||
const palette = ['#e0742b', '#2f9e6e', '#4f7cff', '#8a5cf0', '#d9453a', '#2aa6a0', '#e5a00d'];
|
||||
const people = () => users.all().filter(u => !u.disabled).map((u, i) => ({ id: u.id, name: u.name, kid: isKid(u), pin: hasPin(u.id), color: palette[i % palette.length] }));
|
||||
const onBoard = u => !u.disabled && u.board !== false; // the admin picks who is on the family board
|
||||
const people = () => users.all().filter(onBoard).map((u, i) => ({ id: u.id, name: u.name, kid: isKid(u), pin: hasPin(u.id), color: palette[i % palette.length] }));
|
||||
|
||||
async function board(day) {
|
||||
const t1 = chores.addDays(day, 1), from = new Date(day + 'T00:00:00').getTime() - 864e5, to = new Date(t1 + 'T23:59:59').getTime() + 864e5;
|
||||
let events = []; try { events = cal.familyEvents({ from, to, fd: day, td: t1 }); } catch {}
|
||||
return { day, people: people(), announcement: chat.announcement(), events, chores: chores.board(day).map(i => ({ title: i.title, points: i.points, user: i.user, userName: i.userName, done: !!i.done })), shopping: await recipes.shoppingOpen(), notes: notes.familyNotes(), tasks: tasks.familyOpen() };
|
||||
return { day, people: people(), announcement: chat.announcement(), events, chores: chores.board(day).filter(i => !i.user || onBoard(users.get(i.user) || {})).map(i => ({ title: i.title, points: i.points, user: i.user, userName: i.userName, done: !!i.done })), shopping: await recipes.shoppingOpen(), notes: notes.familyNotes(), tasks: tasks.familyOpen() };
|
||||
}
|
||||
|
||||
async function handle(req, res) {
|
||||
@@ -39,7 +40,7 @@ async function handle(req, res) {
|
||||
if (p === '/api/board' && req.method === 'GET') { if (!dev) throw fail(403, 'This is not a family device'); const day = u.searchParams.get('day'); return json(res, 200, await board(ymdOk(day) ? day : new Date().toISOString().slice(0, 10))); }
|
||||
if (p === '/api/board/switch' && req.method === 'POST') {
|
||||
if (!dev) throw fail(403, 'This is not a family device'); const b = JSON.parse(await readBody(req, 5e3) || '{}'), t = users.get(String(b.uid));
|
||||
if (!t || t.disabled) throw fail(404, 'Person not found');
|
||||
if (!t || !onBoard(t)) throw fail(404, 'Person not found');
|
||||
if (!isKid(t) || hasPin(t.id)) { // a child with no PIN just taps their name; everyone else needs theirs
|
||||
if (!hasPin(t.id)) throw fail(403, 'Set a PIN first (Settings, on your own device), or sign in with your passkey');
|
||||
if (!checkPin(t.id, b.pin)) { audit.log('family device: wrong PIN', { who: t.name }, req); throw fail(401, 'That PIN is not right'); }
|
||||
|
||||
Reference in new issue
Block a user