diff --git a/README.md b/README.md index 3c0fb89..2b114cc 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,8 @@ into a hidden frame and prints it — one label, no dialog on most kiosk setups. the site, the visitor's name, who they are visiting, the time in, their WWCC/VIT number or a boxed **No WWCC / VIT**, the photo if you want it, and an optional line of your own text. +The photo is square, matching the crop taken at the kiosk, and sits vertically centred. + Pick your stock from the **Label stock** list and the dimensions fill themselves in. A label noticeably taller than it is wide gets a stacked layout — photo on top, name beneath — which is what you want on a roll printer. Wider stock gets the photo alongside the text instead. Type diff --git a/public/css/kiosk.css b/public/css/kiosk.css index ca6a2c3..bbd569d 100644 --- a/public/css/kiosk.css +++ b/public/css/kiosk.css @@ -353,3 +353,19 @@ a:focus-visible { border: 0; visibility: hidden; } + +/* --------------------------------------------------- host dropdown */ + +.picker { + width: 100%; + padding: 15px 14px; + border: 1px solid var(--rule); + border-radius: 3px; + background: var(--card); + color: var(--ink); + font: inherit; + font-size: 20px; + /* Tall enough to be a comfortable touch target on a tablet. */ + min-height: 58px; +} +.picker:disabled { color: var(--muted); } diff --git a/public/index.html b/public/index.html index cf67ed3..d056748 100644 --- a/public/index.html +++ b/public/index.html @@ -63,7 +63,11 @@
No one matches that. Check the spelling, or ask the front desk.
`; return; } + listEl.innerHTML = matches .slice(0, 60) .map( @@ -202,11 +240,7 @@ function renderHosts(listEl, searchValue, onPick) { ) .join(''); listEl.querySelectorAll('[data-host-id]').forEach((btn) => { - btn.addEventListener('click', () => { - state.hostId = Number(btn.dataset.hostId); - state.hostName = btn.dataset.hostName; - onPick(); - }); + btn.addEventListener('click', () => choose(btn.dataset.hostId, btn.dataset.hostName)); }); } @@ -413,7 +447,7 @@ async function loadSiteContext() { change.textContent = siteConfig.site ? `Site: ${siteConfig.site.name} — change` : 'Choose site'; hosts = await api('/api/hosts'); - renderHosts($('#host-list'), '', () => show('guest-contact')); + renderHosts($('#host-list'), '', () => show('guest-contact'), $('#host-select')); } $('#change-site').addEventListener('click', chooseSite); @@ -448,7 +482,7 @@ $('[data-next="guest-name"]').addEventListener('click', () => { }); $('#in-host-search').addEventListener('input', (e) => - renderHosts($('#host-list'), e.target.value, () => show('guest-contact')) + renderHosts($('#host-list'), e.target.value, () => show('guest-contact'), $('#host-select')) ); $('[data-next="guest-contact"]').addEventListener('click', () => { @@ -522,8 +556,11 @@ $('#do-freq-auth').addEventListener('click', async () => { state.hasStoredPhoto = Boolean(person.hasPhoto); $('#freq-greeting').textContent = `Hi ${person.firstName}. Who are you here to see?`; $('#in-freq-host-search').value = ''; - renderHosts($('#freq-host-list'), '', () => - state.hasStoredPhoto ? submitSignIn() : show('photo') + renderHosts( + $('#freq-host-list'), + '', + () => (state.hasStoredPhoto ? submitSignIn() : show('photo')), + $('#freq-host-select') ); show('freq-host'); } catch (err) { @@ -535,8 +572,11 @@ $('#do-freq-auth').addEventListener('click', async () => { }); $('#in-freq-host-search').addEventListener('input', (e) => - renderHosts($('#freq-host-list'), e.target.value, () => - state.hasStoredPhoto ? submitSignIn() : show('photo') + renderHosts( + $('#freq-host-list'), + e.target.value, + () => (state.hasStoredPhoto ? submitSignIn() : show('photo')), + $('#freq-host-select') ) ); diff --git a/src/sites.js b/src/sites.js index 54010c5..58e98b0 100644 --- a/src/sites.js +++ b/src/sites.js @@ -86,9 +86,9 @@ export function badgeHtml(visit, site, { autoPrint = true, photoUrl = null } = { const pad = unit * 0.07; const nameSize = Math.max(3.2, unit * (portrait ? 0.105 : 0.115)); const bodySize = Math.max(2.0, unit * (portrait ? 0.055 : 0.062)); - // Square, matching the crop taken at the kiosk. Slightly smaller on a portrait - // badge than the old 4:3 frame, so a square photo still leaves room for the name. - const photoWidth = portrait ? unit * 0.46 : unit * 0.42; + // Square, matching the crop taken at the kiosk. Sized so that even a long name + // wrapping onto two lines still fits above the detail rows on a 62 x 90 mm label. + const photoWidth = portrait ? unit * 0.52 : unit * 0.5; // Red only appears on a two-colour roll (DK-22251 on the QL-820NWB). Anywhere // else it prints as grey, so it is off unless the site opts in. @@ -126,7 +126,8 @@ export function badgeHtml(visit, site, { autoPrint = true, photoUrl = null } = { padding: ${pad}mm; display: flex; flex-direction: ${portrait ? 'column' : 'row'}; - align-items: ${portrait ? 'center' : 'stretch'}; + align-items: center; + ${portrait ? 'justify-content: center;' : ''} text-align: ${portrait ? 'center' : 'left'}; gap: ${unit * 0.05}mm; font-family: "Segoe UI", Arial, Helvetica, sans-serif; @@ -137,11 +138,12 @@ export function badgeHtml(visit, site, { autoPrint = true, photoUrl = null } = { width: ${photoWidth}mm; height: ${photoWidth}mm; flex: 0 0 auto; + align-self: center; object-fit: cover; border: 0.3mm solid #000; } .body { - flex: 1 1 auto; + flex: ${portrait ? '0 1 auto' : '1 1 auto'}; min-width: 0; width: 100%; display: flex; @@ -166,7 +168,9 @@ export function badgeHtml(visit, site, { autoPrint = true, photoUrl = null } = { overflow-wrap: anywhere; } .rows { - margin-top: auto; + /* Portrait badges centre the whole block; wider ones push the detail rows to + the bottom edge, which is where the eye expects them beside a photo. */ + margin-top: ${portrait ? `${unit * 0.05}mm` : 'auto'}; padding-top: ${unit * 0.04}mm; font-size: ${bodySize}mm; line-height: 1.35;