! HELP ! LitElement Custom Panel Not Detecting Sensor Attribute Updates

Hi everyone

I’m building a custom integration for managing a restaurant in Home Assistant. The logic is already working well through YAML UI, where we use input_button, input_text, input_select, and RAM-based sensor.* to track and save dynamic content like ingredients, preparations, and full recipes.

Now I’m working on a custom panel (web UI built with LitElement) to replicate and improve the experience — making it more intuitive and user-friendly for non-technical users.

Everything is already working well, including Caja, Almacen, and Chef sections. But I’ve hit a roadblock with one part of the Chef → Ricette (Recipes) interface…

I’m building a custom dashboard panel using LitElement, fully integrated with Home Assistant (no Lovelace YAML UI). The panel replicates multiple restaurant management views (Caja, Warehouse, Chef, etc.), each with full HTML/JS interactivity.

Everything works flawlessly — except one major issue when dealing with a RAM sensor called sensor.ricetta_in_corso.


:test_tube: What’s the use case?

In the view #chef&sub=ricette, I’m assembling a complex recipe. The sensor sensor.ricetta_in_corso gets populated dynamically via input_select + input_button

{
  "ingredienti": [
    { "name": "Pomodoro", "quantity": 1.2 },
    { "name": "Mozzarella", "quantity": 0.5 }
  ],
  "preparazioni": [
    { "name": "Sugo", "quantity": 1 }
  ]
}

When I add ingredients or preparations using custom controls, the sensor is correctly updated in the backend (verified via Developer Tools).

But my custom dashboard only detects the first update. After that, further changes are ignored.


Markdown works fine

In the Lovelace version, I have a working Markdown card that reflects all changes correctly:

type: markdown
title: 📖 Ricetta in Corso
content: >-
  **Nome Ricetta:** {{ states('input_text.rk_recipe_name') }}

  **Descrizione:** {{ states('input_text.rk_recipe_description') }}

  **Tipo:** {{ states('input_text.rk_recipe_type') }}

  **Dosi:** {{ (states('input_number.rk_recipe_doses') | float(0)) | round(2) }}

  {% set ingredienti = state_attr('sensor.ricetta_in_corso', 'ingredienti') %}
  {% set preparazioni = state_attr('sensor.ricetta_in_corso', 'preparazioni') %}

  {% if ingredienti and ingredienti | length > 0 %}
  **Ingredienti:**
  {% for i in ingredienti %}
  - {{ i.name | capitalize }}: {{ i.quantity | float(0) | round(2) }}
  {% endfor %}
  {% else %} **Ingredienti:** Nessuno aggiunto
  {% endif %}

  {% if preparazioni and preparazioni | length > 0 %}
  **Preparazioni:**
  {% for p in preparazioni %}
  - {{ p.name | capitalize }}: {{ p.quantity | float(0) | round(2) }}
  {% endfor %}
  {% else %} **Preparazioni:** Nessuna aggiunta
  {% endif %}

THIS IS MY CUSTOM DASHBOARD

THIS IS THE SENSOR FROM UI

THATS WHAT I TRIED AND WORKS ONLY ONCE (I NEED TO PRESS F5 TO SEE THE SENSOR IN CUSTOM PANEL UPDATED)

