Commit Graph

108 Commits

Author SHA1 Message Date
dadaloop82 4196130835 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)
2026-05-07 06:19:07 +00:00
dadaloop82 e71ef3aba3 Dashboard: move waste-chart above expiring; fix opened-items conf split, expiry cache, AI validation, MAX_SHOWN 20; remove DupliClick from README 2026-04-29 17:02:10 +00:00
dadaloop82 8722f15aa0 i18n: Translate all hardcoded Italian labels to English & German
- Convert LOCATIONS labels to use t('locations.*')
- Convert SHOPPING_SECTIONS labels to use t('shopping_sections.*')
- Convert CATEGORY_LABELS to use t('categories.*')
- Convert MEAL_PLAN_TYPES to use t('meal_plan_types.*')
- Convert WEEK_DAYS_SHORT to use t('days.*_short')
- Convert MEAL_TYPES to use t('meal_types.*')
- Convert MEAL_SUB_TYPES to use t('meal_sub.*')
- Convert meal-plan column headers to use translated meal_types
- Replace inline locLabels/LOC_LABELS with translated LOCATIONS object
- Fix shopping action buttons: bring_add_n, bring_add_selected, bring_adding, bring_added_*
- Fix recipe archive empty state
- Fix meal plan reset success toast
- Fix meal plan suggestion hint and screensaver display
- Fix settings save status messages (saved, saved_local, saved_local_error)
- Fix product edit form title
- Fix kiosk session phrases for screensaver counter
- Add cooking.expires_chip translation for expiry date format
- Add meal_plan section (reset_success, suggested_by)
- Add error.select_items for Bring shopping validation
- All strings now properly internationalized for EN/DE languages
2026-04-28 16:03:07 +00:00
dadaloop82 d1478245da fix: add 24 missing shopping_name aliases to Bring! catalog (100% coverage)
All shopping_name values now resolve to a German Bring! catalog key:
  aroma / ingredienti spezie -> Zutaten & Gewürze
  bevande / liquore          -> Getränke & Tabak
  camomilla                  -> Tee
  cioccolata calda           -> Kakao
  cipolla                    -> Zwiebeln
  cracker / taralli / snack  -> Snacks & Süsswaren
  farina integrale           -> Mehl
  fette biscottate           -> Toast
  filetto                    -> Fleisch
  muesli                     -> Corn Flakes
  panna da cucina            -> Rahm
  passata / polpa pomodoro   -> Pelati
  piatti pronti/purè/sfornat -> Fertig- & Tiefkühlprodukte
  salsa                      -> Zutaten & Gewürze
  succo                      -> Fruchtsaft
  vino                       -> Rotwein
  zucchero di canna          -> Zucker
2026-04-27 17:37:01 +00:00
dadaloop82 1a73ed91dd fix: compound shopping names + auto-Bring on depletion + panna da cucina
1. shopping_name compound-phrase map (computeShoppingName)
   Add phraseMap checked against the full product name BEFORE the single-token
   keyword loop.  Prevents 'pane grattugiato' → 'Pane', 'panna da cucina' → 'Panna', etc.
   Key new phrases:
   - pane/pan grattugiato → Pangrattato
   - panna da cucina / panna cucina / panna chef → Panna da cucina
   - fette biscottate → Fette biscottate
   - aceto balsamico / glassa balsamico → Aceto balsamico
   - latte condensato/evaporato/vegetale/di soia/mandorla/avena/riso/cocco → specific
   - prosciutto cotto → Prosciutto cotto
   - farina di riso/mais/integrale → specific
   - pasta fresca, zucchero di canna, acqua minerale/frizzante/gassata, brodo, …
   Also added single-token safety-net entries: 'grattugiato'/'grattato'/'pangrattato'
   → 'Pangrattato', 'biscottate' → 'Fette biscottate'.

2. DB migration (sqlite3 UPDATE)
   Re-classified 10 products that had wrong shopping_name:
   Pane grattugiato → Pangrattato
   Panna da cucina (×4) → Panna da cucina
   Fette biscottate (×2) → Fette biscottate
   Aceto balsamico (×3) → Aceto balsamico
   Cleared 2 stale Gemini cache entries.

