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
1 line
3.1 KiB
JavaScript
1 line
3.1 KiB
JavaScript
!function(){"use strict";window.NexusNative={isNative:"undefined"!=typeof Capacitor,_scanStream:null,_scanVideo:null,async scanBarcode(){if(this.isNative)try{const{Camera:e}=await import("@capacitor/camera");return await e.getPhoto({quality:90,resultType:"base64"})}catch(e){return null}return"BarcodeDetector"in window?new Promise((async e=>{try{const t=await navigator.mediaDevices.getUserMedia({video:{facingMode:"environment",width:{ideal:1280},height:{ideal:720}}});this._scanStream=t;const a=document.createElement("div");a.id="barcode-scan-overlay",a.style.cssText="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);z-index:99999;display:flex;flex-direction:column;align-items:center;justify-content:center;";const i=document.createElement("video");i.autoplay=!0,i.playsInline=!0,i.style.cssText="width:90%;max-width:500px;border-radius:12px;border:3px solid #F5A623;",i.srcObject=t,this._scanVideo=i;const o=document.createElement("p");o.textContent="Apunta al codigo de barras...",o.style.cssText="color:#fff;font-size:16px;margin-top:16px;font-family:sans-serif;";const s=document.createElement("button");s.textContent="Cancelar",s.style.cssText="margin-top:16px;padding:10px 24px;background:#F5A623;color:#000;border:none;border-radius:6px;font-size:15px;cursor:pointer;font-weight:bold;",s.onclick=()=>{this.stopScan(),a.remove(),e(null)},a.appendChild(i),a.appendChild(o),a.appendChild(s),document.body.appendChild(a);const n=new BarcodeDetector({formats:["ean_13","ean_8","code_128","code_39","qr_code","upc_a","upc_e"]}),r=async()=>{if(this._scanStream){try{const t=await n.detect(i);if(t.length>0){const i=t[0].rawValue;return o.textContent="Codigo detectado: "+i,o.style.color="#4CAF50",void setTimeout((()=>{this.stopScan(),a.remove(),e(i)}),400)}}catch(e){}requestAnimationFrame(r)}};i.onloadedmetadata=()=>{i.play(),requestAnimationFrame(r)}}catch(t){console.error("Camera access error:",t),alert("No se pudo acceder a la camara: "+t.message),e(null)}})):(alert("Tu navegador no soporta escaneo de codigos de barras. Usa Chrome 83+ o un dispositivo movil."),null)},stopScan(){this._scanStream&&(this._scanStream.getTracks().forEach((e=>e.stop())),this._scanStream=null),this._scanVideo=null;var e=document.getElementById("barcode-scan-overlay");e&&e.remove()},async registerPush(){if(!this.isNative)return null;try{const{PushNotifications:e}=await import("@capacitor/push-notifications");"granted"===(await e.requestPermissions()).receive&&await e.register(),e.addListener("registration",(e=>{console.log("Push token:",e.value)})),e.addListener("pushNotificationReceived",(e=>{console.log("Push received:",e)}))}catch(e){console.log("Push not available:",e)}},async vibrate(){if(this.isNative)try{const{Haptics:e,ImpactStyle:t}=await import("@capacitor/haptics");await e.impact({style:t.Light})}catch(e){}},async setupStatusBar(){if(this.isNative)try{const{StatusBar:e,Style:t}=await import("@capacitor/status-bar");await e.setStyle({style:t.Dark}),await e.setBackgroundColor({color:"#0d0d0d"})}catch(e){}}},window.NexusNative.isNative&&(window.NexusNative.setupStatusBar(),window.NexusNative.registerPush())}(); |