_renderChefRicette() {
    const ingredientiOptions = this.hass?.states["input_select.rk_select_ingredient_recipe"]?.attributes?.options || [];
    const preparazioniOptions = this.hass?.states["input_select.rk_select_preparation_recipe"]?.attributes?.options || [];

    // Dati statici letti dagli input_*
    const nome = this.hass?.states["input_text.rk_recipe_name"]?.state || "-";
    const descrizione = this.hass?.states["input_text.rk_recipe_description"]?.state || "-";
    const tipo = this.hass?.states["input_text.rk_recipe_type"]?.state || "-";
    const dosi = this.hass?.states["input_number.rk_recipe_doses"]?.state || "0";

    // Dati dinamici dal sensore RAM
    const attr = this.hass?.states["sensor.ricetta_in_corso"]?.attributes || {};
    const ingredienti = Array.isArray(attr.ingredienti) ? attr.ingredienti : [];
    const preparazioni = Array.isArray(attr.preparazioni) ? attr.preparazioni : [];

    const rigaIngredienti = ingredienti.length
      ? html`<ul>${ingredienti.map(i => html`<li>${i.name}: ${parseFloat(i.quantity).toFixed(2)}</li>`)}</ul>`
      : html`<p><em>Nessun ingrediente aggiunto</em></p>`;

    const rigaPreparazioni = preparazioni.length
      ? html`<ul>${preparazioni.map(p => html`<li>${p.name}: ${parseFloat(p.quantity).toFixed(2)}</li>`)}</ul>`
      : html`<p><em>Nessuna preparazione aggiunta</em></p>`;

    return html`
      <h3>📖 Crea Ricetta Completa</h3>
      <div style="display: flex; gap: 40px; flex-wrap: wrap;">
        <!-- Info Ricetta -->
        <div style="flex: 1;">
          <h4>📝 Info Ricetta</h4>
          <label>Nome</label><br />
          <input id="ricetta-nome" value="${nome}" /><br /><br />
          <label>Descrizione</label><br />
          <input id="ricetta-desc" value="${descrizione}" /><br /><br />
          <label>Tipo</label><br />
          <input id="ricetta-tipo" value="${tipo}" /><br /><br />
          <label>Dosi</label><br />
          <input type="number" id="ricetta-dosi" value="${dosi}" /><br /><br />
          <button @click=${this._salvaRicetta}>💾 Salva Ricetta</button>
        </div>

        <!-- Aggiungi Ingrediente -->
        <div style="flex: 1;">
          <h4>🥕 Aggiungi Ingrediente</h4>
          <select id="ricetta-ingrediente">
            ${ingredientiOptions.map(opt => html`<option>${opt}</option>`)}
          </select><br /><br />
          <input type="number" id="ricetta-ingrediente-qty" /><br /><br />
          <button @click=${this._aggiungiIngredienteARicetta}>➕ Aggiungi ingrediente</button>
        </div>

        <!-- Aggiungi Preparazione -->
        <div style="flex: 1;">
          <h4>🍳 Aggiungi Preparazione</h4>
          <select id="ricetta-preparazione">
            ${preparazioniOptions.map(opt => html`<option>${opt}</option>`)}
          </select><br /><br />
          <input type="number" id="ricetta-preparazione-qty" /><br /><br />
          <button @click=${this._aggiungiPreparazioneARicetta}>➕ Aggiungi preparazione</button>
        </div>
      </div>

      <hr />
      <h4>📋 Ricetta in Corso</h4>
      <p><strong>Nome:</strong> ${nome}</p>
      <p><strong>Descrizione:</strong> ${descrizione}</p>
      <p><strong>Tipo:</strong> ${tipo}</p>
      <p><strong>Dosi:</strong> ${dosi}</p>

      <p><strong>Ingredienti:</strong></p>
      ${rigaIngredienti}

      <p><strong>Preparazioni:</strong></p>
      ${rigaPreparazioni}
    `;
  }


  _aggiungiIngredienteARicetta() {
    const ingrediente = this.renderRoot.querySelector("#ricetta-ingrediente")?.value;
    const qty = parseFloat(this.renderRoot.querySelector("#ricetta-ingrediente-qty")?.value);
    const nome = this.renderRoot.querySelector("#ricetta-nome")?.value;
    const descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value;
    const tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value;
    const dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value);

    if (!ingrediente || isNaN(qty)) return alert("❌ Quantità non valida");

    // aggiorna input_text per riflettere subito nei sensori
    this.hass.callService("input_text", "set_value", { entity_id: "input_text.rk_recipe_name", value: nome });
    this.hass.callService("input_text", "set_value", { entity_id: "input_text.rk_recipe_description", value: descrizione });
    this.hass.callService("input_text", "set_value", { entity_id: "input_text.rk_recipe_type", value: tipo });
    this.hass.callService("input_number", "set_value", { entity_id: "input_number.rk_recipe_doses", value: dosi });

    // poi aggiungi ingrediente alla RAM
    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_ingredient_recipe",
      option: ingrediente,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_ingredient_quantity",
      value: qty,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_add_ingredient_to_recipe",
    });
    
  }


  _aggiungiPreparazioneARicetta() {
    const preparazione = this.renderRoot.querySelector("#ricetta-preparazione")?.value;
    const qty = parseFloat(this.renderRoot.querySelector("#ricetta-preparazione-qty")?.value);
    const nome = this.renderRoot.querySelector("#ricetta-nome")?.value;
    const descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value;
    const tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value;
    const dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value);

    if (!preparazione || isNaN(qty)) {
      alert("❌ Dati non validi");
      return;
    }

    // 🟡 Aggiorna i dati statici per coerenza nel sensore
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_name",
      value: nome,
    });
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_description",
      value: descrizione,
    });
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_type",
      value: tipo,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_recipe_doses",
      value: dosi,
    });

    // 🟢 Imposta entità per la preparazione da aggiungere
    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_preparation_recipe",
      option: preparazione,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_preparation_quantity_recipe",
      value: qty,
    });

    // 🟣 Trigger per aggiungere la preparazione alla lista RAM
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_add_preparation_to_recipe",
    });
    
  }


  _salvaRicetta() {
    const nome = this.renderRoot.querySelector("#ricetta-nome")?.value;
    const descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value;
    const tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value;
    const dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value);

    if (!nome || !descrizione || !tipo || isNaN(dosi)) {
      alert("❌ Inserisci tutti i dati della ricetta");
      return;
    }

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_name",
      value: nome,
    });

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_description",
      value: descrizione,
    });

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_type",
      value: tipo,
    });

    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_recipe_doses",
      value: dosi,
    });

    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_save_recipe",
    });

  }

Using updated(changedProps)

updated(changedProps) {
    super.updated?.(changedProps);

    if (this.section !== "chef" || this.subSection !== "ricette") return;

    const attr = this.hass?.states["sensor.ricetta_in_corso"]?.attributes || {};
    const currentList = {
      ingredienti: attr.ingredienti || [],
      preparazioni: attr.preparazioni || [],
    };

    const snapshot = JSON.stringify(currentList);
    if (this._lastRicettaSnapshot !== snapshot) {
      console.log("🔄 Cambiamento ingredienti/preparazioni rilevato");
      this._lastRicettaSnapshot = snapshot;
      this.requestUpdate();
    }
  }



Global state-changed event

connectedCallback() {
  super.connectedCallback();
  window.addEventListener("state-changed", this._onHassStateChange);
}

_onHassStateChange = (e) => {
  if (
    this.section === "chef" &&
    this.subSection === "ricette" &&
    e?.detail?.entity_id === "sensor.ricetta_in_corso"
  ) {
    console.log("📡 state-changed received!");
    this.requestUpdate();
  }
};

Meanwhile…

In the chef&sub=preparazioni view, a similar RAM sensor sensor.preparazione_in_corso works fine.
The Custom view is reactive and re-renders on each ingredient added.

My question:

I’m attaching in the next message my full custom panel code — is there something I’m missing that prevents sensor.ricetta_in_corso from triggering UI updates after the first change?
Is there a better way to react to attribute changes within a LitElement based custom panel?

Thanks in advance

THIS IS MY CUSTOM PANEL CODE

import { html, css, LitElement } from "https://unpkg.com/[email protected]/lit-element.js?module";


