Files
design-v3/10-scan-spool.html
2026-09-25 10:26:24 -04:00

48 lines
6.2 KiB
HTML

<style>
.scanwrap { max-width: 560px; width: 100%; margin: 0 auto; display: flex; flex-direction: column; gap: var(--space-4); }
.hero { padding: var(--space-5); display: grid; grid-template-columns: 64px 1fr; gap: 6px 16px; align-items: center; }
.hero h1 { margin: 0; font-size: var(--fs-h2); line-height: 1.15; }
.hero .meter { grid-column: 1 / -1; height: 12px; margin-top: 8px; }
.big { font-size: 40px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.scale { font-size: 28px !important; min-height: 68px !important; text-align: center; }
.res { display: grid; grid-template-columns: 1fr auto 1fr; gap: 8px; align-items: center; text-align: center; padding: var(--space-4); }
.res .n { font-size: 26px; font-weight: 800; font-variant-numeric: tabular-nums; }
.bigbtn { min-height: 60px; font-size: 16px; justify-content: center; width: 100%; border-radius: var(--radius-lg); }
.pick { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.pick a { flex: none; text-decoration: none; color: inherit; padding: 8px 12px; border-radius: var(--radius-pill); border: 1px solid var(--border-control); font-size: 13px; background: var(--surface-raised); }
.pick a[aria-current] { border: 2px solid var(--text-accent); color: var(--text-accent); font-weight: 700; }
</style>
<script>
(function () {
var x = X;
var q = new URLSearchParams(location.search), sid = +(q.get('s') || 41);
var S = { reading: '', saved: null };
function render() {
var s = x.spool(sid), w = x.where(s);
var demo = '<nav class="pick" aria-label="Demo: pick a scanned spool">' + [41, 44, 47, 49].map(function (i) { return '<a href="?s=' + i + '"' + (i === sid ? ' aria-current="page"' : '') + '>#' + i + ' ' + x.esc(x.spool(i).color) + '</a>'; }).join('') + '</nav>';
var weigh;
if (s.tare == null) {
weigh = '<section class="nm-raised panel stack" style="gap:12px"><h2 class="section" style="margin:0">Weigh it</h2><div class="banner"><b>?</b><span>No empty spool weight is known for this spool, so a scale reading can\'t be turned into filament. It is never assumed to be 0.</span></div><select class="select"><option>Pick its spool type…</option><option>Generic — 1 kg spool (assumed) · 180 g · estimated</option><option>Creality — Hyper cardboard · 176 g · community</option></select><button class="btn bigbtn" type="button" data-fake="Spool type saved. Weigh-in unlocked.">Save spool type</button></section>';
} else {
var v = +S.reading, r = Math.round(v - s.tare), ok = v > 0 && v >= s.tare && r <= s.tot + 1;
weigh = '<section class="nm-raised panel stack" style="gap:12px"><h2 class="section" style="margin:0">Weigh it</h2><label class="stack" style="gap:6px"><span class="small strong">Whole spool on the scale</span><input class="input scale num" id="sc" inputmode="numeric" value="' + x.esc(S.reading) + '" placeholder="grams" autocomplete="off"><span class="sub">minus ' + x.g(s.tare) + ' empty spool (' + x.tareProv(s) + ') = what\'s left</span></label>' +
'<div class="res nm-inset"><span><span class="sub">now</span><br><span class="n">' + x.g(s.rem) + '</span></span><span class="muted" style="font-size:22px">→</span><span><span class="sub">after</span><br><span class="n"' + (v && !ok ? ' style="color:var(--status-error)"' : '') + '>' + (v ? x.g(r) : '—') + '</span></span></div>' +
(v && v < s.tare ? '<p class="field-error" style="margin:0">' + x.g(v) + ' is less than the ' + x.g(s.tare) + ' empty spool. Re-weigh, or correct the empty spool weight.</p>' : v && r > s.tot + 1 ? '<p class="field-error" style="margin:0">That leaves ' + x.g(r) + ', more than a full spool (' + x.g(s.tot) + '). Check the total or the empty spool weight.</p>' : '') +
'<button class="btn btn-primary bigbtn" type="button" data-wsave ' + (ok ? '' : 'disabled') + '>Save weigh-in</button></section>';
}
return '<div class="scanwrap">' + demo +
'<section class="hero nm-raised">' + x.sw(s.c, '" style="width:64px;height:64px') + '<div style="min-width:0"><span class="sub">Scanned spool #' + s.id + '</span><h1>' + x.esc(s.color) + '</h1><span class="sub">' + x.esc(x.fullName(s)) + '</span></div>' +
'<div style="grid-column:1/-1;display:flex;align-items:baseline;gap:10px;margin-top:8px"><span class="big"' + (x.low(s) ? ' style="color:var(--status-warning)"' : '') + '>' + Math.round(s.rem).toLocaleString('en-US') + '<span style="font-size:16px"> g</span></span><span class="muted">of ' + x.g(s.tot) + ' net</span><span class="spacer"></span>' + x.remProv(s) + '</div>' + x.meter(s) + '</section>' +
(S.saved ? '<div class="result ok banner" style="border-color:var(--status-success);background:var(--wash-success)" role="status"><b style="color:var(--status-success)">✓</b><span>Saved: ' + x.g(S.saved[0]) + ' → <b>' + x.g(S.saved[1]) + '</b>. Scan the next label whenever you\'re ready.</span></div>' : '') +
'<div class="findit"><span class="sub">Lives in</span><b>' + x.esc(w.text) + '</b></div>' +
weigh +
'<div class="fr2"><a class="btn bigbtn" href="09-scan-holder.html?c=' + (s.cont ? X.holderIds[s.cont] : 5) + '">' + (s.cont ? 'Open its holder' : 'Load into a holder…') + '</a><a class="btn bigbtn" href="02-filament.html#spool=' + s.id + '">Full details</a></div>' +
'<p class="small muted" style="margin:0">Tip: scan a holder\'s label first to start a <a href="09-scan-holder.html">scan session</a>. Spool labels scanned after that load or move into it instead of opening this page.</p></div>';
}
function redraw(focus) { var pos = focus && document.getElementById('sc') && document.getElementById('sc').selectionStart; document.getElementById('page').innerHTML = render(); if (focus && document.getElementById('sc')) { var el = document.getElementById('sc'); el.focus(); el.setSelectionRange(pos, pos); } }
document.addEventListener('input', function (e) { if (e.target.id === 'sc') { S.reading = e.target.value.replace(/[^\d]/g, ''); S.saved = null; redraw(true); } });
document.addEventListener('click', function (e) { if (e.target.closest('[data-wsave]')) { var s = x.spool(sid), before = s.rem; s.rem = Math.round(+S.reading - s.tare); s.remSrc = 'weighed'; s.weighedAt = '18 Sep 09:41'; S.saved = [before, s.rem]; S.reading = ''; redraw(); } });
X.init({ name: 'filament', refresh: redraw }, render);
})();
</script>