From 4239e0b20497fd9cf151c05d04a7e30d037fbf84 Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Sun, 15 Mar 2026 18:09:38 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=AB=99=20Sotto=20vuoto:=20flag=20per=20es?= =?UTF-8?q?tendere=20scadenza=20prodotti=20conservati=20sotto=20vuoto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/database.php | 7 ++++ api/index.php | 23 ++++++++----- assets/css/style.css | 54 ++++++++++++++++++++++++++++++ assets/js/app.js | 78 +++++++++++++++++++++++++++++++++++++++++-- data/dispensa.db | Bin 167936 -> 167936 bytes index.html | 14 ++++++-- 6 files changed, 163 insertions(+), 13 deletions(-) diff --git a/api/database.php b/api/database.php index 662d136..0c250be 100644 --- a/api/database.php +++ b/api/database.php @@ -140,4 +140,11 @@ function migrateDB(PDO $db): void { ); "); } + + // Add vacuum_sealed column to inventory if missing + $invCols = $db->query("PRAGMA table_info(inventory)")->fetchAll(); + $invColNames = array_column($invCols, 'name'); + if (!in_array('vacuum_sealed', $invColNames)) { + $db->exec("ALTER TABLE inventory ADD COLUMN vacuum_sealed INTEGER DEFAULT 0"); + } } diff --git a/api/index.php b/api/index.php index cf9ff8f..1fcd5db 100644 --- a/api/index.php +++ b/api/index.php @@ -467,7 +467,8 @@ function searchProducts(PDO $db): void { function listInventory(PDO $db): void { $location = $_GET['location'] ?? ''; $query = " - SELECT i.*, p.name, p.brand, p.category, p.image_url, p.unit, p.barcode, p.default_quantity, p.package_unit + SELECT i.*, p.name, p.brand, p.category, p.image_url, p.unit, p.barcode, p.default_quantity, p.package_unit, + COALESCE(i.vacuum_sealed, 0) as vacuum_sealed FROM inventory i JOIN products p ON i.product_id = p.id "; @@ -510,6 +511,8 @@ function addToInventory(PDO $db): void { $stmt->execute([$packageUnit, $packageSize ?: 0, $productId]); } + $vacuumSealed = (int)($input['vacuum_sealed'] ?? 0); + // Check if product already exists in this location $stmt = $db->prepare("SELECT id, quantity FROM inventory WHERE product_id = ? AND location = ?"); $stmt->execute([$productId, $location]); @@ -518,13 +521,13 @@ function addToInventory(PDO $db): void { if ($existing) { // Update quantity $newQty = $existing['quantity'] + $quantity; - $stmt = $db->prepare("UPDATE inventory SET quantity = ?, expiry_date = COALESCE(?, expiry_date), updated_at = CURRENT_TIMESTAMP WHERE id = ?"); - $stmt->execute([$newQty, $expiry, $existing['id']]); + $stmt = $db->prepare("UPDATE inventory SET quantity = ?, expiry_date = COALESCE(?, expiry_date), vacuum_sealed = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?"); + $stmt->execute([$newQty, $expiry, $vacuumSealed, $existing['id']]); } else { $newQty = $quantity; // Insert new inventory entry - $stmt = $db->prepare("INSERT INTO inventory (product_id, location, quantity, expiry_date) VALUES (?, ?, ?, ?)"); - $stmt->execute([$productId, $location, $quantity, $expiry]); + $stmt = $db->prepare("INSERT INTO inventory (product_id, location, quantity, expiry_date, vacuum_sealed) VALUES (?, ?, ?, ?, ?)"); + $stmt->execute([$productId, $location, $quantity, $expiry, $vacuumSealed]); } // Get total across all locations @@ -711,6 +714,7 @@ function updateInventory(PDO $db): void { if (isset($input['quantity'])) { $fields[] = "quantity = ?"; $params[] = $input['quantity']; } if (isset($input['location'])) { $fields[] = "location = ?"; $params[] = $input['location']; } if (isset($input['expiry_date'])) { $fields[] = "expiry_date = ?"; $params[] = $input['expiry_date']; } + if (isset($input['vacuum_sealed'])) { $fields[] = "vacuum_sealed = ?"; $params[] = (int)$input['vacuum_sealed']; } $fields[] = "updated_at = CURRENT_TIMESTAMP"; $params[] = $id; @@ -787,7 +791,8 @@ function getStats(PDO $db): void { // Expiring soonest (next 4 items to expire) $expiring = $db->query(" - SELECT i.*, p.name, p.brand, p.category, p.unit, p.default_quantity, p.package_unit + SELECT i.*, p.name, p.brand, p.category, p.unit, p.default_quantity, p.package_unit, + COALESCE(i.vacuum_sealed, 0) as vacuum_sealed FROM inventory i JOIN products p ON i.product_id = p.id WHERE i.expiry_date IS NOT NULL AND i.expiry_date >= date('now') AND i.quantity > 0 ORDER BY i.expiry_date ASC @@ -796,7 +801,8 @@ function getStats(PDO $db): void { // Expired $expired = $db->query(" - SELECT i.*, p.name, p.brand, p.category, p.unit, p.default_quantity, p.package_unit + SELECT i.*, p.name, p.brand, p.category, p.unit, p.default_quantity, p.package_unit, + COALESCE(i.vacuum_sealed, 0) as vacuum_sealed FROM inventory i JOIN products p ON i.product_id = p.id WHERE i.expiry_date IS NOT NULL AND i.expiry_date < date('now') ORDER BY i.expiry_date ASC @@ -804,7 +810,8 @@ function getStats(PDO $db): void { // Opened (partially used conf items with known package capacity) $opened = $db->query(" - SELECT i.*, p.name, p.brand, p.category, p.unit, p.default_quantity, p.package_unit, p.image_url + SELECT i.*, p.name, p.brand, p.category, p.unit, p.default_quantity, p.package_unit, p.image_url, + COALESCE(i.vacuum_sealed, 0) as vacuum_sealed FROM inventory i JOIN products p ON i.product_id = p.id WHERE p.unit = 'conf' AND p.default_quantity > 0 AND p.package_unit IS NOT NULL AND i.quantity > 0 AND CAST(i.quantity AS REAL) != CAST(CAST(i.quantity AS INTEGER) AS REAL) diff --git a/assets/css/style.css b/assets/css/style.css index 850fbea..e85d8c9 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1998,6 +1998,60 @@ body { margin-top: 4px; } +/* ===== TOGGLE SWITCH ===== */ +.toggle-row { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + -webkit-tap-highlight-color: transparent; +} +.toggle-switch { + position: relative; + display: inline-block; + width: 48px; + height: 28px; + flex-shrink: 0; +} +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} +.toggle-slider { + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + background: #ccc; + border-radius: 28px; + transition: background 0.2s; +} +.toggle-slider::before { + content: ''; + position: absolute; + width: 22px; + height: 22px; + left: 3px; + bottom: 3px; + background: #fff; + border-radius: 50%; + transition: transform 0.2s; +} +.toggle-switch input:checked + .toggle-slider { + background: var(--primary, #3b82f6); +} +.toggle-switch input:checked + .toggle-slider::before { + transform: translateX(20px); +} +.vacuum-badge { + font-size: 0.7rem; + background: rgba(59, 130, 246, 0.12); + color: #2563eb; + padding: 1px 6px; + border-radius: 8px; + font-weight: 600; + white-space: nowrap; +} + /* ===== REMAINING QUANTITY OPTIONS ===== */ .remaining-options { display: grid; diff --git a/assets/js/app.js b/assets/js/app.js index aee7666..ae4513c 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1172,6 +1172,8 @@ function renderInventoryItem(item) { expiryBadge = `${expiryText}`; } + const vacuumBadge = item.vacuum_sealed ? 'πŸ«™ Sotto vuoto' : ''; + return `
@@ -1183,6 +1185,7 @@ function renderInventoryItem(item) {
${locInfo.icon} ${locInfo.label} ${expiryBadge} + ${vacuumBadge}
@@ -1261,6 +1264,11 @@ function showItemDetail(inventoryId, productId) { πŸ“… Scadenza ${formatDate(item.expiry_date)}
` : ''} + ${item.vacuum_sealed ? ` + ` : ''} ${item.barcode ? ` +
+ +
`; @@ -1402,7 +1419,8 @@ async function submitEditInventory(e, id, productId) { const expiry = document.getElementById('edit-expiry').value || null; const unit = document.getElementById('edit-unit').value; - const payload = { id, quantity: qty, location: loc, expiry_date: expiry, unit, product_id: productId }; + const payload = { id, quantity: qty, location: loc, expiry_date: expiry, unit, product_id: productId, + vacuum_sealed: document.getElementById('edit-vacuum')?.checked ? 1 : 0 }; // Add package info if conf if (unit === 'conf') { @@ -2414,7 +2432,8 @@ function showProductAction() { else if (d <= 7) expiryStr = ` Β· 🟑 Scade tra ${d}g`; else expiryStr = ` Β· πŸ“… ${formatDate(inv.expiry_date)}`; } - return `
${locInfo.icon} ${locInfo.label}${expiryStr}${qtyStr}${pkgF ? ' ' + pkgF : ''} ✏️
`; + const vacuumIcon = inv.vacuum_sealed ? ' πŸ«™' : ''; + return `
${locInfo.icon} ${locInfo.label}${vacuumIcon}${expiryStr}${qtyStr}${pkgF ? ' ' + pkgF : ''} ✏️
`; }).join(''); const totalStr = formatQuantity(totalQty, unit, defQty, pkgUnit); @@ -2570,6 +2589,15 @@ function editActionInventoryItem(inventoryId) {
+
+ +
+
+ + +
@@ -884,6 +894,6 @@ - +