class RestaurantDashboard extends LitElement {
  static get properties() {
    return {
      hass: { type: Object },
      narrow: { type: Boolean },
      panel: { type: Object },
      route: { type: Object },
      section: { type: String },       // ✅ AGGIUNTO
      subSection: { type: String },    // ✅ AGGIUNTO
      ricettaInCorso: { type: Object }, // ✅ AGGIUNTA QUI
    };
  }


  constructor() {
    super();
    this.section = null;
    this._boundHashChange = this._onHashChange.bind(this); // bind UNA VOLTA SOLA
    this._lastRicettaState = null;
    this._lastRecipeCount = 0;




  }

  


  connectedCallback() {
    super.connectedCallback();
    window.addEventListener("hashchange", this._boundHashChange);
    window.addEventListener("state-changed", this._onHassStateChange); // 🟢 ascolta eventi
    this._boundHashChange();
  }


  

  
  updated(changedProps) {
    super.updated?.(changedProps);

    if (this.section !== "chef" || this.subSection !== "ricette") return;

    const attr = this.hass?.states["sensor.ricetta_in_corso"]?.attributes || {};
    const currentList = {
      ingredienti: attr.ingredienti || [],
      preparazioni: attr.preparazioni || [],
    };

    const snapshot = JSON.stringify(currentList);
    if (this._lastRicettaSnapshot !== snapshot) {
      console.log("🔄 Cambiamento ingredienti/preparazioni rilevato");
      this._lastRicettaSnapshot = snapshot;
      this.requestUpdate();
    }
  }







  disconnectedCallback() {
    if (this._observer) this._observer.disconnect();
    window.removeEventListener("hashchange", this._boundHashChange);
    window.removeEventListener("state-changed", this._onHassStateChange); // 🔴 rimuovi listener
    super.disconnectedCallback();
  }



  hassChanged(changedProps) {
    if (
      this.section === "chef" &&
      this.subSection === "ricette" &&
      changedProps.has("sensor.ricetta_in_corso")
    ) {
      const old = changedProps.get("sensor.ricetta_in_corso");
      const current = this.hass.states["sensor.ricetta_in_corso"];

      if (JSON.stringify(old?.attributes) !== JSON.stringify(current?.attributes)) {
        console.log("🟢 Ricetta aggiornata via hassChanged:", current);
        this.requestUpdate();
      }
    }
  }











  

  _onHashChange() {
    const [main, sub] = window.location.hash.replace("#", "").split("&sub=");
    this.section = main || null;
    this.subSection = sub || null;
    this.requestUpdate();
  }

  _navigateChef(sub) {
  this.subSection = sub;
  window.location.hash = `#chef&sub=${sub}`;
}



  static get styles() {
    return css`
      :host {
        display: block;
        padding: 20px;
        background-color: #1e1e1e;
        color: white;
      }
      h2 {
        color: #00b894;
      }
      nav a {
        display: inline-block;
        margin: 0 10px 20px 0;
        color: white;
        text-decoration: none;
        background: #2d3436;
        padding: 10px;
        border-radius: 5px;
      }
      nav a:hover {
        background: #636e72;
      }
    `;
  }

  render() {
    return html`
      <h2>📋 Dashboard Ristorante</h2>
      <nav>
        <button @click=${() => this._navigate("caja")}>📦 Caja</button>
        <button @click=${() => this._navigate("almacen")}>🏬 Almacen</button>
        <button @click=${() => this._navigate("chef")}>🧑‍🍳 Chef</button>
        <button @click=${() => this._navigate("cocineros")}>👨‍🍳 Cocineros</button>
      </nav>
      <div id="content">
        ${this._renderSection()}
      </div>
    `;
  }

  _renderSection() {
    let content;
    switch (this.section) {
      case "caja":
        content = this._renderCaja();
        break;
      case "almacen":
        content = html`<p>🏬 Sezione magazzino in costruzione</p>`;
        break;
      case "chef":
        content = this._renderChef();
        break;
      case "cocineros":
        content = html`<p>👨‍🍳 Sezione cuochi in costruzione</p>`;
        break;
      case null:
        content = html`<p>📋 Seleziona una sezione dal menu sopra.</p>`;
        break;
      default:
        content = html`<p>❓ Sezione sconosciuta: ${this.section}</p>`;
    }


    return content;
  }

  _renderChef() {
    return html`
      <h2>🧑‍🍳 Chef</h2>
      <div style="margin-bottom: 20px;">
        <button @click=${() => this._navigateChef("base")}>👨‍🍳 Ingredientes</button>
        <button @click=${() => this._navigateChef("gestionalmacen")}>📦 Almacen</button>
        <button @click=${() => this._navigateChef("preparazioni")}>🍳 Preparaciones</button>
        <button @click=${() => this._navigateChef("ricette")}>📖 Recetas</button>
        <button @click=${() => this._navigateChef("tasks")}>✅ Tasks</button>
      </div>
      <div>
        ${this._renderChefSubSection()}
      </div>
    `;
  }

  _renderChefSubSection() {
    let content;
    switch (this.subSection) {
      case "base":
        content = this._renderChefBase();
        break;
      case "gestionalmacen":
        content = this._renderChefGestioneMagazzino();
        break;
      case "preparazioni":
        content = this._renderChefPreparazioni();
        break;
      case "ricette":
        content = this._renderChefRicette();
        break;
      case "tasks":
        content = html`<p>✅ Tasks in arrivo</p>`;
        break;
      default:
        content = html`<p>📋 Selecciona un elemento para gestionar: Almacenes,Preparaciones, Recetas y tasks.</p>`;
    }



    return content;
  }


