- Agrega TTS (speechSynthesis) a chat.js del POS para leer respuestas IA - Copia lógica de voz completa (STT + TTS) a dashboard/chat-public.js - Extiende estilos TTS en chat.css y chat-public.css - Agrega chat widget a 13 templates POS que no lo tenían - Corrige duplicado de chat.css en diagrams.html - Minifica assets actualizados - 73/73 tests pasan
1 line
6.0 KiB
JavaScript
1 line
6.0 KiB
JavaScript
!function(){"use strict";var e=!1,t=!1,n=!1,a=null,s=[],c=!0,i=null,o="webkitSpeechRecognition"in window||"SpeechRecognition"in window,r="speechSynthesis"in window;function l(){var e=document.createElement("button");e.className="chat-fab",e.id="chatFab",e.title="Asistente IA",e.innerHTML="💬",e.setAttribute("aria-label","Abrir asistente IA");var t=document.createElement("div");t.className="chat-panel",t.id="chatPanel",t.innerHTML='<div class="chat-header"><h3>Asistente — Buscar partes</h3><div class="chat-header-actions">'+(r?'<button class="chat-tts-toggle" id="chatTtsToggle" aria-label="Activar lectura de respuestas" title="Activar lectura de respuestas">🔊</button>':"")+'<button class="chat-header-close" id="chatClose" aria-label="Cerrar">×</button></div></div><div class="chat-messages" id="chatMessages"><div class="chat-msg ai">Hola, soy el asistente de Nexus Autoparts. Dime que refaccion buscas y te ayudo a encontrarla en el catalogo.</div><div class="chat-typing" id="chatTyping"><span></span><span></span><span></span></div></div><div class="chat-input-area"><textarea class="chat-input" id="chatInput" placeholder="Ej: Balatas para Tsuru 2015..." rows="1"></textarea>'+(o?'<button class="chat-mic-btn" id="chatMic" aria-label="Entrada por voz" title="Entrada por voz">🎤</button>':"")+'<button class="chat-send-btn" id="chatSend" aria-label="Enviar">▶</button></div>',document.body.appendChild(e),document.body.appendChild(t),e.addEventListener("click",m),document.getElementById("chatClose").addEventListener("click",m),document.getElementById("chatSend").addEventListener("click",p),document.getElementById("chatInput").addEventListener("keydown",(function(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),p())})),document.getElementById("chatInput").addEventListener("input",(function(){this.style.height="auto",this.style.height=Math.min(this.scrollHeight,80)+"px"})),o&&document.getElementById("chatMic").addEventListener("click",h),r&&document.getElementById("chatTtsToggle").addEventListener("click",d),document.getElementById("chatClose").addEventListener("click",(function(){r&&u()}))}function d(){c=!c;var e=document.getElementById("chatTtsToggle");e&&(e.classList.toggle("off",!c),e.setAttribute("title",c?"Desactivar lectura de respuestas":"Activar lectura de respuestas")),c||u()}function u(){r&&window.speechSynthesis.speaking&&window.speechSynthesis.cancel(),i=null}function h(){n?function(){a&&(a.abort(),a=null);n=!1;var e=document.getElementById("chatMic");e&&e.classList.remove("listening")}():function(){var e=window.SpeechRecognition||window.webkitSpeechRecognition;if(!e)return;(a=new e).lang="es-MX",a.continuous=!1,a.interimResults=!0;var 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="",u()},a.onresult=function(e){for(var n="",a="",s=e.resultIndex;s<e.results.length;s++)e.results[s].isFinal?a+=e.results[s][0].transcript:n+=e.results[s][0].transcript;t.value=a||n},a.onend=function(){n=!1,s.classList.remove("listening"),t.placeholder=c,a=null,t.value.trim()&&p()},a.onerror=function(e){var i,o;n=!1,s.classList.remove("listening"),t.placeholder=c,a=null,"no-speech"!==e.error&&"audio-capture"!==e.error&&"not-allowed"!==e.error||(i="No se detecto voz",(o=document.createElement("div")).className="chat-voice-toast",o.textContent=i,document.body.appendChild(o),setTimeout((function(){o.classList.add("visible")}),10),setTimeout((function(){o.classList.remove("visible"),setTimeout((function(){o.remove()}),300)}),2e3))},a.start()}()}function m(){e=!e;var 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 p(){if(!t){var e=document.getElementById("chatInput"),n=e.value.trim();n&&(e.value="",e.style.height="auto",v(n,"user"),s.push({role:"user",content:n}),s.length>20&&s.splice(0,2),t=!0,document.getElementById("chatSend").disabled=!0,g(!0),fetch("/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:n,history:s.slice(-10)})}).then((function(e){return e.json()})).then((function(e){if(e.error)v("Error: "+e.error,"ai");else{var t,n,a,o,l=e.response||"Sin respuesta.";v(l,"ai"),s.push({role:"assistant",content:l}),c&&function(e){r&&c&&e&&(u(),(i=new SpeechSynthesisUtterance(e)).lang="es-MX",i.rate=1.1,i.pitch=1,window.speechSynthesis.speak(i))}(l),e.search_results&&e.search_results.length>0&&(t=e.search_results,n=document.getElementById("chatMessages"),a=document.getElementById("chatTyping"),(o=document.createElement("div")).className="chat-parts",t.slice(0,8).forEach((function(e){var t=document.createElement("div");t.className="chat-part-card";var n=e.name_es||e.name_part||"",a=e.oem_part_number||e.part_number||"",s=e.brand||"";t.innerHTML='<div class="part-number">'+f(a)+'</div><div class="part-name">'+f(n)+(s?' <span style="color:var(--color-text-muted);">('+f(s)+")</span>":"")+"</div>",t.style.cursor="pointer",t.addEventListener("click",(function(){var e=document.getElementById("searchInput");e&&a&&(e.value=a,"function"==typeof window.doSearch&&window.doSearch(),m())})),o.appendChild(t)})),n.insertBefore(o,a),y())}})).catch((function(e){v("Error de conexion: "+e.message,"ai")})).finally((function(){t=!1,document.getElementById("chatSend").disabled=!1,g(!1)})))}}function v(e,t){var n=document.getElementById("chatMessages"),a=document.getElementById("chatTyping"),s=document.createElement("div");s.className="chat-msg "+t,s.textContent=e,n.insertBefore(s,a),y()}function g(e){var t=document.getElementById("chatTyping");t&&t.classList.toggle("visible",e),e&&y()}function y(){var e=document.getElementById("chatMessages");e&&(e.scrollTop=e.scrollHeight)}function f(e){if(!e)return"";var t=document.createElement("div");return t.textContent=e,t.innerHTML}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",l):l()}(); |