chore: auto-merge develop → main

Triggered by: 8928c75 feat(recipes): add tools_needed field — appliances shown as chips above ingredients
This commit is contained in:
github-actions[bot]
2026-05-16 09:57:43 +00:00
6 changed files with 41 additions and 4 deletions
+9 -4
View File
@@ -3020,6 +3020,7 @@ PROMPT;
'error_empty_reply' => 'Risposta vuota da Gemini',
'prompt_lang_rule' => 'IMPORTANTE: scrivi tutti i campi testuali della ricetta in Italiano.',
'prompt_step_example' => 'Passo 1…',
'tools_title' => 'Strumenti necessari',
],
'en' => [
'status_analyze_pantry' => '📦 Analyzing pantry...',
@@ -3042,6 +3043,7 @@ PROMPT;
'error_empty_reply' => 'Empty response from Gemini',
'prompt_lang_rule' => 'IMPORTANT: write all textual recipe fields in English only. Do not use Italian or German.',
'prompt_step_example' => 'Step 1…',
'tools_title' => 'Equipment needed',
],
'de' => [
'status_analyze_pantry' => '📦 Vorrat wird analysiert...',
@@ -3064,6 +3066,7 @@ PROMPT;
'error_empty_reply' => 'Leere Antwort von Gemini',
'prompt_lang_rule' => 'WICHTIG: schreibe alle textuellen Rezeptfelder nur auf Deutsch. Verwende kein Italienisch oder Englisch.',
'prompt_step_example' => 'Schritt 1…',
'tools_title' => 'Benötigte Geräte',
],
];
$text = $dict[$lang][$key] ?? $dict['it'][$key] ?? $key;
@@ -3441,14 +3444,15 @@ REGOLE:
4. "qty_number": valore NUMERICO nella STESSA unità della dispensa (g/ml/pz/conf, MAI kg o litri). Per non-dispensa: 0. IMPORTANTE: per ingredienti con unità "pz" scrivi qty_number come numero di PEZZI (es. 2, non 200g).
5. "name": usa ESATTAMENTE il nome dalla lista (il sistema lo usa per scalare l'inventario).
6. Includi nella lista ingredienti TUTTI quelli citati nei passi (tranne acqua/sale/pepe/olio).
7. Language rule: {$recipeLangName} only for all textual fields (`title`, `tags`, `expiry_note`, `ingredients.qty`, `steps`, `nutrition_note`). Keep `meal` unchanged.
7. Language rule: {$recipeLangName} only for all textual fields (`title`, `tags`, `expiry_note`, `ingredients.qty`, `steps`, `nutrition_note`, `tools_needed`). Keep `meal` unchanged.
8. `tools_needed`: array of kitchen tools/appliances actually required by this recipe (e.g. ["Forno","Frullatore"]). Use the same language as all other text fields. Empty array [] if only stovetop/knife/pan needed.
DISPENSA:
$ingredientsText
Rispondi SOLO JSON valido (no markdown):
{$promptLanguageRule}
{"title":"","meal":"$mealType","persons":$persons,"prep_time":"","cook_time":"","tags":[""],"expiry_note":"","ingredients":[{"name":"","qty":"200 g","qty_number":200,"from_pantry":true}],"steps":["{$promptStepExample}"],"nutrition_note":""}
{"title":"","meal":"$mealType","persons":$persons,"prep_time":"","cook_time":"","tags":[""],"expiry_note":"","tools_needed":[""],"ingredients":[{"name":"","qty":"200 g","qty_number":200,"from_pantry":true}],"steps":["{$promptStepExample}"],"nutrition_note":""}
PROMPT;
$payload = [
@@ -4317,14 +4321,15 @@ REGOLE:
4. "qty_number": valore NUMERICO nella STESSA unità della dispensa (g/ml/pz/conf, MAI kg o litri). Per non-dispensa: 0. IMPORTANTE: per ingredienti con unità "pz" scrivi qty_number come numero di PEZZI (es. 2, non 200g).
5. "name": usa ESATTAMENTE il nome dalla lista (il sistema lo usa per scalare l'inventario).
6. Includi nella lista ingredienti TUTTI quelli citati nei passi (tranne acqua/sale/pepe/olio).
7. Language rule: {$recipeLangName} only for all textual fields (`title`, `tags`, `expiry_note`, `ingredients.qty`, `steps`, `nutrition_note`). Keep `meal` unchanged.
7. Language rule: {$recipeLangName} only for all textual fields (`title`, `tags`, `expiry_note`, `ingredients.qty`, `steps`, `nutrition_note`, `tools_needed`). Keep `meal` unchanged.
8. `tools_needed`: array of kitchen tools/appliances actually required by this recipe (e.g. ["Forno","Frullatore"]). Use the same language as all other text fields. Empty array [] if only stovetop/knife/pan needed.
DISPENSA:
$ingredientsText
Rispondi SOLO JSON valido (no markdown):
{$promptLanguageRule}
{"title":"","meal":"$mealType","persons":$persons,"prep_time":"","cook_time":"","tags":[""],"expiry_note":"","ingredients":[{"name":"","qty":"200 g","qty_number":200,"from_pantry":true}],"steps":["{$promptStepExample}"],"nutrition_note":""}
{"title":"","meal":"$mealType","persons":$persons,"prep_time":"","cook_time":"","tags":[""],"expiry_note":"","tools_needed":[""],"ingredients":[{"name":"","qty":"200 g","qty_number":200,"from_pantry":true}],"steps":["{$promptStepExample}"],"nutrition_note":""}
PROMPT;
$genConfig = [
+23
View File
@@ -3918,6 +3918,29 @@ body.server-offline .bottom-nav {
line-height: 1.5;
}
.recipe-tools-banner {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px;
background: #f0f4ff;
border: 1px solid #c7d2fe;
border-radius: var(--radius-sm);
padding: 8px 12px;
font-size: 0.85rem;
color: #3730a3;
margin-bottom: 12px;
line-height: 1.5;
}
.recipe-tool-chip {
background: #e0e7ff;
border-radius: 20px;
padding: 2px 10px;
font-size: 0.8rem;
color: #3730a3;
white-space: nowrap;
}
/* Recipe ingredient use buttons */
.recipe-ingredients {
list-style: none;
+6
View File
@@ -11954,6 +11954,12 @@ function renderRecipe(r) {
html += `<div class="recipe-expiry-note">⚠️ ${r.expiry_note}</div>`;
}
// Tools/appliances banner (shown only when specific equipment is needed)
const tools = (r.tools_needed || []).filter(t => t && t.trim());
if (tools.length > 0) {
html += `<div class="recipe-tools-banner">🔧 <strong>${t('recipes.tools_title')}:</strong> ${tools.map(t => `<span class="recipe-tool-chip">${t}</span>`).join('')}</div>`;
}
// Ingredients
html += `<h3>${t('recipes.ingredients_title')}</h3><ul class="recipe-ingredients">`;
(r.ingredients || []).forEach((ing, idx) => {
+1
View File
@@ -341,6 +341,7 @@
"regenerate": "🔄 Noch eins generieren",
"close_btn": "✅ Schließen",
"ingredients_title": "🧾 Zutaten",
"tools_title": "Benötigte Geräte",
"steps_title": "👨‍🍳 Zubereitung",
"no_steps": "Keine Zubereitungsschritte verfügbar",
"generate_error": "Fehler bei der Generierung",
+1
View File
@@ -341,6 +341,7 @@
"regenerate": "🔄 Generate another one",
"close_btn": "✅ Close",
"ingredients_title": "🧾 Ingredients",
"tools_title": "Equipment needed",
"steps_title": "👨‍🍳 Steps",
"no_steps": "No steps available",
"generate_error": "Generation error",
+1
View File
@@ -341,6 +341,7 @@
"regenerate": "🔄 Generane un'altra",
"close_btn": "✅ Chiudi",
"ingredients_title": "🧾 Ingredienti",
"tools_title": "Strumenti necessari",
"steps_title": "👨‍🍳 Procedimento",
"no_steps": "Nessun procedimento disponibile",
"generate_error": "Errore nella generazione",