From 44c3a6c910fe9f84c84dc982450ab1b87ea6b560 Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Wed, 29 Apr 2026 06:30:13 +0000 Subject: [PATCH] fix(chat): add missing chatTtsToggle button to prevent null reference error The chat.js init() template did not include #chatTtsToggle, causing a runtime TypeError when hasTTS was true. Added the toggle button inside .chat-header-actions, matching chat-public.js structure. Regenerated chat.min.js. --- pos/static/js/chat.js | 5 ++++- pos/static/js/chat.min.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pos/static/js/chat.js b/pos/static/js/chat.js index ddcaac7..59a89d4 100644 --- a/pos/static/js/chat.js +++ b/pos/static/js/chat.js @@ -32,7 +32,10 @@ panel.innerHTML = `

Asistente IA — Buscar partes

- +
+ ${hasTTS ? '' : ''} + +
Hola, soy el asistente de Nexus. Dime que refaccion necesitas y te ayudo a encontrarla.
diff --git a/pos/static/js/chat.min.js b/pos/static/js/chat.min.js index f11e8cf..15a8217 100644 --- a/pos/static/js/chat.min.js +++ b/pos/static/js/chat.min.js @@ -1 +1 @@ -!function(){"use strict";let e=!1,t=!1,n=!1,a=null,s=!0,i=null;const c=[],o="webkitSpeechRecognition"in window||"SpeechRecognition"in window,r="speechSynthesis"in window;function l(){const e=document.createElement("button");e.className="chat-fab",e.id="chatFab",e.title="Asistente IA",e.innerHTML="💬",e.setAttribute("aria-label","Abrir asistente IA");const t=document.createElement("div");t.className="chat-panel",t.id="chatPanel",t.innerHTML=`\n
\n

Asistente IA — Buscar partes

\n \n
\n
\n
Hola, soy el asistente de Nexus. Dime que refaccion necesitas y te ayudo a encontrarla.
\n
\n \n
\n
\n
\n \n \n \n ${o?'':""}\n \n
\n `,document.body.appendChild(e),document.body.appendChild(t),e.addEventListener("click",p),document.getElementById("chatClose").addEventListener("click",p),document.getElementById("chatSend").addEventListener("click",y),document.getElementById("chatInput").addEventListener("keydown",(function(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),y())})),document.getElementById("chatCam").addEventListener("click",(function(){document.getElementById("chatImageInput").click()})),document.getElementById("chatImageInput").addEventListener("change",h),o&&document.getElementById("chatMic").addEventListener("click",d),r&&document.getElementById("chatTtsToggle").addEventListener("click",u),document.getElementById("chatClose").addEventListener("click",(function(){r&&m()})),document.getElementById("chatInput").addEventListener("input",(function(){this.style.height="auto",this.style.height=Math.min(this.scrollHeight,80)+"px"}))}function d(){n?function(){a&&(a.abort(),a=null);n=!1;const e=document.getElementById("chatMic");e&&e.classList.remove("listening")}():function(){const e=window.SpeechRecognition||window.webkitSpeechRecognition;if(!e)return;a=new e,a.lang="es-MX",a.continuous=!1,a.interimResults=!0;const t=document.getElementById("chatInput"),s=document.getElementById("chatMic"),i=t.placeholder;a.onstart=function(){n=!0,s.classList.add("listening"),t.placeholder="Escuchando...",t.value=""},a.onresult=function(e){let n="",a="";for(let t=e.resultIndex;t5242880)return void f("La imagen es muy grande (max 5MB).","ai");const a=new FileReader;a.onload=function(e){const n=document.getElementById("chatMessages"),a=document.getElementById("chatTyping"),s=document.createElement("div");s.className="chat-msg user chat-msg-image",s.innerHTML='Foto de parteIdentificar esta parte',n.insertBefore(s,a),I();var i=e.target.result,o="Identifica esta parte automotriz y sugiere terminos de busqueda.";c.push({role:"user",content:o}),c.length>20&&c.splice(0,2),t=!0,document.getElementById("chatSend").disabled=!0,b(!0);var r=g();fetch("/pos/api/chat",{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer "+r},body:JSON.stringify({message:o,image:i,history:c.slice(-10)})}).then((function(e){return e.json()})).then((function(e){const t=e.response||"No pude identificar la parte. Intenta describirla con texto.";f(t,"ai"),c.push({role:"assistant",content:t}),e.vehicle&&e.vehicle.brand_id&&v(e.vehicle),e.search_results&&e.search_results.length>0&&E(e.search_results)})).catch((function(e){f("Error al procesar imagen: "+e.message,"ai")})).finally((function(){t=!1,document.getElementById("chatSend").disabled=!1,b(!1)}))},a.readAsDataURL(n)}function p(){e=!e;const t=document.getElementById("chatPanel"),n=document.getElementById("chatFab");e?(t.classList.add("open"),n.style.display="none",document.getElementById("chatInput").focus()):(t.classList.remove("open"),n.style.display="flex")}function g(){return window.__pos&&window.__pos.token?window.__pos.token:localStorage.getItem("pos_token")||""}async function y(){if(t)return;const e=document.getElementById("chatInput"),n=e.value.trim();if(n){e.value="",e.style.height="auto",f(n,"user"),c.push({role:"user",content:n}),c.length>20&&c.splice(0,2),t=!0,document.getElementById("chatSend").disabled=!0,b(!0);try{const e=g(),t=await fetch("/pos/api/chat",{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer "+e},body:JSON.stringify({message:n,history:c.slice(-10)})}),a=await t.json();if(!t.ok)return void f("Error: "+(a.error||t.statusText),"ai");const o=a.response||"Sin respuesta.";f(o,"ai"),c.push({role:"assistant",content:o}),function(e){r&&s&&e&&(m(),i=new SpeechSynthesisUtterance(e),i.lang="es-MX",i.rate=1.1,i.pitch=1,window.speechSynthesis.speak(i))}(o),a.vehicle&&a.vehicle.brand_id&&v(a.vehicle),a.search_results&&a.search_results.length>0&&E(a.search_results)}catch(e){f("Error de conexion: "+e.message,"ai")}finally{t=!1,document.getElementById("chatSend").disabled=!1,b(!1)}}}function f(e,t){const n=document.getElementById("chatMessages"),a=document.getElementById("chatTyping"),s=document.createElement("div");s.className="chat-msg "+t,s.textContent=e,n.insertBefore(s,a),I()}function v(e){const t=document.getElementById("chatMessages"),n=document.getElementById("chatTyping"),a=document.createElement("div");a.className="chat-vehicle-banner";let s=""+B(e.brand||"")+" "+B(e.model||"")+"";e.year&&(s+=" "+e.year),e.mye_options&&e.mye_options.length>0&&(s+="
Motorizaciones encontradas:",e.mye_options.forEach((function(e){s+="
• "+B(e.engine),e.trim&&(s+=" ("+B(e.trim)+")")}))),a.innerHTML=s,t.insertBefore(a,n),I()}function E(e){const t=document.getElementById("chatMessages"),n=document.getElementById("chatTyping"),a=document.createElement("div");a.className="chat-parts",e.slice(0,8).forEach((function(e){const t=document.createElement("div");t.className="chat-part-card";const n="local"===e.source,s=e.local_stock||0,i=s>0?"in-stock":"",c=s>0?s+" en stock":"Sin stock local",o=e.name_es||e.name_part||"",r=e.oem_part_number||e.part_number||"",l=e.brand||"",d=e.price_1?"$"+parseFloat(e.price_1).toFixed(2):"",u=n?'MI INVENTARIO':'CATÁLOGO';t.innerHTML='
'+B(r)+u+(d?" — "+d:"")+'
'+B(o)+(l?' ('+B(l)+")":"")+'
'+B(c)+"
",t.addEventListener("click",(function(){e.id_part&&"function"==typeof window.openPartDetail&&(window.openPartDetail(e.id_part),p())})),a.appendChild(t)})),t.insertBefore(a,n),I()}function b(e){const t=document.getElementById("chatTyping");t&&t.classList.toggle("visible",e),e&&I()}function I(){const e=document.getElementById("chatMessages");e&&(e.scrollTop=e.scrollHeight)}function B(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",l):l()}(); \ No newline at end of file +!function(){"use strict";let e=!1,t=!1,n=!1,a=null,s=!0,c=null;const i=[],o="webkitSpeechRecognition"in window||"SpeechRecognition"in window,r="speechSynthesis"in window;function l(){const e=document.createElement("button");e.className="chat-fab",e.id="chatFab",e.title="Asistente IA",e.innerHTML="💬",e.setAttribute("aria-label","Abrir asistente IA");const t=document.createElement("div");t.className="chat-panel",t.id="chatPanel",t.innerHTML=`\n
\n

Asistente IA — Buscar partes

\n
\n ${r?'':""}\n \n
\n
\n
\n
Hola, soy el asistente de Nexus. Dime que refaccion necesitas y te ayudo a encontrarla.
\n
\n \n
\n
\n
\n \n \n \n ${o?'':""}\n \n
\n `,document.body.appendChild(e),document.body.appendChild(t),e.addEventListener("click",p),document.getElementById("chatClose").addEventListener("click",p),document.getElementById("chatSend").addEventListener("click",y),document.getElementById("chatInput").addEventListener("keydown",(function(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),y())})),document.getElementById("chatCam").addEventListener("click",(function(){document.getElementById("chatImageInput").click()})),document.getElementById("chatImageInput").addEventListener("change",h),o&&document.getElementById("chatMic").addEventListener("click",d),r&&document.getElementById("chatTtsToggle").addEventListener("click",u),document.getElementById("chatClose").addEventListener("click",(function(){r&&m()})),document.getElementById("chatInput").addEventListener("input",(function(){this.style.height="auto",this.style.height=Math.min(this.scrollHeight,80)+"px"}))}function d(){n?function(){a&&(a.abort(),a=null);n=!1;const e=document.getElementById("chatMic");e&&e.classList.remove("listening")}():function(){const e=window.SpeechRecognition||window.webkitSpeechRecognition;if(!e)return;a=new e,a.lang="es-MX",a.continuous=!1,a.interimResults=!0;const t=document.getElementById("chatInput"),s=document.getElementById("chatMic"),c=t.placeholder;a.onstart=function(){n=!0,s.classList.add("listening"),t.placeholder="Escuchando...",t.value=""},a.onresult=function(e){let n="",a="";for(let t=e.resultIndex;t5242880)return void f("La imagen es muy grande (max 5MB).","ai");const a=new FileReader;a.onload=function(e){const n=document.getElementById("chatMessages"),a=document.getElementById("chatTyping"),s=document.createElement("div");s.className="chat-msg user chat-msg-image",s.innerHTML='Foto de parteIdentificar esta parte',n.insertBefore(s,a),I();var c=e.target.result,o="Identifica esta parte automotriz y sugiere terminos de busqueda.";i.push({role:"user",content:o}),i.length>20&&i.splice(0,2),t=!0,document.getElementById("chatSend").disabled=!0,b(!0);var r=g();fetch("/pos/api/chat",{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer "+r},body:JSON.stringify({message:o,image:c,history:i.slice(-10)})}).then((function(e){return e.json()})).then((function(e){const t=e.response||"No pude identificar la parte. Intenta describirla con texto.";f(t,"ai"),i.push({role:"assistant",content:t}),e.vehicle&&e.vehicle.brand_id&&v(e.vehicle),e.search_results&&e.search_results.length>0&&E(e.search_results)})).catch((function(e){f("Error al procesar imagen: "+e.message,"ai")})).finally((function(){t=!1,document.getElementById("chatSend").disabled=!1,b(!1)}))},a.readAsDataURL(n)}function p(){e=!e;const t=document.getElementById("chatPanel"),n=document.getElementById("chatFab");e?(t.classList.add("open"),n.style.display="none",document.getElementById("chatInput").focus()):(t.classList.remove("open"),n.style.display="flex")}function g(){return window.__pos&&window.__pos.token?window.__pos.token:localStorage.getItem("pos_token")||""}async function y(){if(t)return;const e=document.getElementById("chatInput"),n=e.value.trim();if(n){e.value="",e.style.height="auto",f(n,"user"),i.push({role:"user",content:n}),i.length>20&&i.splice(0,2),t=!0,document.getElementById("chatSend").disabled=!0,b(!0);try{const e=g(),t=await fetch("/pos/api/chat",{method:"POST",headers:{"Content-Type":"application/json",Authorization:"Bearer "+e},body:JSON.stringify({message:n,history:i.slice(-10)})}),a=await t.json();if(!t.ok)return void f("Error: "+(a.error||t.statusText),"ai");const o=a.response||"Sin respuesta.";f(o,"ai"),i.push({role:"assistant",content:o}),function(e){r&&s&&e&&(m(),c=new SpeechSynthesisUtterance(e),c.lang="es-MX",c.rate=1.1,c.pitch=1,window.speechSynthesis.speak(c))}(o),a.vehicle&&a.vehicle.brand_id&&v(a.vehicle),a.search_results&&a.search_results.length>0&&E(a.search_results)}catch(e){f("Error de conexion: "+e.message,"ai")}finally{t=!1,document.getElementById("chatSend").disabled=!1,b(!1)}}}function f(e,t){const n=document.getElementById("chatMessages"),a=document.getElementById("chatTyping"),s=document.createElement("div");s.className="chat-msg "+t,s.textContent=e,n.insertBefore(s,a),I()}function v(e){const t=document.getElementById("chatMessages"),n=document.getElementById("chatTyping"),a=document.createElement("div");a.className="chat-vehicle-banner";let s=""+B(e.brand||"")+" "+B(e.model||"")+"";e.year&&(s+=" "+e.year),e.mye_options&&e.mye_options.length>0&&(s+="
Motorizaciones encontradas:",e.mye_options.forEach((function(e){s+="
• "+B(e.engine),e.trim&&(s+=" ("+B(e.trim)+")")}))),a.innerHTML=s,t.insertBefore(a,n),I()}function E(e){const t=document.getElementById("chatMessages"),n=document.getElementById("chatTyping"),a=document.createElement("div");a.className="chat-parts",e.slice(0,8).forEach((function(e){const t=document.createElement("div");t.className="chat-part-card";const n="local"===e.source,s=e.local_stock||0,c=s>0?"in-stock":"",i=s>0?s+" en stock":"Sin stock local",o=e.name_es||e.name_part||"",r=e.oem_part_number||e.part_number||"",l=e.brand||"",d=e.price_1?"$"+parseFloat(e.price_1).toFixed(2):"",u=n?'MI INVENTARIO':'CATÁLOGO';t.innerHTML='
'+B(r)+u+(d?" — "+d:"")+'
'+B(o)+(l?' ('+B(l)+")":"")+'
'+B(i)+"
",t.addEventListener("click",(function(){e.id_part&&"function"==typeof window.openPartDetail&&(window.openPartDetail(e.id_part),p())})),a.appendChild(t)})),t.insertBefore(a,n),I()}function b(e){const t=document.getElementById("chatTyping");t&&t.classList.toggle("visible",e),e&&I()}function I(){const e=document.getElementById("chatMessages");e&&(e.scrollTop=e.scrollHeight)}function B(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",l):l()}(); \ No newline at end of file