3. showLowStockBringPrompt (app.js)
   When totalRemaining <= 0 (product fully depleted), skip the modal entirely.
   The backend already auto-adds to Bring! on depletion; the JS only asks as a
   fallback if that failed (fire-and-forget async, never blocks the UI).
   The afterCallback (e.g. move-remainder modal, navigate to dashboard) is called
   immediately without user interaction.
2026-04-27 12:04:48 +00:00
dadaloop82 8b5985dc80 feat: improve computeShoppingName — expanded keyword map + Gemini AI fallback
- Extended keyword map: 100+ entries covering bread (bauletto->Pane),
  cheese (bel->Formaggio, casatella->Formaggio), wine (vesoletto/trebbiano->Vino),
  foreign brand names (kaffee->Caffe, risofrolle->Cracker, zuppalatte->Biscotti,
  inchusa->Birra, apfelsaft->Succo, kartoffelpüree->Purè, ciobar->Cioccolata calda,
  ovomaltine->Bevande), desserts (gelato->Gelato), herbs (camomilla->Camomilla),
  liquors (sambuca->Liquore), sugar variants (zuccheri->Zucchero), foreign words
  (jus/zumo/arome->Italian equivalents)
- Add _geminiClassifyProduct(): calls Gemini 2.0 Flash for ambiguous product names,
  with persistent cache in data/shopping_name_cache.json (never re-queries same product)
- computeShoppingName() now calls Gemini when keyword map and Bring! catalog both fail
  and the product name is multi-token or has a brand/category hint
- saveProduct() auto-computes shopping_name on every create/update (already in prev commit)
- DB migration: all 210 products re-classified with new rules
- shopping list: 38->33 groups (Formaggio +4v, Affettato +5v, Biscotti +1v, Pane +1v...)
- Final SQL fixes for edge cases: Gelato, Camomilla, brand name single tokens
2026-04-27 11:40:14 +00:00
dadaloop82 36f6fcd232 fix: reduce finished-banner to only products with unexpected zero balance
Of the 75 qty=0 rows restored in previous commit, delete the 66 where
total_in - total_out <= unit threshold (legitimately finished by user).
Keep only 9 products where transaction math says there should still be
stock but inventory hit 0 (likely system/scale error):
- Latte di Montagna (0.41 conf)
- Passata di pomodoro (692g)
- Carote (80g), mele (6pz), Uova biologiche (1pz)
- Cipolla dorata (496pz), Panna da cucina (0.6 conf)
- Gran bauletto integrale e noci (448 conf), il tuo muesli mountain (331g)

These 9 will appear in the banner asking user to verify.
2026-04-27 05:43:59 +00:00
dadaloop82 e0956c6043 Prepare for public distribution v1.0.0
- Remove all personal data from source code (HA IP, JWT tokens)
- Move secrets to .env configuration (gitignored)
- Create .env.example template for new installations
- Add centralized env() helper, eliminate code duplication (~120 lines removed)
- Add input validation on inventory operations (quantity bounds, location whitelist)
- Remove sensitive credential exposure in API responses
- Remove database and runtime files from Git tracking
- Disable database push-to-GitHub backup (local-only backup now)
- Update .gitignore for distribution
- Add comprehensive README with installation guide
- Add CHANGELOG.md for version tracking
- Add MIT LICENSE
- Add author/license headers to all source files
- TTS defaults now empty (configured per-installation via .env)
2026-04-10 05:24:27 +00:00
dadaloop82 35cf133be4 Pre-distribution snapshot: current working state 2026-04-10 05:16:17 +00:00
dadaloop82 655ec63aaf 📦 Backup database automatico - 2026-04-10 03:00 2026-04-10 03:00:01 +00:00
dadaloop82 978c298cc3 📦 Backup database automatico - 2026-04-09 03:00 2026-04-09 03:00:01 +00:00
dadaloop82 e8649a87fc 📦 Backup database automatico - 2026-04-08 03:00 2026-04-08 03:00:01 +00:00
dadaloop82 dc36ce2ae4 fix: MODIFICA button now edits inventory instance (expiry/location/qty/vacuum)
The MODIFICA button on the action page was opening the catalog editor
(name/brand/category). Users expect it to edit the physical item in hand.

