diff --git a/assets/css/style.css b/assets/css/style.css index 60e76f3..850fbea 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -2808,6 +2808,14 @@ body { font-weight: 700; } +.inventory-status-bar .inv-status-item-clickable { + cursor: pointer; + transition: background 0.15s; +} +.inventory-status-bar .inv-status-item-clickable:active { + background: rgba(59, 130, 246, 0.15); +} + /* ===== ACTION BUTTONS GRID ===== */ .action-buttons-3col { display: grid; diff --git a/assets/js/app.js b/assets/js/app.js index 2b4528c..aee7666 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -232,15 +232,14 @@ const CATEGORY_LABELS = { function detectUnitAndQuantity(quantityInfo) { if (!quantityInfo) return { unit: 'pz', quantity: 1, weightInfo: '' }; const q = quantityInfo.toLowerCase().trim(); - // Match multi-pack patterns like "6 x 1l", "4 x 125g" → total weight + // Match multi-pack patterns like "6 x 1l", "4 x 125g" → confezioni const multiMatch = q.match(/(\d+)\s*x\s*([\d.,]+)\s*(ml|l|g|kg|cl)/i); if (multiMatch) { const count = parseInt(multiMatch[1]); let perUnitVal = parseFloat(multiMatch[2].replace(',', '.')); let perUnitUnit = multiMatch[3].toLowerCase(); if (perUnitUnit === 'cl') { perUnitUnit = 'ml'; perUnitVal *= 10; } - const totalVal = count * perUnitVal; - return { unit: perUnitUnit, quantity: totalVal, weightInfo: quantityInfo }; + return { unit: 'conf', quantity: perUnitVal, packageUnit: perUnitUnit, confCount: count, weightInfo: quantityInfo }; } // Match single package patterns like "500 g", "1 l", "750 ml", "1.5 kg" const match = q.match(/([\d.,]+)\s*(kg|g|l|ml|cl)/i); @@ -349,6 +348,7 @@ function guessLocation(product) { // ===== STATE ===== let currentProduct = null; let currentInventory = []; +let _actionInventoryItems = []; let currentLocation = ''; let scannerStream = null; let quaggaRunning = false; @@ -1786,6 +1786,8 @@ async function onBarcodeDetected(barcode) { currentProduct.unit = detected.unit; currentProduct.default_quantity = detected.quantity; currentProduct.weight_info = weightStr; + if (detected.packageUnit) currentProduct.package_unit = detected.packageUnit; + if (detected.confCount) currentProduct._confCount = detected.confCount; // Update product in DB for future scans api('product_save', {}, 'POST', { id: currentProduct.id, @@ -1796,6 +1798,7 @@ async function onBarcodeDetected(barcode) { image_url: currentProduct.image_url || '', unit: detected.unit, default_quantity: detected.quantity, + package_unit: detected.packageUnit || '', notes: currentProduct.notes, }); } @@ -1806,6 +1809,11 @@ async function onBarcodeDetected(barcode) { const pesoMatch = currentProduct.notes.match(/Peso:\s*([^·]+)/); if (pesoMatch) currentProduct.weight_info = pesoMatch[1].trim(); } + // Detect confCount from weight_info for multipack pre-fill + if (currentProduct.weight_info && currentProduct.unit === 'conf' && !currentProduct._confCount) { + const detected = detectUnitAndQuantity(currentProduct.weight_info); + if (detected.confCount) currentProduct._confCount = detected.confCount; + } showLoading(false); stopScanner(); showProductAction(); @@ -1837,6 +1845,7 @@ async function onBarcodeDetected(barcode) { image_url: p.image_url || '', unit: detected.unit, default_quantity: detected.quantity, + package_unit: detected.packageUnit || '', notes: notesParts.join(' · '), }); @@ -1850,6 +1859,8 @@ async function onBarcodeDetected(barcode) { image_url: p.image_url || '', unit: detected.unit, default_quantity: detected.quantity, + package_unit: detected.packageUnit || '', + _confCount: detected.confCount || 0, weight_info: p.quantity_info || '', nutriscore: p.nutriscore || '', ingredients: p.ingredients || '', @@ -2379,6 +2390,7 @@ function showProductAction() { // === CHECK INVENTORY FOR THIS PRODUCT === checkInventoryForProduct(currentProduct.id).then(inventoryItems => { + _actionInventoryItems = inventoryItems; const statusBar = document.getElementById('action-inventory-status'); const btnsContainer = document.getElementById('action-buttons-container'); @@ -2402,7 +2414,7 @@ function showProductAction() { else if (d <= 7) expiryStr = ` · 🟡 Scade tra ${d}g`; else expiryStr = ` · 📅 ${formatDate(inv.expiry_date)}`; } - return `
Tocca una riga per modificare
`; btnsContainer.className = 'action-buttons-4col'; @@ -2505,6 +2518,105 @@ function editProductFromAction() { showPage('product-form'); } +// === EDIT INVENTORY ITEM FROM ACTION PAGE === +function editActionInventoryItem(inventoryId) { + const item = _actionInventoryItems.find(i => i.id === inventoryId); + if (!item) return; + + const isConf = (item.unit || 'pz') === 'conf'; + const confSizeVal = (isConf && item.default_quantity > 0) ? item.default_quantity : ''; + const confUnitVal = (isConf && item.package_unit) ? item.package_unit : 'g'; + + document.getElementById('modal-content').innerHTML = ` +