diff --git a/api/index.php b/api/index.php index 0a1421e..d94610d 100644 --- a/api/index.php +++ b/api/index.php @@ -524,7 +524,7 @@ function getStats(PDO $db): void { // Expired $expired = $db->query(" - SELECT i.*, p.name, p.brand + SELECT i.*, p.name, p.brand, p.category 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 diff --git a/assets/css/style.css b/assets/css/style.css index f60f973..b0b675e 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -310,6 +310,39 @@ body { color: #fff; } +/* Safety badges for expired items */ +.alert-item-badges { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 4px; + flex-shrink: 0; +} + +.safety-badge { + font-size: 0.72rem; + font-weight: 700; + padding: 3px 8px; + border-radius: 12px; + white-space: nowrap; + cursor: help; +} + +.safety-badge.safety-danger { + background: #dc3545; + color: #fff; +} + +.safety-badge.safety-warning { + background: #ffc107; + color: #333; +} + +.safety-badge.safety-ok { + background: #28a745; + color: #fff; +} + /* ===== SECTION CARD ===== */ .section-card { background: var(--bg-card); diff --git a/assets/js/app.js b/assets/js/app.js index 2c5638d..31bd237 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -105,6 +105,52 @@ function guessCategoryFromName(name) { return 'altro'; } +// Determine safety level for expired products +// Returns { level: 'danger'|'warning'|'ok', icon, label, tip } +function getExpiredSafety(item, daysExpired) { + const cat = mapToLocalCategory(item.category || '', item.name || ''); + const loc = (item.location || '').toLowerCase(); + const name = (item.name || '').toLowerCase(); + + // HIGH RISK categories - perishable, can be dangerous + // Latticini freschi, carne, pesce, verdura, frutta + const highRisk = ['latticini', 'carne', 'pesce', 'verdura', 'frutta']; + // MEDIUM RISK - check before consuming + // Pane, surgelati, bevande (fresh juices, milk) + const medRisk = ['pane', 'surgelati']; + + // Items in frigo are more perishable + const inFrigo = loc === 'frigo'; + + if (highRisk.includes(cat)) { + if (daysExpired <= 2 && inFrigo) { + return { level: 'warning', icon: 'π', label: 'Controlla', tip: 'Scaduto da poco, controlla odore e aspetto prima di consumare' }; + } + return { level: 'danger', icon: 'ποΈ', label: 'Buttare', tip: 'Prodotto deperibile scaduto: da buttare per sicurezza' }; + } + + if (medRisk.includes(cat)) { + if (daysExpired <= 7) { + return { level: 'warning', icon: 'π', label: 'Controlla', tip: 'Controlla aspetto e odore prima di consumare' }; + } + if (daysExpired <= 30) { + return { level: 'warning', icon: 'π', label: 'Controlla', tip: 'Scaduto da un po\', verificare bene prima dell\'uso' }; + } + return { level: 'danger', icon: 'ποΈ', label: 'Buttare', tip: 'Troppo tempo dalla scadenza, meglio buttare' }; + } + + // LOW RISK - long shelf life items + // Pasta, conserve, condimenti, cereali, snack, bevande confezionate + // "Da consumarsi preferibilmente entro" = TMC, safe well past expiry + if (daysExpired <= 30) { + return { level: 'ok', icon: 'β ', label: 'OK', tip: 'Prodotto a lunga conservazione, ancora sicuro da consumare' }; + } + if (daysExpired <= 180) { + return { level: 'warning', icon: 'π', label: 'Controlla', tip: 'Scaduto da oltre un mese, controllare integritΓ confezione' }; + } + return { level: 'danger', icon: 'ποΈ', label: 'Buttare', tip: 'Scaduto da troppo tempo, meglio non rischiare' }; +} + // Nice Italian labels for local categories const CATEGORY_LABELS = { 'latticini': 'π₯ Latticini', 'carne': 'π₯© Carne', 'pesce': 'π Pesce', @@ -355,17 +401,21 @@ async function loadDashboard() { expiredSection.style.display = 'block'; expiredList.innerHTML = statsData.expired.map(item => { const days = Math.abs(daysUntilExpiry(item.expiry_date)); - let badgeText; - if (days === 0) badgeText = 'Oggi'; - else if (days === 1) badgeText = 'Da ieri'; - else badgeText = `Da ${days} giorni`; + let daysText; + if (days === 0) daysText = 'Oggi'; + else if (days === 1) daysText = 'Da ieri'; + else daysText = `Da ${days}g`; + const safety = getExpiredSafety(item, days); return ` -