Changes:
- MODIFICA button → openInventoryEdit(): edits the inventory row directly.
  If product is in one location → opens editActionInventoryItem directly.
  If multiple locations → shows a location picker modal first.
- editActionInventoryItem modal already has: qty ±, unit, conf size, location
  buttons, expiry date, vacuum toggle — all fields for the instance.
- Catalog editing (name/brand/category) moved to a small secondary link
  '⚙️ Modifica scheda prodotto' shown discreetly below the action buttons.
- Removed redundant 'Tocca una riga per modificare' hint from status bar.
- Added .btn-link-small CSS class for the secondary catalog-edit link.
2026-04-07 12:52:31 +00:00
dadaloop82 4e576559a9 feat: barcode scan button + reminder in manual product form
- Add 📷 scan button next to the barcode field in product form
  Opens a camera modal (BarcodeDetector if available, manual fallback)
  Detects barcode after 2 consistent frames, fills field and closes modal
- Show ⚠️ hint below the barcode field when it's empty (new products only):
  'Aggiungi il barcode così al prossimo acquisto basta scansionarlo!'
  Hint hides automatically when a code is entered or scanned
- Hint is hidden in edit-product mode (barcode already saved)
- scanBarcodeForForm() reuses the modal overlay; handles camera permission
  errors gracefully (shows manual input only)
2026-04-07 12:17:18 +00:00
dadaloop82 b7ed9899fa feat+fix: Bring removal, multi-expiry batches, FIFO in cooking steps
BRING! REMOVAL FIX (latte/aglio not removed after shopping):
- PHP addToInventory: replace exact strcasecmp with token-based fuzzy
  matching (same logic as _productOnBring) so custom Bring item names
  and translated catalog keys both match correctly
- JS submitAdd: add client-side fallback — if PHP removal missed the item,
  use _findSimilarItem against the loaded shoppingItems and call bring_remove

MULTI-EXPIRY BATCHES (when buying conf with different expiry dates):
- Add form (unit=conf): shows '+ Lotto con scadenza diversa' button
- Each extra batch has its own qty + expiry date input with +/- controls
- On submitAdd, extra batches are submitted as additional inventory_add calls
  (separate DB rows, separate expiry dates)
- Multi-batch section hidden in 'Ce l'avevo già' mode and for non-conf units
- Re-shown/hidden when switching unit via onAddUnitChange

RECIPE COOKING STEPS - FIFO ingredient display:
- renderCookingStep: each ingredient row now shows brand chip, location chip,
  and expiry date chip (color-coded: red ≤3d, yellow ≤7d)
- PHP already selected earliest-expiry inventory entry (ORDER BY days_left ASC
  with > not >= ensures first/earliest match wins)
- CSS: .cooking-ing-meta, .cooking-ing-chip, .exp-soon, .exp-close,
  .multi-batch-row, .multi-batch-qty, .multi-batch-date, .btn-icon-sm
