Files
Autoparts-DB/pos/static/js/whatsapp.min.js
consultoria-as 21959f1b37 FASE 7d: Lazy Loading + Minificación + Auto-serve minified
Cambios implementados:

1. Lazy loading de imágenes:
   - catalog.js: loading="lazy" decoding="async" en part cards y detail panel
   - inventory.js: lazy loading en imagen de detalle de item

2. Minificación de assets:
   - scripts/minify-assets.sh: minifica JS (terser) y CSS para POS y Dashboard
   - 25 archivos .min.js + 5 .min.css generados en pos/static/
   - 14 archivos .min.js + 8 .min.css generados en dashboard/

3. Nginx auto-serve minified:
   - try_files $1.min.js antes de servir .js original
   - try_files $1.min.css antes de servir .css original
   - Transparente para los templates HTML (cero cambios en HTML)

4. Cache warming script:
   - scripts/warm_vehicle_cache.py: pobla Redis con vehicle info por batches
   - Mitiga DISTINCT ON + 4 JOINs sobre 2B filas
   - Corre en background, procesa ~1.5M parts

Tests: 73/73 pasando
2026-04-27 08:34:24 +00:00

1 line
8.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
!function(){"use strict";var e=localStorage.getItem("pos_token");if(e){var t=null,n=null,o=null,a=document.getElementById("convList"),s=document.getElementById("chatMessages"),i=document.getElementById("chatHeaderPhone"),r=document.getElementById("chatInput"),c=document.getElementById("sendBtn"),l=document.getElementById("newChatBtn"),d=document.getElementById("emptyState"),u=document.getElementById("chatPanel"),p=document.getElementById("statusDot"),v=document.getElementById("statusText"),m=document.getElementById("connectSection"),h=document.getElementById("messengerArea"),y=document.getElementById("qrImg"),f=document.getElementById("qrPlaceholder"),g=document.getElementById("connectBtn"),E=document.getElementById("disconnectBtn"),b=document.getElementById("refreshQrBtn");g.addEventListener("click",(function(){g.disabled=!0,g.textContent="Creando instancia...",B("POST","/connect").then((function(e){g.disabled=!1,g.textContent="Conectar WhatsApp",e.error?alert("Error: "+(e.error.message||e.error)):w()})).catch((function(){g.disabled=!1,g.textContent="Conectar WhatsApp",alert("Error de red al crear instancia")}))})),E.addEventListener("click",(function(){confirm("Desconectar WhatsApp?")&&B("POST","/logout").then((function(){k("close"),q()}))})),b.addEventListener("click",w),window.deleteAllConversations=function(){confirm("Borrar TODAS las conversaciones? Esta accion no se puede deshacer.")&&B("DELETE","/conversations").then((function(e){e.ok&&(t=null,u.style.display="none",d.style.display="",D())}))};var x="";c.addEventListener("click",P),r.addEventListener("keydown",(function(e){"Enter"!==e.key||e.shiftKey||(e.preventDefault(),P())})),l.addEventListener("click",(function(){var e=prompt("Numero de telefono (formato: 5215512345678):");e&&(O(e=e.replace(/[\s\-\+\(\)]/g,"")),D())}));var I=document.getElementById("sendQuoteBtn");I&&I.addEventListener("click",(function(){t?fetch("/pos/api/quotations?per_page=20",{headers:C()}).then((function(e){return e.json()})).then((function(e){var n=(e.data||[]).filter((function(e){return"active"===e.status}));if(0!==n.length){var o="Cotizaciones activas:\n";n.forEach((function(e){o+="#"+e.id+" — $"+e.total.toFixed(2)+" ("+(e.customer_name||e.source||"sin cliente")+")\n"}));var a=prompt(o+"\nEscribe el ID de la cotizacion a enviar:");a&&fetch("/pos/api/quotations/"+a,{headers:C()}).then((function(e){return e.json()})).then((function(e){if(e.error)alert("Error: "+e.error);else{var n=["📄 *COTIZACIÓN #"+e.id+"*",""];(e.items||[]).forEach((function(e,t){n.push(t+1+". "+e.name),n.push(" #"+e.part_number+" × "+e.quantity+" = $"+e.subtotal.toFixed(2))})),n.push("─────────────"),n.push("Subtotal: $"+e.subtotal.toFixed(2)),n.push("IVA: $"+e.tax_total.toFixed(2)),n.push("*TOTAL: $"+e.total.toFixed(2)+"*");var o=n.join("\n");B("POST","/send",{phone:t,message:o}).then((function(e){e.error?alert("Error enviando: "+e.error):(N(t),D())}))}}))}else alert("No hay cotizaciones activas. Crea una desde el POS (F4) o via WhatsApp.")})):alert("Selecciona una conversacion primero")})),A(),setInterval(A,3e4);try{var _=JSON.parse(atob(e.split(".")[1]));window.POS_USER={name:_.name||"Usuario",roleLabel:(_.role||"").charAt(0).toUpperCase()+(_.role||"").slice(1),initials:(_.name||"U").split(" ").map((function(e){return e[0]})).join("").slice(0,2).toUpperCase()}}catch(e){}}else window.location.href="/pos/login";function C(){return{Authorization:"Bearer "+e,"Content-Type":"application/json"}}function B(e,t,n){var o={method:e,headers:C()};return n&&(o.body=JSON.stringify(n)),fetch("/pos/api/whatsapp"+t,o).then((function(e){return 401===e.status&&(window.location.href="/pos/login"),e.json()}))}function S(e){var t=document.createElement("div");return t.textContent=e||"",t.innerHTML}function T(e){if(!e)return"";var t=new Date(e),n=new Date;return t.toDateString()===n.toDateString()?t.toLocaleTimeString("es-MX",{hour:"2-digit",minute:"2-digit"}):t.toLocaleDateString("es-MX",{day:"2-digit",month:"short"})+" "+t.toLocaleTimeString("es-MX",{hour:"2-digit",minute:"2-digit"})}function L(e){return e?13===e.length&&e.startsWith("521")?"+52 1 "+e.slice(3,5)+" "+e.slice(5,9)+" "+e.slice(9):12===e.length&&e.startsWith("52")?"+52 "+e.slice(2,4)+" "+e.slice(4,8)+" "+e.slice(8):"+"+e:""}function A(){B("GET","/status").then((function(e){k((e.instance||e).state||e.state||"close")})).catch((function(){k("close")}))}function k(e){"open"===e?(p.className="status-dot status-dot--ok",v.textContent="Conectado",m.style.display="none",h.style.display="flex",E.style.display="",g.style.display="none",D(),M()):"connecting"===e?(p.className="status-dot status-dot--warn",v.textContent="Escaneando QR...",m.style.display="flex",h.style.display="none",E.style.display="none",g.style.display="none",b.style.display=""):(p.className="status-dot status-dot--error",v.textContent="Desconectado",m.style.display="flex",h.style.display="none",E.style.display="none",g.style.display="",b.style.display="none",y.style.display="none",f.style.display="")}function w(){f.textContent="Generando QR...",B("GET","/qr").then((function(e){var t=e.qr||e.base64||e.qrcode||"";t?(y.src=t.startsWith("data:")?t:"data:image/png;base64,"+t,y.style.display="block",f.style.display="none",b.style.display="",k("connecting"),q(),o=setInterval((function(){B("GET","/status").then((function(e){"open"===((e.instance||e).state||e.state||"close")&&(k("open"),q(),D(),M())}))}),3e3)):e.instance&&"open"===e.instance.state||"open"===e.state?(k("open"),D()):(f.textContent="No se pudo generar el QR. Intenta de nuevo.",f.style.display="",y.style.display="none")})).catch((function(){f.textContent="Error al obtener QR"}))}function q(){o&&(clearInterval(o),o=null)}function D(){B("GET","/conversations").then((function(e){var n=e.conversations||[];if(0!==n.length){var o="";n.forEach((function(e){var n=e.phone===t,a="outgoing"===e.last_direction?"↗ ":"↙ ",s=e.contact_name||"";s||(s=e.phone.length>13||!/^(52|1|44|34)/.test(e.phone)?"Contacto WhatsApp":L(e.phone));o+='<div class="conv-item'+(n?" is-active":"")+'" data-phone="'+S(e.phone)+'"><div class="conv-item__phone">'+S(s)+'</div><div class="conv-item__preview">'+a+S(e.last_message||"(sin texto)")+'</div><div class="conv-item__time">'+T(e.last_at)+'</div><button class="conv-item__delete" data-del-phone="'+S(e.phone)+'" title="Borrar conversacion">&times;</button></div>'})),o+='<div style="padding:8px;text-align:center;"><button class="conv-delete-all" style="background:none;border:1px dashed var(--color-border,#444);color:var(--color-text-muted);padding:6px 12px;border-radius:6px;cursor:pointer;font-size:11px;" onclick="deleteAllConversations()">Borrar todas las conversaciones</button></div>',a.innerHTML=o,a.querySelectorAll(".conv-item").forEach((function(e){e.addEventListener("click",(function(t){if(!t.target.classList.contains("conv-item__delete")){var n=e.querySelector(".conv-item__phone")?e.querySelector(".conv-item__phone").textContent:"";O(e.getAttribute("data-phone"),n)}}))})),a.querySelectorAll(".conv-item__delete").forEach((function(e){e.addEventListener("click",(function(n){n.stopPropagation();var o=e.getAttribute("data-del-phone");confirm("Borrar conversacion con "+L(o)+"?")&&function(e){B("DELETE","/conversations/"+encodeURIComponent(e)).then((function(n){n.ok?(t===e&&(t=null,u.style.display="none",d.style.display=""),D()):alert("Error: "+(n.error||"unknown"))}))}(o)}))}))}else a.innerHTML='<div class="conv-empty">No hay conversaciones</div>'})).catch((function(){a.innerHTML='<div class="conv-empty">Error cargando conversaciones</div>'}))}function O(e,n){t=e;var o=e.length>13||!/^(52|1|44|34)/.test(e);x=n||"",i.textContent=x||(o?"Contacto WhatsApp":L(e)),d.style.display="none",u.style.display="flex",a.querySelectorAll(".conv-item").forEach((function(t){t.classList.toggle("is-active",t.getAttribute("data-phone")===e)})),N(e),M()}function N(e){B("GET","/conversations/"+encodeURIComponent(e)).then((function(e){!function(e){var t="";e.forEach((function(e){var n="outgoing"===e.direction?"msg-bubble--out":"msg-bubble--in",o=e.message_text||e.text||"",a=e.created_at||e.date||"";t+='<div class="msg-bubble '+n+'"><div class="msg-bubble__text">'+S(o).replace(/\n/g,"<br>")+'</div><div class="msg-bubble__meta">'+T(a)+"</div></div>"})),s.innerHTML=t||'<div class="chat-empty">Sin mensajes</div>',s.scrollTop=s.scrollHeight}(e.messages||[])}))}function P(){var e=r.value.trim();e&&t&&(r.value="",c.disabled=!0,B("POST","/send",{phone:t,message:e}).then((function(e){c.disabled=!1,e.error?alert("Error: "+e.error):(N(t),D())})).catch((function(){c.disabled=!1,alert("Error de red al enviar mensaje")})))}function M(){n&&clearInterval(n),n=setInterval((function(){t&&N(t),D()}),1e4)}}();