Board: all people visible in the name picker, PIN enters itself, no number before shopping items
build-container / build (push) Successful in 3m35s

- Name picker wraps in a wider box so five or more people fit
- The board knows each PIN's length and submits when the last digit is typed
- Shopping items typed in are added with no quantity and shown without Mealie's leading 1
- Test updated

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-26 15:12:22 -04:00
1 parent 96b00108bb
commit a45fc1b89c
6 files changed
+13 -12

No files matched your search

+2 -2
View File
@@ -63,7 +63,7 @@
.pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; max-width: 300px; margin: 14px auto 0; } .pad button { height: 64px; font-size: 26px; border-radius: 16px; background: var(--panel2); color: var(--text); border: 1px solid var(--line); font: inherit; font-size: 26px; }
.dots { display: flex; justify-content: center; gap: 12px; margin: 12px 0; min-height: 18px; } .dots i { width: 16px; height: 16px; border-radius: 50%; background: var(--line); } .dots i.on { background: var(--accent); }
#ov { position: fixed; inset: 0; background: rgba(0,0,0,.6); display: grid; place-items: center; padding: 18px; } #ov[hidden] { display: none; }
#ovb { background: var(--panel); border: 1px solid var(--line); border-radius: 20px; padding: 20px; width: 100%; max-width: 380px; text-align: center; }
#ovb .tiles { flex-wrap: wrap; overflow: visible; justify-content: center; } #ovb .tile { width: 96px; } #ovb { background: var(--panel); border: 1px solid var(--line); border-radius: 20px; padding: 20px; width: 100%; max-width: 520px; text-align: center; max-height: 92dvh; overflow-y: auto; scrollbar-width: none; }
.err { color: var(--danger); min-height: 20px; }
/* touch screen: things scroll by dragging, with no scroll bars */
.card, .chl, #ovb div { scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; } .card::-webkit-scrollbar, .chl::-webkit-scrollbar, #ovb div::-webkit-scrollbar { display: none; }
@@ -77,7 +77,7 @@
.bd { height: 100%; display: flex; flex-direction: column; max-width: none; }
.bdtop h1 { font-size: 28px; } .bdclock { font-size: 32px; } .bdtop p { margin: 0; }
.ann { margin: 8px 0; padding: 8px 14px; font-size: 20px; } .who { margin: 8px 0; } .who h2 { margin-bottom: 6px; font-size: 15px; }
.tiles { flex-wrap: nowrap; overflow: hidden; gap: 10px; } .tile { width: 92px; padding: 8px 4px; border-radius: 16px; flex: none; } .tile .av { width: 44px; height: 44px; font-size: 20px; } .tile b { font-size: 14px; }
.tiles { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; gap: 10px; } .tile { width: 92px; padding: 8px 4px; border-radius: 16px; flex: none; } .tile .av { width: 44px; height: 44px; font-size: 20px; } .tile b { font-size: 14px; }
.grid { flex: 1; min-height: 0; grid-template-columns: repeat(2, 1fr); grid-template-rows: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: 10px; }
.card.wide { grid-column: 1 / -1; }
.card.wide { display: flex; flex-direction: column; } .chcols { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; align-items: stretch; } .chcols .chp { display: flex; flex-direction: column; min-height: 0; } .chl { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; display: flex; flex-direction: column; align-items: stretch; overscroll-behavior: contain; } .chl .pill { margin: 3px 0; justify-content: flex-start; } .chl .pill.more { justify-content: center; } .chcols .chp { margin-top: 6px; min-width: 0; }
+3 -3
View File
@@ -47,7 +47,7 @@ function pick(p) {
let pin = ''; const paint = () => { $('#dots').innerHTML = Array.from({ length: Math.max(4, pin.length) }, (_, i) => `<i class="${i < pin.length ? 'on' : ''}"></i>`).join(''); };
box.innerHTML = head + `<p class="sub">Enter your PIN</p><div class="dots" id="dots"></div><div class="err" id="e"></div><div class="pad">${[1, 2, 3, 4, 5, 6, 7, 8, 9, '⌫', 0, '✓'].map(k => `<button data-k="${k}">${k}</button>`).join('')}</div><p><button class="btn ghost" id="no" style="width:100%;justify-content:center">Cancel</button></p>`;
paint(); $('#no').onclick = close;
box.querySelectorAll('.pad button').forEach(b => b.onclick = async () => { const k = b.dataset.k; $('#e').textContent = ''; if (k === '⌫') pin = pin.slice(0, -1); else if (k === '✓') { try { await go(pin); } catch (e) { $('#e').textContent = e.message; pin = ''; } } else if (pin.length < 8) pin += k; paint(); });
box.querySelectorAll('.pad button').forEach(b => b.onclick = async () => { let k = b.dataset.k; $('#e').textContent = ''; if (k === '⌫') pin = pin.slice(0, -1); else if (k !== '✓' && pin.length < 8) { pin += k; if (p.pinLen && pin.length === p.pinLen) k = '✓'; } if (k === '✓') { try { await go(pin); return; } catch (e) { $('#e').textContent = e.message; pin = ''; } } paint(); });
}
clock(); setInterval(clock, 15000); load(); setInterval(() => { if (!document.hidden && $('#ov').hidden) load(); }, 60000);
document.addEventListener('visibilitychange', () => { if (!document.hidden) load(); });
@@ -67,7 +67,7 @@ function choreTap(c) {
if (!p.pin) { const x = sheet(`${title}<p>${esc(p.name)} has not set a PIN yet. Set one in Settings on your own device.</p><button class="btn ghost" id="no" style="width:100%;justify-content:center">OK</button>`); x.box.querySelector('#no').onclick = x.close; return; }
let pin = ''; const { box } = sheet(`${title}<p class="sub">${esc(p.name)}, enter your PIN</p><div class="dots" id="dots"></div><div class="err" id="e"></div><div class="pad">${[1, 2, 3, 4, 5, 6, 7, 8, 9, '⌫', 0, '✓'].map(k => `<button data-k="${k}">${k}</button>`).join('')}</div><p><button class="btn ghost" id="no" style="width:100%;justify-content:center">Cancel</button></p>`);
const paint = () => { box.querySelector('#dots').innerHTML = Array.from({ length: Math.max(4, pin.length) }, (_, i) => `<i class="${i < pin.length ? 'on' : ''}"></i>`).join(''); }; paint(); box.querySelector('#no').onclick = close;
box.querySelectorAll('.pad button').forEach(b => b.onclick = async () => { const k = b.dataset.k; box.querySelector('#e').textContent = ''; if (k === '⌫') pin = pin.slice(0, -1); else if (k === '✓') { try { await send(pin); return; } catch (e) { box.querySelector('#e').textContent = e.message; pin = ''; } } else if (pin.length < 8) pin += k; paint(); });
box.querySelectorAll('.pad button').forEach(b => b.onclick = async () => { let k = b.dataset.k; box.querySelector('#e').textContent = ''; if (k === '⌫') pin = pin.slice(0, -1); else if (k !== '✓' && pin.length < 8) { pin += k; if (p.pinLen && pin.length === p.pinLen) k = '✓'; } if (k === '✓') { try { await send(pin); return; } catch (e) { box.querySelector('#e').textContent = e.message; pin = ''; } } paint(); });
};
if (c.done) return who('undo');
if (c.claimable) { const { box, close } = sheet(`${title}<p class="sub">${c.points ? c.points + ' points' : 'Up for grabs'}</p><button class="btn" id="did" style="width:100%;min-height:52px;justify-content:center;margin-bottom:10px">I did it</button><button class="btn ghost" id="take" style="width:100%;min-height:52px;justify-content:center">Take it for later</button><p><button class="btn ghost" id="no" style="width:100%;justify-content:center">Cancel</button></p>`); box.querySelector('#no').onclick = close; box.querySelector('#did').onclick = () => who('done'); box.querySelector('#take').onclick = () => who('claim'); return; }
@@ -97,6 +97,6 @@ function whoThen(title, payload, doneMsg) {
box.querySelectorAll('.tile').forEach(t => t.onclick = () => { const p = data.people.find(x => x.id === t.dataset.id); if (p.kid && !p.pin) return send(p).catch(e => { box.querySelector('#e').textContent = e.message; }); if (!p.pin) { box.querySelector('#e').textContent = p.name + ' has not set a PIN yet. Set one in Settings on your own device.'; return; }
let pin = ''; box.innerHTML = `${head}<p class="sub">${esc(p.name)}, enter your PIN</p><div class="dots" id="dots"></div><div class="err" id="e"></div><div class="pad">${[1, 2, 3, 4, 5, 6, 7, 8, 9, '⌫', 0, '✓'].map(k => `<button data-k="${k}">${k}</button>`).join('')}</div><p><button class="btn ghost" id="no" style="width:100%;justify-content:center">Cancel</button></p>`;
const paint = () => { box.querySelector('#dots').innerHTML = Array.from({ length: Math.max(4, pin.length) }, (_, i) => `<i class="${i < pin.length ? 'on' : ''}"></i>`).join(''); }; paint(); box.querySelector('#no').onclick = close;
box.querySelectorAll('.pad button').forEach(b => b.onclick = async () => { const k = b.dataset.k; box.querySelector('#e').textContent = ''; if (k === '⌫') pin = pin.slice(0, -1); else if (k === '✓') { try { await send(p, pin); return; } catch (e) { box.querySelector('#e').textContent = e.message; pin = ''; } } else if (pin.length < 8) pin += k; paint(); }); });
box.querySelectorAll('.pad button').forEach(b => b.onclick = async () => { let k = b.dataset.k; box.querySelector('#e').textContent = ''; if (k === '⌫') pin = pin.slice(0, -1); else if (k !== '✓' && pin.length < 8) { pin += k; if (p.pinLen && pin.length === p.pinLen) k = '✓'; } if (k === '✓') { try { await send(p, pin); return; } catch (e) { box.querySelector('#e').textContent = e.message; pin = ''; } } paint(); }); });
}
function toast(msg) { let t = document.getElementById('bt'); if (!t) { t = document.createElement('div'); t.id = 'bt'; t.style.cssText = 'position:fixed;left:50%;bottom:24px;transform:translateX(-50%);background:var(--panel2);border:1px solid var(--line);padding:12px 20px;border-radius:20px;font-size:18px;z-index:99'; document.body.appendChild(t); } t.textContent = msg; t.hidden = false; clearTimeout(t._t); t._t = setTimeout(() => { t.hidden = true; }, 2500); }
+1 -1
View File
@@ -1,5 +1,5 @@
// App-shell cache only; Seafile/API traffic always goes to the network.
const CACHE = 'hub-v81';
const CACHE = 'hub-v82';
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'];