2026-04-07 12:10:14 +00:00
dadaloop82 22ae3abf47 📦 Backup database automatico - 2026-04-07 03:00 2026-04-07 03:00:01 +00:00
dadaloop82 568cc1e6fa fix: don't re-add items to Bring after user removes them (purchased blocklist, 4h TTL) 2026-04-06 08:53:14 +00:00
dadaloop82 854bc37709 📦 Backup database automatico - 2026-04-06 03:00 2026-04-06 03:00:01 +00:00
dadaloop82 fedb7c50e2 📦 Backup database automatico - 2026-04-05 03:00 2026-04-05 03:00:02 +00:00
dadaloop82 57677fa0d0 fix: keep previous settings (meal, persons, options) on regenerate 2026-04-04 15:35:07 +00:00
dadaloop82 e233dcef6d fix: remove duplicate const meal declaration in regenerateRecipe 2026-04-04 15:31:31 +00:00
dadaloop82 da5552e992 fix: hide meal-plan banner on chip uncheck; fix recipe variety (variation counter, temp scaling, client-side title tracking) 2026-04-04 15:29:07 +00:00
dadaloop82 bd6f92f2f3 fix: route TTS through PHP proxy to bypass mixed-content/CORS 2026-04-04 14:44:11 +00:00
dadaloop82 475d482184 feat: TTS generic API builder, remove HA refs, pre-fill credentials 2026-04-04 14:40:48 +00:00
dadaloop82 7bc1c87d5c feat: TTS via Home Assistant API, settings panel, remove browser speechSynthesis 2026-04-04 14:37:00 +00:00
dadaloop82 63db7cc114 feat: bring urgency sync, background auto-sync, recipe mealplan chip, screensaver fix 2026-04-04 14:32:25 +00:00
dadaloop82 6e3e451a39 📦 Backup database automatico - 2026-04-04 03:00 2026-04-04 03:00:01 +00:00
dadaloop82 3bbf093857 📦 Backup database automatico - 2026-04-03 03:00 2026-04-03 03:00:01 +00:00
dadaloop82 20e7d2cbfc 📦 Backup database automatico - 2026-04-02 03:00 2026-04-02 03:00:01 +00:00
dadaloop82 200ec145d9 📦 Backup database automatico - 2026-04-01 03:00 2026-04-01 03:00:01 +00:00
dadaloop82 2be6643104 📦 Backup database automatico - 2026-03-31 03:00 2026-03-31 03:00:01 +00:00
dadaloop82 bcddba46d4 Remove kg/l units everywhere — only g (grammi) and ml (millilitri)
- HTML: removed kg/l options from all unit selector dropdowns
- JS detectUnitAndQuantity(): auto-converts kg→g (*1000) and l→ml (*1000)
- JS unit labels: removed all kg/l entries from unitLabels maps
- JS category defaults: frutta 1000g, verdura 500g, bevande 1000ml
- JS step/min logic: simplified for g/ml only (no more 0.01 steps)
- JS getSubUnitStep(): removed kg/l cases
- JS isLowStock(): removed kg/l threshold
- JS spec parser: labels now show g/ml instead of kg/L
- PHP recipe parser: converts kg→g and l→ml immediately on parse
- PHP AI prompt: updated to specify only g/ml/pz/conf units
- PHP migration endpoint available at ?action=migrate_units (no-op if DB already clean)
2026-03-30 14:13:11 +00:00
dadaloop82 c4938457ac Fix min quantity for kg/l units in use forms
- Normal mode (non-conf) now sets min=0.01 for kg/l, min=1 for g/ml
- +/- buttons use unit-aware steps: 0.01 for small kg/l values, 0.1 for
  values <1, 0.5 for values >=1 (instead of fixed 0.5)
- Same fix applied to recipe use form
- Allows inputting e.g. 0.07kg (70g) when product is tracked in kg
2026-03-30 13:45:02 +00:00
dadaloop82 c63faf56e4 Conservative Bring! cleanup + operations log
- cleanupObsoleteBringItems() now much more conservative:
  * Only removes items matching a known DB product (preserves manual additions)
  * Only removes if the product has current_qty > 0 (has stock)
  * AND item is no longer flagged by smart shopping
- Added logOperation() — stores all Bring! operations in localStorage '_opLog'
  (bring_auto_add, bring_cleanup, bring_found, bring_manual_remove)
  Capped at 200 entries, each with timestamp + action + details
- All Bring! add/remove paths now log their operations
2026-03-30 13:36:51 +00:00
dadaloop82 b954be4cac Fix smart shopping: skip one-time purchases, better frequency for short history
- Products bought only once (buy_count=1) and out of stock are skipped entirely
  (not enough history to predict repurchase need, e.g. piadelle)
- usesPerMonth for items tracked 7-30 days now normalized instead of using raw count
- usesPerMonth for items tracked <7 days halved to avoid inflation
- Critical urgency now requires buy_count >= 2
2026-03-29 19:58:43 +00:00
dadaloop82 4b3e5f2ce4 Cleanup obsolete Bring! items after smart shopping algorithm fix
- cleanupObsoleteBringItems(): one-time per session, removes items from Bring!
  that the updated smart shopping algorithm no longer considers relevant
