fix: 0.5 conf use page (default conf mode + fraction btns); depleted items always in shopping; conf decimals in history log
This commit is contained in:
+6
-3
@@ -2395,7 +2395,7 @@ function listTransactions(PDO $db): void {
|
|||||||
$productId = $_GET['product_id'] ?? '';
|
$productId = $_GET['product_id'] ?? '';
|
||||||
|
|
||||||
$query = "
|
$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
|
FROM transactions t
|
||||||
JOIN products p ON t.product_id = p.id
|
JOIN products p ON t.product_id = p.id
|
||||||
";
|
";
|
||||||
@@ -7658,8 +7658,11 @@ function smartShopping(PDO $db): void {
|
|||||||
$reasons[] = 'Esaurito';
|
$reasons[] = 'Esaurito';
|
||||||
$score += 30;
|
$score += 30;
|
||||||
} else {
|
} else {
|
||||||
// Rarely used or not used recently — skip
|
// Product is depleted. Even without a proven usage pattern, always
|
||||||
continue;
|
// show at minimum 'low' so the user can restock it.
|
||||||
|
$urgency = 'low';
|
||||||
|
$reasons[] = 'Esaurito';
|
||||||
|
$score += 15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
-6
@@ -8571,9 +8571,27 @@ async function loadUseInventoryInfo() {
|
|||||||
// Show unit switch
|
// Show unit switch
|
||||||
unitSwitch.style.display = 'flex';
|
unitSwitch.style.display = 'flex';
|
||||||
document.getElementById('use-unit-sub').textContent = subLabel;
|
document.getElementById('use-unit-sub').textContent = subLabel;
|
||||||
|
|
||||||
// Default to sub-unit mode
|
// Default to conf mode — users think in packages; scale auto-switches to sub
|
||||||
switchUseUnit('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 = `<div class="fraction-btn-row">${
|
||||||
|
confFracs.filter(f => f <= _useConfMode.totalConf + 0.01).map(f => {
|
||||||
|
const label = f === 0.25 ? '¼' : f === 0.5 ? '½' : f;
|
||||||
|
return `<button type="button" class="frac-btn${f === 1 ? ' active' : ''}" data-frac="${f}" onclick="setConfFraction(${f})">${label} ${t('units.conf') || 'conf'}</button>`;
|
||||||
|
}).join('')
|
||||||
|
}</div>`;
|
||||||
|
document.querySelector('#page-use .use-partial').appendChild(confFracDiv);
|
||||||
|
|
||||||
// Trigger a live-box refresh with the latest reading if on scale
|
// Trigger a live-box refresh with the latest reading if on scale
|
||||||
if (_scaleLatestWeight) _scaleAutoFillUse(_scaleLatestWeight);
|
if (_scaleLatestWeight) _scaleAutoFillUse(_scaleLatestWeight);
|
||||||
} else {
|
} else {
|
||||||
@@ -8625,6 +8643,10 @@ function switchUseUnit(mode) {
|
|||||||
const qtyInput = document.getElementById('use-quantity');
|
const qtyInput = document.getElementById('use-quantity');
|
||||||
const hint = document.getElementById('use-partial-hint');
|
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') {
|
if (mode === 'sub') {
|
||||||
subBtn.classList.add('active');
|
subBtn.classList.add('active');
|
||||||
confBtn.classList.remove('active');
|
confBtn.classList.remove('active');
|
||||||
@@ -8634,17 +8656,28 @@ function switchUseUnit(mode) {
|
|||||||
qtyInput.step = 'any';
|
qtyInput.step = 'any';
|
||||||
qtyInput.min = 1;
|
qtyInput.min = 1;
|
||||||
hint.textContent = t('recipes.quantity_in_total', { unit: _useConfMode.subLabel, total: `${Math.round(_useConfMode.totalSub)}${_useConfMode.subLabel}` });
|
hint.textContent = t('recipes.quantity_in_total', { unit: _useConfMode.subLabel, total: `${Math.round(_useConfMode.totalSub)}${_useConfMode.subLabel}` });
|
||||||
|
if (confFracBtns) confFracBtns.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
confBtn.classList.add('active');
|
confBtn.classList.add('active');
|
||||||
subBtn.classList.remove('active');
|
subBtn.classList.remove('active');
|
||||||
_useConfMode._activeUnit = 'conf';
|
_useConfMode._activeUnit = 'conf';
|
||||||
qtyInput.value = 1;
|
qtyInput.value = Math.min(1, _useConfMode.totalConf); // start at 1 or max if < 1
|
||||||
qtyInput.step = 'any';
|
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) });
|
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) {
|
function getSubUnitStep(pkgUnit) {
|
||||||
switch (pkgUnit) {
|
switch (pkgUnit) {
|
||||||
case 'ml': return 50;
|
case 'ml': return 50;
|
||||||
@@ -11927,7 +11960,10 @@ async function loadLog(more = false) {
|
|||||||
html += `<span class="log-icon">${icon}</span>`;
|
html += `<span class="log-icon">${icon}</span>`;
|
||||||
html += `<div class="log-info">`;
|
html += `<div class="log-info">`;
|
||||||
html += `<div class="log-product"><strong>${escapeHtml(tx.name)}</strong>${brand}${undone ? ` <span class="log-undone-badge">${t('log.undone_badge')}</span>` : ''}</div>`;
|
html += `<div class="log-product"><strong>${escapeHtml(tx.name)}</strong>${brand}${undone ? ` <span class="log-undone-badge">${t('log.undone_badge')}</span>` : ''}</div>`;
|
||||||
html += `<div class="log-detail">${typeLabel} ${tx.type !== 'bring' ? (tx.quantity + ' ' + (tx.unit || '')) + ' · ' : ''}${locStr}${notes} · ${timeStr}</div>`;
|
const txQtyStr = tx.type !== 'bring'
|
||||||
|
? formatQuantity(parseFloat(tx.quantity), tx.unit, tx.default_quantity, tx.package_unit) + ' · '
|
||||||
|
: '';
|
||||||
|
html += `<div class="log-detail">${typeLabel} ${txQtyStr}${locStr}${notes} · ${timeStr}</div>`;
|
||||||
html += recipeNote;
|
html += recipeNote;
|
||||||
html += `</div>`;
|
html += `</div>`;
|
||||||
if (canUndo) {
|
if (canUndo) {
|
||||||
|
|||||||
Reference in New Issue
Block a user