  _renderChefBase() {
    
    return html`
      <h3>👨‍🍳 Gestión de ingredientes</h3>
      <div style="display: flex; gap: 40px; align-items: flex-start; flex-wrap: wrap;">
        <div style="flex: 1;">
          <h4>➕ Añadir ingrediente</h4>
          <label>📛 Nombre</label><br />
          <input id="rk_ingredient_name" placeholder="Es. Pomodoro" /><br /><br />
          <label>⚖️ Unidad (kg,gr,ud)</label><br />
          <input id="rk_ingredient_unit" placeholder="Es. kg, l, pz..." /><br /><br />
          <label>🏢 Provedoor</label><br />
          <input id="rk_supplier" placeholder="Es. Makro" /><br /><br />
          <label>💶 Coste unidad (€)</label><br />
          <input type="number" id="rk_cost" placeholder="Es. 2.35" /><br /><br />
          <button @click=${this._aggiungiIngrediente}>➕ Añadir</button>
        </div>

        <div style="flex: 1;">
          <h4>🗑️ Borrar Ingrediente</h4>
          ${this._renderRimuoviIngrediente()}
        </div>
      </div>

      <hr style="margin: 30px 0;">
      <h3>📋 Lista Ingredientes</h3>
      <div>
        ${this._renderListaIngredienti()}
      </div>
    `;
  }
  

  _renderChefGestioneMagazzino() {
    const stock = this.hass?.states["sensor.stock_magazzino"]?.attributes || {};

    const addOptions = (
      this.hass?.states["input_select.rk_select_ingredient_add_stock_total"]?.attributes?.options || []
    );

    const remOptions = (
      this.hass?.states["input_select.rk_select_ingredient_remove_stock_total"]?.attributes?.options || []
    );

    const rows = Object.entries(stock)
      .filter(([, val]) => val.quantity)
      .map(
        ([name, val]) => html`
          <tr>
            <td><strong>${name}</strong></td>
            <td>${val.quantity} ${val.unit}</td>
            <td>${val.supplier}</td>
          </tr>
        `
      );
    
    
    return html`
      <h3>📦 Gestion Almacen</h3>
      <div style="display: flex; gap: 40px; align-items: flex-start; flex-wrap: wrap;">
        <div style="flex: 1;">
          <h4>📥 Anadir</h4>
          <label>Ingrediente</label><br />
          <select id="stock-add">
            ${addOptions.map(opt => html`<option value="${opt}">${opt}</option>`)}
          </select><br /><br />
          <label>Cantidad</label><br />
          <input type="number" id="stock-qty-add" /><br /><br />
          <button @click=${this._aggiungiMagazzino}>Anadir</button>
        </div>
        <div style="flex: 1;">
          <h4>❌ Borrar</h4>
          <label>Ingrediente</label><br />
          <select id="stock-remove">
            ${remOptions.map(opt => html`<option value="${opt}">${opt}</option>`)}
          </select><br /><br />
          <button @click=${this._rimuoviMagazzino}>Borrar</button>
        </div>
      </div>
      <hr style="margin: 30px 0;">
      <h3>📋 Almacen Actual</h3>
      <table style="width: 100%; border-collapse: collapse; font-size: 14px;">
        <thead>
          <tr><th>Ingrediente</th><th>Cantidad</th><th>Provedor</th></tr>
        </thead>
        <tbody>${rows}</tbody>
      </table>
    `;
  }
  _renderChefPreparazioni() {
    const costoSensor = this.hass?.states["sensor.costo_preparazioni"];
    const costoPreparazioni = costoSensor?.attributes?.costo_preparazioni || {};
    const righeCosto = Object.entries(costoPreparazioni).map(([nome, dati]) => {
      const costoPerDose = (dati.dosi && dati.costo_totale)
        ? (dati.costo_totale / dati.dosi).toFixed(2)
        : "0.00";
      return html`<li><strong>${nome}</strong>: ${costoPerDose} €</li>`;
    });

    const preparazioneAttr = this.hass?.states["sensor.preparazione_in_corso"]?.attributes || {};
    const ingredienti = Object.entries(preparazioneAttr).filter(([k]) => k !== "friendly_name");

    const rigaIngredienti = ingredienti.length
      ? html`
          <p><strong>Ingredienti:</strong></p>
          <ul>
            ${ingredienti.map(([nome, qty]) => html`
              <li>${nome}: ${parseFloat(qty).toFixed(2)}</li>
            `)}
          </ul>
        `
      : html`<p><strong>Ingredienti:</strong> Nessun ingrediente aggiunto</p>`;

    const nome = this.hass?.states["input_text.rk_preparation_name"]?.state || "-";
    const desc = this.hass?.states["input_text.rk_preparation_description"]?.state || "-";
    const dosi = this.hass?.states["input_number.rk_preparation_doses"]?.state || "0";

    const ingredientiOptions = this.hass?.states["input_select.rk_select_ingredient_preparation"]?.attributes?.options || [];
    const rimuoviOptions = this.hass?.states["input_select.rk_select_preparation_remove"]?.attributes?.options || [];

    return html`
      <h3>🍳 Nuova Preparazione</h3>
      <div style="display: flex; gap: 40px; align-items: flex-start; flex-wrap: wrap;">
        
        <div style="flex: 1;">
          <h4>📝 Info Preparazione</h4>
          <label>📛 Nome</label><br />
          <input id="prep-nome" /><br /><br />
          <label>📝 Descrizione</label><br />
          <input id="prep-desc" /><br /><br />
          <label>🔢 Dosi</label><br />
          <input type="number" id="prep-dosi" /><br /><br />
          <button @click=${this._salvaPreparazione}>💾 Salva Preparazione</button>
        </div>

        <div style="flex: 1;">
          <h4>🥕 Aggiungi Ingrediente</h4>
          <label>Seleziona ingrediente</label><br />
          <select id="prep-ingrediente">
            ${ingredientiOptions.map(opt => html`<option>${opt}</option>`)}
          </select><br /><br />
          <input type="number" id="prep-qty" placeholder="Quantità" /><br /><br />
          <button @click=${this._aggiungiIngredienteAPreparazione}>➕ Aggiungi ingrediente</button>
        </div>

        <div style="flex: 1;">
          <h4>🗑️ Rimuovi Preparazione</h4>
          <label>Preparazione da rimuovere</label><br />
          <select id="prep-remove">
            ${rimuoviOptions.map(opt => html`<option>${opt}</option>`)}
          </select><br /><br />
          <button @click=${this._rimuoviPreparazione}>❌ Rimuovi</button>
        </div>
      </div>

      <hr />
      <h4>📋 Preparazione in Corso</h4>
      <p><strong>Nome:</strong> ${nome}</p>
      <p><strong>Descrizione:</strong> ${desc}</p>
      <p><strong>Dosi:</strong> ${dosi}</p>
      ${rigaIngredienti}

      <hr />
      <h4>💰 Costi per Dose</h4>
      <ul>${righeCosto}</ul>
    `;
  }

