// ── CONFIGURACIÓN DE PLANTILLAS DE CLIENTES ── export const clientTemplates = { 'Esp': { 'Generico': 'images/AF Generico Esp.png', 'Claro': 'images/AF Claro Esp.png', 'Colgate': 'images/GLM Colgate Esp.png', 'KitchenAid': 'images/AF KitchenAid Esp.png', 'Kraft': 'images/AF Kraft Esp.png', 'Motorola': 'images/AF Motorola Esp.png', 'Nestle': 'images/AF Nestle Esp.png', 'P&G': 'images/AF P&G Esp.png', 'Philip Morris': 'images/AF Philip Morris Esp.png', 'Whirlpool': 'images/AF Whirlpool Esp.png' }, 'Ing': { 'Generico': 'images/AF Generico Ing.png', 'Claro': 'images/AF Claro Ing.png', 'Colgate': 'images/GLM Colgate Ing.png', 'KitchenAid': 'images/AF KitchenAid Ing.png', 'Kraft': 'images/AF Kraft Ing.png', 'Motorola': 'images/AF Motorola Ing.png', 'Nestle': 'images/AF Nestle Ing.png', 'P&G': 'images/AF P&G Ing.png', 'Philip Morris': 'images/AF Philip Morris Ing.png', 'Whirlpool': 'images/AF Whirlpool Ing.png' } }; // ── INYECTORES DINÁMICOS DE DEPENDENCIAS ── function loadScript(src, globalKey) { return new Promise((resolve) => { if (window[globalKey]) return resolve(window[globalKey]); const s = document.createElement('script'); s.src = src; s.onload = () => resolve(window[globalKey]); document.head.appendChild(s); }); } const getQRLib = () => loadScript('https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js', 'QRCode'); const getHtml2Canvas = () => loadScript('https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js', 'html2canvas'); // ── GENERADOR DE QR NATIVO (REACT RENDERING) ── export async function renderQRCode(employeeId, canvasElement) { if (!canvasElement) return; const text = (employeeId || '').trim(); const ctx = canvasElement.getContext('2d'); ctx.clearRect(0, 0, canvasElement.width, canvasElement.height); if (text.length <= 2) return; const QRCodeLib = await getQRLib(); const tmp = document.createElement('div'); tmp.style.display = 'none'; document.body.appendChild(tmp); new QRCodeLib(tmp, { text: `http://localhost:5173/employee/${text}`, width: 55, height: 55, colorDark: '#000000', colorLight: '#ffffff', correctLevel: QRCodeLib.CorrectLevel.M }); setTimeout(() => { const img = tmp.querySelector('img') || tmp.querySelector('canvas'); const drawIt = (src) => { const i = new Image(); i.onload = () => { ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, 55, 55); ctx.drawImage(i, 0, 0, 55, 55); if (tmp.parentNode) document.body.removeChild(tmp); }; i.src = src; }; if (img && img.tagName === 'CANVAS') { drawIt(img.toDataURL()); } else if (img) { if (img.complete) drawIt(img.src); else img.onload = () => drawIt(img.src); } else { if (tmp.parentNode) document.body.removeChild(tmp); } }, 50); } // ── ENGINE DE PROCESAMIENTO ULTRA MAX QUALITY (650x1004) ── export async function downloadIDCards(config) { const { name, role, selectedClient, language, photoSrc, baseUrl, qrCanvas, onStateChange } = config; if (onStateChange) onStateChange({ processing: true, text: 'Procesando...' }); const html2canvasLib = await getHtml2Canvas(); const cleanName = name.trim().replace(/\s+/g, '') || 'Empleado'; // Resolver rutas absolutas const frontBgUrl = `${baseUrl}images/AF GLM Frente.png`; const currentGroup = clientTemplates[language] || clientTemplates['Esp']; const backBgFile = currentGroup[selectedClient] || 'images/AF Generico Esp.png'; const backBgUrl = `${baseUrl}${backBgFile}`; // Sandbox virtual aislado const sandbox = document.createElement('div'); sandbox.style.position = 'fixed'; sandbox.style.top = '-9999px'; sandbox.style.left = '-9999px'; sandbox.style.width = '1400px'; document.body.appendChild(sandbox); const cardStyleBase = ` position: relative; width: 650px; height: 1004px; border-radius: 16px; background-size: cover; background-position: center; background-repeat: no-repeat; display: inline-block; margin-right: 50px; overflow: hidden; font-family: Arial, Helvetica, sans-serif; `; // 1. Frente Virtual en tamaño real const vFront = document.createElement('div'); vFront.style.cssText = cardStyleBase; vFront.style.backgroundImage = `url('${frontBgUrl}')`; let photoStyleHtml = `background: #e1e9ee; display: flex; align-items: center; justify-content: center;`; let innerPhotoContent = ``; if (photoSrc) { photoStyleHtml = ` background-image: url('${photoSrc}') !important; background-size: cover !important; background-position: center center !important; background-repeat: no-repeat !important; `; innerPhotoContent = ''; } vFront.innerHTML = `