// ───────────────────────────────────────────────────────────── // main.jsx — App shell, state, routing, PDF wire-up // ───────────────────────────────────────────────────────────── const { useState, useEffect, useRef, useCallback } = React; // Detect if we are inside an iframe (e.g. embedded in WordPress). // Adds .is-embedded to so CSS can collapse `min-height: 100vh`, // which would otherwise force the body to fill the iframe and make // auto-resize stick to the tallest screen ever rendered. if (typeof window !== 'undefined' && window.parent && window.parent !== window) { try { document.body.classList.add('is-embedded'); } catch (e) { /* noop */ } } // Scrolls the diagnostic view to top. // When embedded inside an iframe (e.g. WordPress page), also notifies // the parent so the OUTER page scrolls to the iframe's top — otherwise // the user sees the bottom of the iframe after each view change. function scrollDiagToTop() { try { window.scrollTo({ top: 0, behavior: 'smooth' }); } catch (e) { /* noop */ } if (window.parent && window.parent !== window) { try { window.parent.postMessage({ type: 'alfa-diag:scroll-to-top' }, '*'); } catch (e) { /* cross-origin / silent */ } } } function App() { const [view, setView] = useState('inicio'); // inicio | encuesta | resultados | gracias const [areaIdx, setAreaIdx] = useState(0); const [respuestas, setRespuestas] = useState({}); const [resultados, setResultados] = useState(null); const [leadData, setLeadData] = useState(null); const [pdfBlob, setPdfBlob] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const [leadFormError, setLeadFormError] = useState(null); function handleStart() { setView('encuesta'); setAreaIdx(0); scrollDiagToTop(); } function handleAnswer(key, value) { setRespuestas(prev => ({...prev, [key]: value})); } function handleNextArea() { if (areaIdx === AREAS.length - 1) { // compute results const res = computeResultados(respuestas); setResultados(res); setView('resultados'); scrollDiagToTop(); } else { setAreaIdx(prev => prev + 1); scrollDiagToTop(); } } function handlePrevArea() { setAreaIdx(prev => Math.max(0, prev - 1)); scrollDiagToTop(); } async function handleLeadSubmit(form) { setLeadFormError(null); if (!form.nombre || !form.empresa || !form.cargo || !form.email || !form.email.includes('@')) { setLeadFormError('Por favor completa todos los campos con información válida.'); return; } setIsSubmitting(true); setLeadData(form); // Fire-and-forget submission to ActiveCampaign. // We do NOT await this — the PDF download must never be blocked // by network conditions or AC availability. if (typeof window.submitToActiveCampaign === 'function') { window.submitToActiveCampaign(form); } try { const blob = await generatePDF(form, resultados); setPdfBlob(blob); triggerDownload(blob, form); setView('gracias'); scrollDiagToTop(); } catch (err) { console.error(err); setLeadFormError('Hubo un error generando el PDF. Intenta de nuevo.'); } finally { setIsSubmitting(false); } } function handleReDownload() { if (pdfBlob && leadData) triggerDownload(pdfBlob, leadData); } // progress const totalQ = AREAS.length * 6; const respCount = Object.keys(respuestas).length; const pct = Math.round((respCount / totalQ) * 100); return ( <>
{view === 'encuesta' && (
EJE {String(areaIdx+1).padStart(2,'0')} / {String(AREAS.length).padStart(2,'0')} · {AREAS[areaIdx].nombre}
{pct}% completado
{AREAS.map((_, i) => ( ))}
)}
{view === 'inicio' && } {view === 'encuesta' && ( )} {view === 'resultados' && resultados && ( )} {view === 'gracias' && ( )}
); } // ─── Helpers ─── function computeResultados(respuestas) { const res = {}; let sumaGlobal = 0; AREAS.forEach((area, idx) => { let suma = 0; for (let i = 0; i < 6; i++) { suma += parseInt(respuestas[`${idx}_${i}`] || 1); } const promedio = suma / 6; res[idx+1] = { promedio, nivel: getNivel(promedio), nombre: area.nombre, corto: area.corto, id: area.id, }; sumaGlobal += promedio; }); res.globalProm = sumaGlobal / AREAS.length; res.global = getNivel(res.globalProm); return res; } function triggerDownload(blob, lead) { const url = URL.createObjectURL(blob); const a = document.createElement('a'); const safeEmpresa = (lead.empresa || 'empresa').replace(/[^a-z0-9]+/gi, '-').toLowerCase(); a.href = url; a.download = `diagnostico-madurez-${safeEmpresa}.pdf`; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 1000); } window.App = App; ReactDOM.createRoot(document.getElementById('root')).render();