  _onHassStateChange = (e) => {
    if (
      this.section === "chef" &&
      this.subSection === "ricette" &&
      e?.detail?.entity_id === "sensor.ricetta_in_corso"
    ) {
      console.log("📡 Evento state-changed ricevuto!", e.detail);
      this.requestUpdate();
    }
  };


  _aggiungiIngredienteAPreparazione() {
    const ingrediente = this.renderRoot.querySelector("#prep-ingrediente")?.value;
    const qty = parseFloat(this.renderRoot.querySelector("#prep-qty")?.value);
    if (!ingrediente || isNaN(qty)) return alert("Dati non validi");

    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_ingredient_preparation",
      option: ingrediente,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_preparation_ingredient_quantity",
      value: qty,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_add_ingredient_to_preparation",
    });
  }



  _salvaPreparazione() {
    const nome = this.renderRoot.querySelector("#prep-nome")?.value;
    const desc = this.renderRoot.querySelector("#prep-desc")?.value;
    const dosi = parseFloat(this.renderRoot.querySelector("#prep-dosi")?.value);
    if (!nome || !desc || isNaN(dosi)) return alert("Dati non validi");

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_preparation_name",
      value: nome,
    });
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_preparation_description",
      value: desc,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_preparation_doses",
      value: dosi,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_save_preparation",
    });
    alert("✅ Preparazione salvata!");
  }

  _rimuoviPreparazione() {
    const selezione = this.renderRoot.querySelector("#prep-remove")?.value;
    if (!selezione) return;

    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_preparation_remove",
      option: selezione,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_remove_preparation",
    });
    alert("🗑️ Preparazione rimossa");
  }



  _aggiungiMagazzino() {
    const ing = this.renderRoot.querySelector("#stock-add")?.value;
    const qty = parseFloat(this.renderRoot.querySelector("#stock-qty-add")?.value);
    if (!ing || isNaN(qty)) return alert("Dati non validi");
    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_ingredient_add_stock_total",
      option: ing,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_stock_total_quantity",
      value: qty,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_update_stock_total",
    });
    alert("✅ Aggiunta effettuata");
  }

  _rimuoviMagazzino() {
    const ing = this.renderRoot.querySelector("#stock-remove")?.value;
    if (!ing) return alert("Nessun ingrediente selezionato");
    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_ingredient_remove_stock_total",
      option: ing,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_remove_stock_total",
    });
    alert("🗑️ Rimozione effettuata");
  }

  _aggiungiIngrediente() {
    const nome = this.renderRoot.querySelector("#rk_ingredient_name")?.value;
    const unita = this.renderRoot.querySelector("#rk_ingredient_unit")?.value;
    const fornitore = this.renderRoot.querySelector("#rk_supplier")?.value;
    const costo = parseFloat(this.renderRoot.querySelector("#rk_cost")?.value);

    if (!nome || !unita || !fornitore || isNaN(costo)) {
      alert("Compila tutti i campi con valori validi.");
      return;
    }

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_ingredient_name",
      value: nome,
    });
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_ingredient_unit",
      value: unita,
    });
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_supplier",
      value: fornitore,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_ingredient_cost",
      value: costo,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_add_ingredient",
    });

    alert("✅ Ingrediente aggiunto!");
  }

  _renderListaIngredienti() {
    const sensor = this.hass?.states["sensor.ingredienti"];
    const attr = sensor?.attributes;

    if (!attr || Object.keys(attr).length === 0) {
      return html`<p>📭 Nessun ingrediente trovato.</p>`;
    }

    const righe = Object.entries(attr)
      .filter(([k]) => k !== "friendly_name")
      .map(([nome, info]) => {
        const costo = info.cost ? `${info.cost} €` : "-";
        const unita = info.unit || "-";
        const supplier = info.supplier || "-";
        

        return html`
          <tr>
            <td>${nome}</td>
            <td>${unita}</td>
            <td>${supplier}</td>
            <td>${costo}</td>
          </tr>
        `;
      });

    return html`
      <table style="width:100%;border-collapse:collapse;font-size:14px;margin-top:10px;">
        <thead>
          <tr>
            <th>Ingrediente</th>
            <th>Unidad</th>
            <th>Provedor</th>
            <th>Coste</th>
          </tr>
        </thead>
        <tbody>${righe}</tbody>
      </table>
    `;
  }


  _renderRimuoviIngrediente() {
    const select = this.hass?.states["input_select.rk_select_ingredient_remove"];
    const options = select?.attributes?.options || [];

    if (options.length === 0) {
      return html`<p>❌ Nessun ingrediente disponibile.</p>`;
    }
    

    return html`
      <select id="select-rimuovi-ingrediente">
        ${options.map(opt => html`<option value="${opt}">${opt}</option>`)}
      </select><br><br>
      <button @click=${this._rimuoviIngrediente}>❌ Rimuovi</button>
    `;
  }

  _rimuoviIngrediente() {
    const select = this.renderRoot.querySelector("#select-rimuovi-ingrediente");
    const ingrediente = select?.value;
    if (!ingrediente) return;

    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_ingredient_remove",
      option: ingrediente,
    });

    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_remove_ingredient",
    });

    alert(`🗑️ Ingrediente "${ingrediente}" rimosso`);
  }


  _navigate(section) {
    if (this.section !== section) {
      this.section = section;
      this.requestUpdate();
    }
  }
  

  _renderChefRicette() {
    const ingredientiOptions = this.hass?.states["input_select.rk_select_ingredient_recipe"]?.attributes?.options || [];
    const preparazioniOptions = this.hass?.states["input_select.rk_select_preparation_recipe"]?.attributes?.options || [];

    // Dati statici letti dagli input_*
    const nome = this.hass?.states["input_text.rk_recipe_name"]?.state || "-";
    const descrizione = this.hass?.states["input_text.rk_recipe_description"]?.state || "-";
    const tipo = this.hass?.states["input_text.rk_recipe_type"]?.state || "-";
    const dosi = this.hass?.states["input_number.rk_recipe_doses"]?.state || "0";

    // Dati dinamici dal sensore RAM
    const attr = this.hass?.states["sensor.ricetta_in_corso"]?.attributes || {};
    const ingredienti = Array.isArray(attr.ingredienti) ? attr.ingredienti : [];
    const preparazioni = Array.isArray(attr.preparazioni) ? attr.preparazioni : [];

    const rigaIngredienti = ingredienti.length
      ? html`<ul>${ingredienti.map(i => html`<li>${i.name}: ${parseFloat(i.quantity).toFixed(2)}</li>`)}</ul>`
      : html`<p><em>Nessun ingrediente aggiunto</em></p>`;

    const rigaPreparazioni = preparazioni.length
      ? html`<ul>${preparazioni.map(p => html`<li>${p.name}: ${parseFloat(p.quantity).toFixed(2)}</li>`)}</ul>`
      : html`<p><em>Nessuna preparazione aggiunta</em></p>`;

    return html`
      <h3>📖 Crea Ricetta Completa</h3>
      <div style="display: flex; gap: 40px; flex-wrap: wrap;">
        <!-- Info Ricetta -->
        <div style="flex: 1;">
          <h4>📝 Info Ricetta</h4>
          <label>Nome</label><br />
          <input id="ricetta-nome" value="${nome}" /><br /><br />
          <label>Descrizione</label><br />
          <input id="ricetta-desc" value="${descrizione}" /><br /><br />
          <label>Tipo</label><br />
          <input id="ricetta-tipo" value="${tipo}" /><br /><br />
          <label>Dosi</label><br />
          <input type="number" id="ricetta-dosi" value="${dosi}" /><br /><br />
          <button @click=${this._salvaRicetta}>💾 Salva Ricetta</button>
        </div>

        <!-- Aggiungi Ingrediente -->
        <div style="flex: 1;">
          <h4>🥕 Aggiungi Ingrediente</h4>
          <select id="ricetta-ingrediente">
            ${ingredientiOptions.map(opt => html`<option>${opt}</option>`)}
          </select><br /><br />
          <input type="number" id="ricetta-ingrediente-qty" /><br /><br />
          <button @click=${this._aggiungiIngredienteARicetta}>➕ Aggiungi ingrediente</button>
        </div>

        <!-- Aggiungi Preparazione -->
        <div style="flex: 1;">
          <h4>🍳 Aggiungi Preparazione</h4>
          <select id="ricetta-preparazione">
            ${preparazioniOptions.map(opt => html`<option>${opt}</option>`)}
          </select><br /><br />
          <input type="number" id="ricetta-preparazione-qty" /><br /><br />
          <button @click=${this._aggiungiPreparazioneARicetta}>➕ Aggiungi preparazione</button>
        </div>
      </div>

      <hr />
      <h4>📋 Ricetta in Corso</h4>
      <p><strong>Nome:</strong> ${nome}</p>
      <p><strong>Descrizione:</strong> ${descrizione}</p>
      <p><strong>Tipo:</strong> ${tipo}</p>
      <p><strong>Dosi:</strong> ${dosi}</p>

      <p><strong>Ingredienti:</strong></p>
      ${rigaIngredienti}

      <p><strong>Preparazioni:</strong></p>
      ${rigaPreparazioni}
    `;
  }


  _aggiungiIngredienteARicetta() {
    const ingrediente = this.renderRoot.querySelector("#ricetta-ingrediente")?.value;
    const qty = parseFloat(this.renderRoot.querySelector("#ricetta-ingrediente-qty")?.value);
    const nome = this.renderRoot.querySelector("#ricetta-nome")?.value;
    const descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value;
    const tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value;
    const dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value);

    if (!ingrediente || isNaN(qty)) return alert("❌ Quantità non valida");

    // aggiorna input_text per riflettere subito nei sensori
    this.hass.callService("input_text", "set_value", { entity_id: "input_text.rk_recipe_name", value: nome });
    this.hass.callService("input_text", "set_value", { entity_id: "input_text.rk_recipe_description", value: descrizione });
    this.hass.callService("input_text", "set_value", { entity_id: "input_text.rk_recipe_type", value: tipo });
    this.hass.callService("input_number", "set_value", { entity_id: "input_number.rk_recipe_doses", value: dosi });

    // poi aggiungi ingrediente alla RAM
    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_ingredient_recipe",
      option: ingrediente,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_ingredient_quantity",
      value: qty,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_add_ingredient_to_recipe",
    });
    
  }


  _aggiungiPreparazioneARicetta() {
    const preparazione = this.renderRoot.querySelector("#ricetta-preparazione")?.value;
    const qty = parseFloat(this.renderRoot.querySelector("#ricetta-preparazione-qty")?.value);
    const nome = this.renderRoot.querySelector("#ricetta-nome")?.value;
    const descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value;
    const tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value;
    const dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value);

    if (!preparazione || isNaN(qty)) {
      alert("❌ Dati non validi");
      return;
    }

    // 🟡 Aggiorna i dati statici per coerenza nel sensore
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_name",
      value: nome,
    });
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_description",
      value: descrizione,
    });
    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_type",
      value: tipo,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_recipe_doses",
      value: dosi,
    });

    // 🟢 Imposta entità per la preparazione da aggiungere
    this.hass.callService("input_select", "select_option", {
      entity_id: "input_select.rk_select_preparation_recipe",
      option: preparazione,
    });
    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_preparation_quantity_recipe",
      value: qty,
    });

    // 🟣 Trigger per aggiungere la preparazione alla lista RAM
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_add_preparation_to_recipe",
    });
    
  }


  _salvaRicetta() {
    const nome = this.renderRoot.querySelector("#ricetta-nome")?.value;
    const descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value;
    const tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value;
    const dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value);

    if (!nome || !descrizione || !tipo || isNaN(dosi)) {
      alert("❌ Inserisci tutti i dati della ricetta");
      return;
    }

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_name",
      value: nome,
    });

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_description",
      value: descrizione,
    });

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.rk_recipe_type",
      value: tipo,
    });

    this.hass.callService("input_number", "set_value", {
      entity_id: "input_number.rk_recipe_doses",
      value: dosi,
    });

    this.hass.callService("input_button", "press", {
      entity_id: "input_button.rk_save_recipe",
    });

  }



 _renderCaja() {
  const stato = this.hass?.states["sensor.stato_cassa"]?.state;
  const storico = this.hass?.states["sensor.storico_cassa"];

  if (!stato) {
    return html`<p>⏳ Caricamento stato cassa...</p>`;
  }

  const storicoHtml = (() => {
    if (!storico?.attributes) {
      return html`<p>❌ Storico non disponibile.</p>`;
    }

    const items = Object.entries(storico.attributes)
      .filter(([k]) => k.startsWith("#"))
      .reverse();

    if (!items.length) {
      return html`<p>📭 Nessuna cassa registrata.</p>`;
    }
    
    return html`
      <h3>📊 Historial Caja</h3>
      <table style="width:100%;margin-top:10px;border-collapse:collapse;font-size:14px;">
        <thead>
          <tr>
            <th>Turno</th>
            <th>Apertura</th>
            <th>Efectivo</th>
            <th>Tarjeta</th>
            <th>Total</th>
          </tr>
        </thead>
        <tbody>
          ${items.map(
            ([turno, dati]) => html`
              <tr>
                <td>${turno}</td>
                <td>${dati.apertura ?? "-"}</td>
                <td>${dati.chiusura_contanti ?? "-"} €</td>
                <td>${dati.chiusura_carta ?? "-"} €</td>
                <td><strong>${dati.totale ?? "-"} €</strong></td>
              </tr>
            `
          )}
        </tbody>
      </table>
    `;
  })();

  return html`
    <h3>📦 Gestion de Caja</h3>
    <p>Stato attuale: ${stato === "si" ? "🟢 Abierta" : "🔒 Cerrada"}</p>
    ${stato === "no"
      ? html`
          <input type="number" id="importo-apertura" placeholder="Cantidad €" />
          <br />
          <button @click=${this._apriCassa}>🟢 Abrir Caja</button>
        `
      : html`
          <button @click=${this._chiudiCassa}>🔒 Cerrar Caja</button>
        `}
    <div style="margin-top: 20px;">${storicoHtml}</div>
  `;
}
  async _updateRecipeField(entity_id, value) {
    if (!entity_id || value == null) return;
    const domain = entity_id.split(".")[0];

    await this.hass.callService(domain, "set_value", {
      entity_id,
      value,
    });
  }

  

  _chiudiCassa() {
    this.hass.callService("restaurant_orders", "chiudi_cassa_del_giorno");
    alert("🔒 Richiesta chiusura cassa inviata");
    window.location.hash = "#caja";
  }


  _apriCassa() {
    const input = this.renderRoot.querySelector("#importo-apertura");
    const quantita = parseFloat(input?.value);
    if (!quantita || isNaN(quantita)) {
      alert("Inserisci una quantità valida.");
      return;
    }

    this.hass.callService("input_text", "set_value", {
      entity_id: "input_text.cassa_quantita_apertura",
      value: quantita,
    });
    this.hass.callService("input_button", "press", {
      entity_id: "input_button.apri_cassa",
    });

    alert(`🟢 Cassa aperta con ${quantita} €`);
    window.location.hash = "#caja"; // forza ricaricamento
  }

}