- Cross-references shoppingItems vs smartShoppingItems using exact + token match
- Shows toast with count of removed items
- Called alongside autoAddCriticalItems after loading smart shopping data
2026-03-29 19:54:05 +00:00
dadaloop82 7be6ae8cd7 feat: timer integrato nella modalita cucina
- Rileva automaticamente durate nel testo dello step (minuti, ore, secondi,
  mezz'ora, un quarto d'ora, qualche minuto, un paio di minuti, ecc.)
- Mostra countdown grande con Avvia/Pausa/Reset
- Ultimi 30 secondi in arancione, scaduto in rosso pulsante
- Allo scadere: vibrazione + TTS 'Tempo scaduto!'
- Timer continua a contare in overtime (+00:XX) dopo lo zero
- Timer si resetta automaticamente cambiando step o chiudendo
2026-03-29 16:09:12 +00:00
dadaloop82 917aa56001 feat: sezioni reparto lista spesa, gradient urgenza, modalità cucina con TTS
- renderShoppingItems: raggruppamento per reparto (sezioni), ordinamento
  per urgenza+frequenza, sfondo con gradiente colore urgenza
- renderSmartShopping: stesso raggruppamento per reparto in tab previsione
- Modalità Cucina: overlay fullscreen nero, step per step con navigazione,
  TTS italiano via Web Speech API, pulsante 'Usa' ingredienti per step
- CSS: modal z-index 600 in cooking-mode-active per sovrapposizione corretta
2026-03-29 15:30:55 +00:00
dadaloop82 a38a5d670f feat: lista spesa con tab Da comprare/In previsione, tag, frequenza, tap-to-scan
- Counter nei tab aggiornati dinamicamente
- Auto-aggiunta prodotti CRITICI a Bring! al caricamento (1x per sessione)
- Badge urgenza e frequenza sugli item in lista (cross-ref smart shopping)
- Tag locali per item (Urgente/Priorità/Verificare) con menu dropdown
- Ordinamento automatico per frequenza utilizzo (item più usati in cima)
- Tap su un item → scanner barcode, con banner 'Trovato! Rimuovi dalla lista'
- Fix pctLeft: usa max(1, qty) come fallback refQty per evitare falsi alert
- Fix daysLeft capped a 365gg per pulire stringhe di previsione
- Back button on action page → torna a shopping se aperto da lista
2026-03-29 14:12:37 +00:00
dadaloop82 5b11ab6493 📦 Backup database automatico - 2026-03-28 03:00 2026-03-28 03:00:01 +00:00
dadaloop82 dac1465c45 📦 Backup database automatico - 2026-03-27 03:00 2026-03-27 03:00:01 +00:00
dadaloop82 21e93a5546 📦 Backup database automatico - 2026-03-26 03:00 2026-03-26 03:00:01 +00:00
dadaloop82 df391df150 📦 Backup database automatico - 2026-03-25 03:00 2026-03-25 03:00:01 +00:00
dadaloop82 0835bc8b84 📦 Backup database automatico - 2026-03-21 03:00 2026-03-21 03:00:01 +00:00
dadaloop82 3037d64664 📦 Backup database automatico - 2026-03-20 03:00 2026-03-20 03:00:01 +00:00
dadaloop82 11a703d274 20260319a: Auto-refresh recipe archive after save, Bring spec uses product name not brand 2026-03-19 13:18:35 +00:00
dadaloop82 b8528f79a9 📦 Backup database automatico - 2026-03-19 03:00 2026-03-19 03:00:01 +00:00
dadaloop82 dae4c4d435 20260318b: Fix countdown bar color - was using non-existent CSS variable 2026-03-18 06:33:04 +00:00
dadaloop82 4536decfaf 20260318a: Bump cache busters 2026-03-18 06:16:11 +00:00
dadaloop82 3e284da7ad 📦 Backup database automatico - 2026-03-18 03:00 2026-03-18 03:00:01 +00:00