fix: comprehensive shopping name audit + README update
Shopping name system hardening (api/index.php): - phraseMap: added sugar subtypes (zucchero a velo), passato di verdure/patate → Verdure, aroma phrases → Ingredienti Spezie, farina 00 → Farina, explicit brodo subtypes; added ordering comment on 'farina integrale' - keywordMap: added 'lievito' → Lievito, 'aroma' → Ingredienti Spezie single-token fallbacks DB migration (sqlite3 direct): - farina integrale / Farina integrale di grano tenero → Farina integrale (3 rows) - Prodotto sconosciuto (Belbake, it:farina-integrale) → Farina integrale - Zucchero di canna → Zucchero di canna - Passato di patate e carote → Verdure (it's a blended veg purée) - Aroma mandorla per dolci → Ingredienti Spezie (consistent with other aromas) Total: 11 products re-classified README.md: - Shopping List: added generic shopping name feature + auto-add on depletion - Cooking Mode: updated TTS description (browser / native Android / REST) - Kiosk: added native TTS bridge bullet - Roadmap: checked off 3 new completed items
This commit is contained in:
@@ -33,15 +33,17 @@
|
|||||||
|
|
||||||
### 🛒 Shopping List
|
### 🛒 Shopping List
|
||||||
- **Bring! integration** — Sync with the [Bring!](https://www.getbring.com/) shopping list app
|
- **Bring! integration** — Sync with the [Bring!](https://www.getbring.com/) shopping list app
|
||||||
|
- **Generic shopping names** — Products are grouped by type ("Latte", "Affettato", "Panna da cucina") rather than brand, keeping the Bring! list clean and consolidated
|
||||||
- **Smart predictions** — Know what you'll need before you run out
|
- **Smart predictions** — Know what you'll need before you run out
|
||||||
|
- **Auto-add on depletion** — When a product reaches zero the app adds it to Bring! automatically, no confirmation needed
|
||||||
- **Auto-remove on scan** — Products are removed from the shopping list when scanned in
|
- **Auto-remove on scan** — Products are removed from the shopping list when scanned in
|
||||||
- **DupliClick integration** — Online grocery ordering (Gruppo Poli)
|
- **DupliClick integration** — Online grocery ordering (Gruppo Poli)
|
||||||
|
|
||||||
### 🍳 Cooking Mode
|
### 🍳 Cooking Mode
|
||||||
- **Step-by-step guidance** — Follow recipes with a hands-free cooking interface
|
- **Step-by-step guidance** — Follow recipes with a hands-free cooking interface
|
||||||
- **Text-to-Speech** — Voice readout of recipe steps (configurable TTS endpoint)
|
- **Text-to-Speech** — Voice readout of recipe steps; supports browser Web Speech API, native Android TTS (kiosk), or a custom REST endpoint (Home Assistant, etc.)
|
||||||
- **Built-in timer** — Automatic timer suggestions based on recipe instructions
|
- **Built-in timer** — Automatic timer suggestions based on recipe instructions
|
||||||
- **Ingredient tracking** — Mark ingredients as used during cooking
|
- **Ingredient tracking** — Mark ingredients as used during cooking; leftover quantities prompt a "move to another location" flow
|
||||||
|
|
||||||
### 📊 Dashboard
|
### 📊 Dashboard
|
||||||
- **Waste tracking** — Monitor consumed vs. wasted products over 30 days
|
- **Waste tracking** — Monitor consumed vs. wasted products over 30 days
|
||||||
@@ -76,6 +78,7 @@
|
|||||||
- **Setup wizard** — 3-step guided configuration (URL, connection test, gateway)
|
- **Setup wizard** — 3-step guided configuration (URL, connection test, gateway)
|
||||||
- **Gateway auto-launch** — Launches the Scale Gateway in the background on startup
|
- **Gateway auto-launch** — Launches the Scale Gateway in the background on startup
|
||||||
- **Camera & mic permissions** — Full hardware access for barcode scanning and voice
|
- **Camera & mic permissions** — Full hardware access for barcode scanning and voice
|
||||||
|
- **Native TTS bridge** — Cooking mode voice readout uses the Android TextToSpeech engine directly, bypassing Web Speech API voice limitations; no offline voice packs required
|
||||||
- **Hard refresh** — ↻ button clears WebView cache to pick up web app updates
|
- **Hard refresh** — ↻ button clears WebView cache to pick up web app updates
|
||||||
- **Update notifications** — Checks GitHub releases every 6h, shows banner when updates available
|
- **Update notifications** — Checks GitHub releases every 6h, shows banner when updates available
|
||||||
- **SSL support** — Accepts self-signed certificates
|
- **SSL support** — Accepts self-signed certificates
|
||||||
@@ -313,6 +316,9 @@ The application uses no build tools — edit files directly and refresh.
|
|||||||
- [x] AI scan local matching — suggest existing pantry products before OFF lookup
|
- [x] AI scan local matching — suggest existing pantry products before OFF lookup
|
||||||
- [x] Scale auto-fill improvements — 10g threshold, ml conversion hints
|
- [x] Scale auto-fill improvements — 10g threshold, ml conversion hints
|
||||||
- [x] Update notification system — kiosk checks GitHub releases
|
- [x] Update notification system — kiosk checks GitHub releases
|
||||||
|
- [x] Generic shopping name grouping — compound-phrase + keyword map (100+ entries) + Gemini AI fallback
|
||||||
|
- [x] Auto-add to Bring! on product depletion — no confirmation step when stock reaches zero
|
||||||
|
- [x] Native Android TTS in kiosk — bypasses Web Speech API voice detection issues
|
||||||
- [ ] Offline mode with service worker
|
- [ ] Offline mode with service worker
|
||||||
- [ ] Export/import inventory data
|
- [ ] Export/import inventory data
|
||||||
- [ ] Notification system (Telegram, email) for expiring products
|
- [ ] Notification system (Telegram, email) for expiring products
|
||||||
|
|||||||
+20
-4
@@ -3703,25 +3703,37 @@ function computeShoppingName(string $name, string $category = '', string $brand
|
|||||||
'glassa balsamic' => 'Aceto balsamico',
|
'glassa balsamic' => 'Aceto balsamico',
|
||||||
// Cold cuts — specific cuts
|
// Cold cuts — specific cuts
|
||||||
'prosciutto cotto' => 'Prosciutto cotto',
|
'prosciutto cotto' => 'Prosciutto cotto',
|
||||||
// Flour subtypes
|
// Flour subtypes (MUST come before generic "farina")
|
||||||
'farina di riso' => 'Farina di riso',
|
'farina di riso' => 'Farina di riso',
|
||||||
'farina riso' => 'Farina di riso',
|
'farina riso' => 'Farina di riso',
|
||||||
'farina di mais' => 'Farina di mais',
|
'farina di mais' => 'Farina di mais',
|
||||||
'farina mais' => 'Farina di mais',
|
'farina mais' => 'Farina di mais',
|
||||||
'farina integrale' => 'Farina integrale',
|
'farina integrale' => 'Farina integrale',
|
||||||
|
'farina 00' => 'Farina',
|
||||||
|
// Roux / sugar subtypes
|
||||||
|
'zucchero di canna' => 'Zucchero di canna',
|
||||||
|
'zucchero canna' => 'Zucchero di canna',
|
||||||
|
'zucchero velo' => 'Zucchero a velo',
|
||||||
|
'zucchero a velo' => 'Zucchero a velo',
|
||||||
// Fresh pasta
|
// Fresh pasta
|
||||||
'pasta fresca' => 'Pasta fresca',
|
'pasta fresca' => 'Pasta fresca',
|
||||||
// Broth / stock
|
// Broth / stock
|
||||||
'brodo vegetale' => 'Brodo',
|
'brodo vegetale' => 'Brodo',
|
||||||
'brodo pollo' => 'Brodo',
|
'brodo pollo' => 'Brodo',
|
||||||
'brodo manzo' => 'Brodo',
|
'brodo manzo' => 'Brodo',
|
||||||
// Sugar subtypes
|
// Mixed vegetable purée / passato (MUST come before generic carote/patate)
|
||||||
'zucchero di canna' => 'Zucchero di canna',
|
'passato di verdure' => 'Verdure',
|
||||||
'zucchero canna' => 'Zucchero di canna',
|
'passato di patate' => 'Verdure',
|
||||||
// Water
|
// Water
|
||||||
'acqua frizzante' => 'Acqua',
|
'acqua frizzante' => 'Acqua',
|
||||||
'acqua gassata' => 'Acqua',
|
'acqua gassata' => 'Acqua',
|
||||||
'acqua minerale' => 'Acqua',
|
'acqua minerale' => 'Acqua',
|
||||||
|
// Aroma / flavouring
|
||||||
|
'aroma vaniglia' => 'Ingredienti Spezie',
|
||||||
|
'aroma mandorla' => 'Ingredienti Spezie',
|
||||||
|
'aroma limone' => 'Ingredienti Spezie',
|
||||||
|
'aroma rum' => 'Ingredienti Spezie',
|
||||||
|
'aroma arancia' => 'Ingredienti Spezie',
|
||||||
];
|
];
|
||||||
foreach ($phraseMap as $phrase => $canonical) {
|
foreach ($phraseMap as $phrase => $canonical) {
|
||||||
if (mb_strpos($lower, $phrase) !== false) {
|
if (mb_strpos($lower, $phrase) !== false) {
|
||||||
@@ -3771,6 +3783,10 @@ function computeShoppingName(string $name, string $category = '', string $brand
|
|||||||
'grattato' => 'Pangrattato',
|
'grattato' => 'Pangrattato',
|
||||||
'pangrattato' => 'Pangrattato',
|
'pangrattato' => 'Pangrattato',
|
||||||
'biscottate' => 'Fette biscottate',
|
'biscottate' => 'Fette biscottate',
|
||||||
|
// Leavening agents
|
||||||
|
'lievito' => 'Lievito',
|
||||||
|
// Flavourings / aromas (single-token fallback; phrases handled above)
|
||||||
|
'aroma' => 'Ingredienti Spezie',
|
||||||
// Dairy
|
// Dairy
|
||||||
'latte' => 'Latte',
|
'latte' => 'Latte',
|
||||||
'yogurt' => 'Yogurt',
|
'yogurt' => 'Yogurt',
|
||||||
|
|||||||
Reference in New Issue
Block a user