customElements.define("restaurant-dashboard", RestaurantDashboard);

window.customPanel = {
  async setup(hass, narrow, config) {
    const el = document.createElement("restaurant-dashboard");
    el.hass = hass;
    el.narrow = narrow;
    el.panel = { config };
    return el;
  },
};

i solved using a temporary sensor that pass all the data just at the end, when i save the receipe.

so i used in the constructor

this._ricettaTemporanea = {
  nome: "",
  descrizione: "",
  tipo: "",
  dosi: 0,
  ingredienti: [],
  preparazioni: [],
};

and using

in the render of the sub class chef/ricette

_renderChefRicette() {
  const ingredientiOptions = this.hass?.states["input_select.rk_select_ingredient_recipe"]?.attributes?.options || [];
  const preparazioniOptions = this.hass?.states["input_select.rk_select_preparation_recipe"]?.attributes?.options || [];

  const r = this._ricettaTemporanea;

  const rigaIngredienti = r.ingredienti.length
    ? html`<ul>${r.ingredienti.map(i => html`<li>${i.name}: ${parseFloat(i.quantity).toFixed(2)}</li>`)}</ul>`
    : html`<p><em>Nessun ingrediente aggiunto</em></p>`;

  const rigaPreparazioni = r.preparazioni.length
    ? html`<ul>${r.preparazioni.map(p => html`<li>${p.name}: ${parseFloat(p.quantity).toFixed(2)}</li>`)}</ul>`
    : html`<p><em>Nessuna preparazione aggiunta</em></p>`;

  return html`
    <h3>📖 Crea Ricetta Completa</h3>
    <div style="display: flex; gap: 40px; flex-wrap: wrap;">
      <!-- Info Ricetta -->
      <div style="flex: 1;">
        <h4>📝 Info Ricetta</h4>
        <label>Nome</label><br />
        <input id="ricetta-nome" .value=${r.nome} /><br /><br />
        <label>Descrizione</label><br />
        <input id="ricetta-desc" .value=${r.descrizione} /><br /><br />
        <label>Tipo</label><br />
        <input id="ricetta-tipo" .value=${r.tipo} /><br /><br />
        <label>Dosi</label><br />
        <input type="number" id="ricetta-dosi" .value=${r.dosi} /><br /><br />
        <button @click=${this._salvaRicetta}>💾 Salva Ricetta</button>
      </div>

      <!-- Aggiungi Ingrediente -->
      <div style="flex: 1;">
        <h4>🥕 Aggiungi Ingrediente</h4>
        <select id="ricetta-ingrediente">
          ${ingredientiOptions.map(opt => html`<option>${opt}</option>`)}
        </select><br /><br />
        <input type="number" id="ricetta-ingrediente-qty" /><br /><br />
        <button @click=${this._aggiungiIngredienteARicetta}>➕ Aggiungi ingrediente</button>
      </div>

      <!-- Aggiungi Preparazione -->
      <div style="flex: 1;">
        <h4>🍳 Aggiungi Preparazione</h4>
        <select id="ricetta-preparazione">
          ${preparazioniOptions.map(opt => html`<option>${opt}</option>`)}
        </select><br /><br />
        <input type="number" id="ricetta-preparazione-qty" /><br /><br />
        <button @click=${this._aggiungiPreparazioneARicetta}>➕ Aggiungi preparazione</button>
      </div>
    </div>

    <hr />
    <h4>📋 Ricetta in Corso</h4>
    <p><strong>Nome:</strong> ${r.nome}</p>
    <p><strong>Descrizione:</strong> ${r.descrizione}</p>
    <p><strong>Tipo:</strong> ${r.tipo}</p>
    <p><strong>Dosi:</strong> ${r.dosi}</p>

    <p><strong>Ingredienti:</strong></p>
    ${rigaIngredienti}

    <p><strong>Preparazioni:</strong></p>
    ${rigaPreparazioni}
  `;
}

