Family board: chore picker shows a progress bar toward the child's goal
build-container / build (push) Canceled after 0s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-29 09:07:27 -04:00
1 parent 0991185eb4
commit 32db6256e8
1 file changed
+3 -1
+3 -1
View File
@@ -122,11 +122,13 @@ function choreHub(p) {
const paint = () => {
const mine = data.chores.filter(c => c.user === p.id), todo = mine.filter(c => !c.done), done = mine.filter(c => c.done), pool = data.chores.filter(c => c.claimable && !c.done), me = (data.week && data.week.people.find(x => x.id === p.id)) || { points: 0 };
const row = (c, btns, cls) => `<div class="chrow ${cls || ''}"><span class="g">${esc(c.title)}${c.points ? ` <small class="sub">${c.points} pts</small>` : ''}</span>${btns}</div>`, h = t => `<p class="sub" style="margin:12px 0 2px;text-align:left"><b>${t}</b></p>`;
box.innerHTML = head + `<p class="sub" style="margin:0;text-align:left">${me.points} points this week</p><div style="max-height:56dvh;overflow:auto">`
const tier = (data.week ? data.week.tiers : []).find(t => t.id === me.goal), pct = tier ? Math.min(100, Math.round(me.points / tier.points * 100)) : 0, got = tier && me.points >= tier.points;
box.innerHTML = head + (tier ? `<div style="text-align:left;margin:2px 0 4px"><div style="display:flex;justify-content:space-between;gap:10px;font-size:15px"><b>🎯 ${esc(tier.title)}</b><span class="sub">${me.points} / ${tier.points} pts</span></div><div class="bar2" style="height:20px;margin:6px 0 4px;border-radius:10px"><i style="width:${pct}%;border-radius:10px${got ? ';background:#2f9e6e' : ''}"></i></div><small class="sub">${got ? 'You did it! 🎉 Tell a parent' : (tier.points - me.points) + ' more points to go'}</small></div>` : `<p class="sub" style="margin:0;text-align:left">${me.points} points this week${(data.week ? data.week.tiers : []).some(t => ((data.week.people.find(x => x.id === p.id) || {}).tiers || []).includes(t.id)) ? ' · <a href="#" id="pgl" style="color:var(--accent)">Choose a reward to aim for</a>' : ''}</p>`) + `<div style="max-height:50dvh;overflow:auto">`
+ h('To do today') + (todo.map(c => row(c, `<button class="btn" data-a="done" data-c="${esc(c.chore)}" data-u="${esc(c.user || '')}">Done ✓</button>${c.claimed ? `<button class="btn ghost" data-a="unclaim" data-c="${esc(c.chore)}" data-u="${esc(c.user || '')}">Put back</button>` : ''}`)).join('') || '<p class="none" style="text-align:left">Nothing left. Nice! 🎉</p>')
+ (pool.length ? h('Up for grabs. Take one!') + pool.map(c => row(c, `<button class="btn ghost" data-a="claim" data-c="${esc(c.chore)}" data-u="${esc(c.user || '')}">Take it</button><button class="btn" data-a="done" data-c="${esc(c.chore)}" data-u="${esc(c.user || '')}">I did it</button>`)).join('') : '')
+ (done.length ? h('Finished') + done.map(c => row(c, `<button class="btn ghost" data-a="undo" data-c="${esc(c.chore)}" data-u="${esc(c.user || '')}">Undo</button>`, 'dn')).join('') : '')
+ `</div><div class="err" id="e"></div><div style="display:flex;gap:10px;margin-top:10px"><button class="btn ghost" id="sgn" style="flex:1;justify-content:center">Open my account</button><button class="btn" id="no" style="flex:1;justify-content:center">Close</button></div>`;
const pg = box.querySelector('#pgl'); if (pg) pg.onclick = e => { e.preventDefault(); close(); goalFlow(p.id); };
box.querySelector('#no').onclick = close; box.querySelector('#sgn').onclick = () => { close(); pick(p); };
box.querySelectorAll('[data-a]').forEach(b => b.onclick = () => { b.disabled = true; const c = data.chores.find(x => x.chore === b.dataset.c && (x.user || '') === b.dataset.u); if (c) act(c, b.dataset.a); else { b.disabled = false; load().then(paint); } });
};