From 7b60f1dbe385144b7cf9e1846c9c0c3e03510bf6 Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Wed, 20 May 2026 13:35:27 +0000 Subject: [PATCH] fix: 0.5 conf use page (default conf mode + fraction btns); depleted items always in shopping; conf decimals in history log --- api/index.php | 9 ++++++--- assets/js/app.js | 48 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/api/index.php b/api/index.php index f948b8e..3e7a394 100644 --- a/api/index.php +++ b/api/index.php @@ -2395,7 +2395,7 @@ function listTransactions(PDO $db): void { $productId = $_GET['product_id'] ?? ''; $query = " - SELECT t.*, p.name, p.brand, p.unit + SELECT t.*, p.name, p.brand, p.unit, p.default_quantity, p.package_unit FROM transactions t JOIN products p ON t.product_id = p.id "; @@ -7658,8 +7658,11 @@ function smartShopping(PDO $db): void { $reasons[] = 'Esaurito'; $score += 30; } else { - // Rarely used or not used recently — skip - continue; + // Product is depleted. Even without a proven usage pattern, always + // show at minimum 'low' so the user can restock it. + $urgency = 'low'; + $reasons[] = 'Esaurito'; + $score += 15; } } diff --git a/assets/js/app.js b/assets/js/app.js index 74632e0..63697cd 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -8571,9 +8571,27 @@ async function loadUseInventoryInfo() { // Show unit switch unitSwitch.style.display = 'flex'; document.getElementById('use-unit-sub').textContent = subLabel; - - // Default to sub-unit mode - switchUseUnit('sub'); + + // Default to conf mode — users think in packages; scale auto-switches to sub + switchUseUnit('conf'); + + // Fraction shortcut buttons for conf mode (½, 1, 2 packages) + const existingConfFrac = document.getElementById('conf-fraction-btns'); + if (existingConfFrac) existingConfFrac.remove(); + const confFracDiv = document.createElement('div'); + confFracDiv.id = 'conf-fraction-btns'; + confFracDiv.className = 'pz-fraction-btns'; + const maxConf = Math.min(4, Math.ceil(_useConfMode.totalConf)); + const confFracs = [0.25, 0.5, 1]; + if (maxConf >= 2) confFracs.push(2); + confFracDiv.innerHTML = `
${ + confFracs.filter(f => f <= _useConfMode.totalConf + 0.01).map(f => { + const label = f === 0.25 ? '¼' : f === 0.5 ? '½' : f; + return ``; + }).join('') + }
`; + document.querySelector('#page-use .use-partial').appendChild(confFracDiv); + // Trigger a live-box refresh with the latest reading if on scale if (_scaleLatestWeight) _scaleAutoFillUse(_scaleLatestWeight); } else { @@ -8625,6 +8643,10 @@ function switchUseUnit(mode) { const qtyInput = document.getElementById('use-quantity'); const hint = document.getElementById('use-partial-hint'); + // Show/hide fraction buttons depending on mode + const confFracBtns = document.getElementById('conf-fraction-btns'); + const pzFracBtns = document.getElementById('pz-fraction-btns'); + if (mode === 'sub') { subBtn.classList.add('active'); confBtn.classList.remove('active'); @@ -8634,17 +8656,28 @@ function switchUseUnit(mode) { qtyInput.step = 'any'; qtyInput.min = 1; hint.textContent = t('recipes.quantity_in_total', { unit: _useConfMode.subLabel, total: `${Math.round(_useConfMode.totalSub)}${_useConfMode.subLabel}` }); + if (confFracBtns) confFracBtns.style.display = 'none'; } else { confBtn.classList.add('active'); subBtn.classList.remove('active'); _useConfMode._activeUnit = 'conf'; - qtyInput.value = 1; + qtyInput.value = Math.min(1, _useConfMode.totalConf); // start at 1 or max if < 1 qtyInput.step = 'any'; - qtyInput.min = 0.1; + qtyInput.min = 0.25; hint.textContent = t('recipes.packs_of_have', { size: `${_useConfMode.packageSize}${_useConfMode.subLabel}`, count: _useConfMode.totalConf.toFixed(1) }); + if (confFracBtns) confFracBtns.style.display = ''; } } +function setConfFraction(f) { + const input = document.getElementById('use-quantity'); + if (!input) return; + input.value = Math.min(f, _useConfMode?.totalConf ?? f); + document.querySelectorAll('#conf-fraction-btns .frac-btn').forEach(b => + b.classList.toggle('active', parseFloat(b.dataset.frac) === f) + ); +} + function getSubUnitStep(pkgUnit) { switch (pkgUnit) { case 'ml': return 50; @@ -11927,7 +11960,10 @@ async function loadLog(more = false) { html += `${icon}`; html += `
`; html += `
${escapeHtml(tx.name)}${brand}${undone ? ` ${t('log.undone_badge')}` : ''}
`; - html += `
${typeLabel} ${tx.type !== 'bring' ? (tx.quantity + ' ' + (tx.unit || '')) + ' · ' : ''}${locStr}${notes} · ${timeStr}
`; + const txQtyStr = tx.type !== 'bring' + ? formatQuantity(parseFloat(tx.quantity), tx.unit, tx.default_quantity, tx.package_unit) + ' · ' + : ''; + html += `
${typeLabel} ${txQtyStr}${locStr}${notes} · ${timeStr}
`; html += recipeNote; html += `
`; if (canUndo) {