so to add ingredienti and preparation to ram sensor (ricettatemporanea)

_aggiungiIngredienteARicetta() {
  const ingrediente = this.renderRoot.querySelector("#ricetta-ingrediente")?.value;
  const qty = parseFloat(this.renderRoot.querySelector("#ricetta-ingrediente-qty")?.value);

  if (!ingrediente || isNaN(qty)) return alert("❌ Quantità non valida");

  this._aggiornaInfoRicetta();
  this._ricettaTemporanea.ingredienti.push({ name: ingrediente, quantity: qty });
  this.requestUpdate();
}

_aggiungiPreparazioneARicetta() {
  const preparazione = this.renderRoot.querySelector("#ricetta-preparazione")?.value;
  const qty = parseFloat(this.renderRoot.querySelector("#ricetta-preparazione-qty")?.value);

  if (!preparazione || isNaN(qty)) return alert("❌ Quantità non valida");

  this._aggiornaInfoRicetta();
  this._ricettaTemporanea.preparazioni.push({ name: preparazione, quantity: qty });
  this.requestUpdate();
}

_aggiornaInfoRicetta() {
  this._ricettaTemporanea.nome = this.renderRoot.querySelector("#ricetta-nome")?.value || "";
  this._ricettaTemporanea.descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value || "";
  this._ricettaTemporanea.tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value || "";
  this._ricettaTemporanea.dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value) || 0;
}

and my save receipe pass everything to the original sensor and call the action

_salvaRicetta() {
  const nome = this.renderRoot.querySelector("#ricetta-nome")?.value;
  const descrizione = this.renderRoot.querySelector("#ricetta-desc")?.value;
  const tipo = this.renderRoot.querySelector("#ricetta-tipo")?.value;
  const dosi = parseFloat(this.renderRoot.querySelector("#ricetta-dosi")?.value);

  if (!nome || !descrizione || !tipo || isNaN(dosi) || dosi <= 0) {
    alert("❌ Inserisci tutti i dati della ricetta");
    return;
  }

  // Carichiamo nel sensore RAM
  this.hass.callService("restaurant_kitchen", "load_current_recipe", {
    ingredienti: this._ricettaTemporanea.ingredienti || [],
    preparazioni: this._ricettaTemporanea.preparazioni || [],
  });

  // Poi salviamo
  this.hass.callService("restaurant_kitchen", "save_recipe", {
    name: nome,
    description: descrizione,
    type: tipo,
    doses: dosi,
  });

  alert("✅ Ricetta salvata!");

  // Pulisci RAM client
  this._ricettaTemporanea = {
    ingredienti: [],
    preparazioni: [],
  };

  this.requestUpdate();
}