feat: AI suggestions, smart shopping qty, shelf life fixes, UX polish

- bringSuggestItems(): Gemini AI for seasonal/complementary suggestions (6h cache)
- renderSuggestions(): AI badge (🤖 AI) for AI-sourced items + CSS .priority-ai
- smartShopping(): suggested_qty/unit/approx with package-aware tiers
- autoSyncUrgencySpecs(): sync suggested quantities to Bring! spec field
- estimateOpenedExpiryDays(): dairy-outside-fridge rules (panna 3d, yogurt 2d, latte 1d)
- AI shelf-life upper bound tightened to max(rule×4, 30) days
- Opened section: fix 0g display (remainderAmt >= 0.5 threshold, pkgSize guard)
- guessCategoryFromName(): expanded with 50+ new patterns (uova, herbs, vegetables...)
- Suggestions panel: excludes already-added Bring! items
- Shopping list: no re-render while suggestions panel is open
- Translations: remove duplicate 🍳 from dashboard.quick_recipe (all 3 langs)
- Scale icon: always white via filter:brightness(0)invert(1)
- opened_shelf_cache.json: remove 3 bad dairy entries (60d outside fridge)
This commit is contained in:
dadaloop82
2026-05-07 06:19:07 +00:00
parent ffb0341eb6
commit 4196130835
8 changed files with 581 additions and 145 deletions
+10 -3
View File
@@ -84,7 +84,7 @@
"opened_title": "📦 Geöffnete Produkte",
"review_title": "🔍 Zu prüfen",
"review_hint": "Mengen, die ungewöhnlich erscheinen. Bestätigen oder ändern.",
"quick_recipe": "🍳 Schnelles Rezept mit ablaufenden Produkten",
"quick_recipe": "Schnelles Rezept mit ablaufenden Produkten",
"banner_review_title": "Ungewöhnliche Menge",
"banner_review_action_ok": "Ist korrekt",
"banner_review_action_finish": "🗑️ Alles aufgebraucht",
@@ -103,8 +103,11 @@
"banner_expired_action_throw": "Habe ich weggeworfen",
"banner_expired_action_edit": "Datum korrigieren",
"banner_anomaly_action_edit": "Bestand korrigieren",
"banner_anomaly_action_dismiss": "Menge ist korrekt",
"banner_expiring_title": "Bald ablaufend",
"banner_anomaly_action_dismiss": "Menge ist korrekt", "banner_no_expiry_title": "Ablaufdatum fehlt: {name}",
"banner_no_expiry_detail": "Dieses Produkt hat kein Ablaufdatum. Möchten Sie eines hinzufügen oder bestätigen, dass es nicht verfällt?",
"banner_no_expiry_action_set": "Ablaufdatum setzen",
"banner_no_expiry_action_dismiss": "Läuft nicht ab ✓",
"banner_no_expiry_toast_dismissed": "Als 'läuft nicht ab' markiert", "banner_expiring_title": "Bald ablaufend",
"banner_expiring_today": "Läuft heute ab!",
"banner_expiring_tomorrow": "Läuft morgen ab",
"banner_expiring_days": "Läuft in {days} Tagen ab",
@@ -357,6 +360,10 @@
"smart_already": "📊 Intelligenter Einkauf sagt bereits {name} voraus",
"all_searched": "Alle Produkte wurden bereits gesucht. Nutze 🔄 für einzelne Suchen.",
"search_complete": "Suche abgeschlossen: {count} Produkte",
"suggest_buy": "🛒 Kaufen: {qty} {unit}",
"suggest_buy_approx": "🛒 Mindestens: {qty} {unit}",
"suggest_buy_tip": "Empfohlene Menge basierend auf dem Verbrauch der letzten 14 Tage",
"suggest_buy_approx_tip": "Mindestschätzung basierend auf Verbrauch (nächste Packungsgröße kaufen)",
"removed_sufficient": "🧹 {removed} Produkt(e) mit ausreichendem Bestand von der Liste entfernt",
"bring_badge": "🛒 Schon auf Bring!",
"add_urgent_toast": "🔴 {n} dringende(s) Produkt(e) automatisch zu Bring! hinzugefügt",
+10 -1
View File
@@ -84,7 +84,7 @@
"opened_title": "📦 Opened Products",
"review_title": "🔍 To Review",
"review_hint": "Quantities that seem unusual. Confirm if correct or modify.",
"quick_recipe": "🍳 Quick recipe with expiring products",
"quick_recipe": "Quick recipe with expiring products",
"banner_review_title": "Anomalous quantity",
"banner_review_action_ok": "It's correct",
"banner_review_action_finish": "🗑️ All gone",
@@ -104,6 +104,11 @@
"banner_expired_action_edit": "Fix date",
"banner_anomaly_action_edit": "Fix inventory",
"banner_anomaly_action_dismiss": "Quantity is correct",
"banner_no_expiry_title": "Missing expiry: {name}",
"banner_no_expiry_detail": "This product has no expiry date. Would you like to add one, or confirm it doesn't expire?",
"banner_no_expiry_action_set": "Set expiry date",
"banner_no_expiry_action_dismiss": "Doesn't expire ✓",
"banner_no_expiry_toast_dismissed": "Marked as 'no expiry'",
"banner_expiring_title": "Expiring soon",
"banner_expiring_today": "Expires today!",
"banner_expiring_tomorrow": "Expires tomorrow",
@@ -357,6 +362,10 @@
"all_searched": "All products have already been searched. Use 🔄 to search individual ones.",
"search_complete": "Search complete: {count} products",
"removed_sufficient": "🧹 {removed} product(s) with sufficient stock removed from the list",
"suggest_buy": "🛒 Buy: {qty} {unit}",
"suggest_buy_approx": "🛒 At least: {qty} {unit}",
"suggest_buy_tip": "Suggested quantity based on your last 14 days of consumption",
"suggest_buy_approx_tip": "Minimum estimate based on consumption (buy the nearest package size)",
"bring_badge": "🛒 Already on Bring!",
"add_urgent_toast": "🔴 {n} urgent product(s) automatically added to Bring!",
"migration_done": "✅ {migrated} updated, {skipped} already ok",
+10 -1
View File
@@ -84,7 +84,7 @@
"opened_title": "📦 Prodotti Aperti",
"review_title": "🔍 Da revisionare",
"review_hint": "Quantità che sembrano anomale. Conferma se corrette o modifica.",
"quick_recipe": "🍳 Ricetta veloce con prodotti in scadenza",
"quick_recipe": "Ricetta veloce con prodotti in scadenza",
"banner_review_title": "Quantità anomala",
"banner_review_action_ok": "È corretto",
"banner_review_action_finish": "🗑️ È finito tutto",
@@ -104,6 +104,11 @@
"banner_expired_action_edit": "Correggi data",
"banner_anomaly_action_edit": "Correggi inventario",
"banner_anomaly_action_dismiss": "La quantità è giusta",
"banner_no_expiry_title": "Scadenza mancante: {name}",
"banner_no_expiry_detail": "Questo prodotto non ha una data di scadenza. Vuoi aggiungerla o confermare che non scade?",
"banner_no_expiry_action_set": "Imposta scadenza",
"banner_no_expiry_action_dismiss": "Non scade ✓",
"banner_no_expiry_toast_dismissed": "Segnato come 'non scade'",
"banner_expiring_title": "In scadenza",
"banner_expiring_today": "Scade oggi!",
"banner_expiring_tomorrow": "Scade domani",
@@ -357,6 +362,10 @@
"all_searched": "Tutti i prodotti sono già stati cercati. Usa 🔄 per ricercare singoli.",
"search_complete": "Ricerca completata: {count} prodotti",
"removed_sufficient": "🧹 {removed} prodotto/i con scorte sufficienti rimosso/i dalla lista",
"suggest_buy": "🛒 Compra: {qty} {unit}",
"suggest_buy_approx": "🛒 Almeno: {qty} {unit}",
"suggest_buy_tip": "Quantità suggerita in base al consumo degli ultimi 14 giorni",
"suggest_buy_approx_tip": "Stima minima basata sul consumo (compra la confezione più vicina)",
"bring_badge": "🛒 Già su Bring!",
"add_urgent_toast": "🔴 {n} prodotto/i urgente/i aggiunto/i automaticamente a Bring!",
"migration_done": "✅ {migrated} aggiornati, {skipped} già ok",