/* ============================================================ APP SHELL — routing + estado + conexión API ============================================================ */ const { useState: useS, useEffect: useE } = React; const IHM = window.IH; const LS = { get(k, d) { try { const v = localStorage.getItem(k); return v ? JSON.parse(v) : d; } catch (e) { return d; } }, set(k, v) { try { localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} }, }; function emptyAnswers() { const o = {}; IHM.order.forEach(id => o[id] = Array(10).fill(0)); return o; } function App() { const [screen, setScreen] = useS(() => LS.get('ih_screen', 'welcome')); const [profile, setProfile] = useS(() => LS.get('ih_profile', {})); const [answers, setAnswers] = useS(() => LS.get('ih_answers', emptyAnswers())); const [block, setBlock] = useS(() => LS.get('ih_block', 0)); const [assessmentId, setAssessmentId] = useS(() => LS.get('ih_aid', null)); const [anonToken, setAnonToken] = useS(() => LS.get('ih_token', null)); const [result, setResult] = useS(null); const [adminUser, setAdminUser] = useS(null); const [reportFilters, setReportFilters] = useS(null); const [loading, setLoading] = useS(false); const [error, setError] = useS(null); useE(() => LS.set('ih_screen', screen), [screen]); useE(() => LS.set('ih_profile', profile), [profile]); useE(() => LS.set('ih_answers', answers), [answers]); useE(() => LS.set('ih_block', block), [block]); // Verifica sesión admin existente al montar useE(() => { IHA.me().then(u => setAdminUser(u)).catch(() => {}); }, []); const go = (s) => { window.scrollTo(0, 0); setScreen(s); }; const onAnswer = (id, idx, v) => { setAnswers(prev => { const next = { ...prev, [id]: [...(prev[id] || Array(10).fill(0))] }; next[id][idx] = v; return next; }); }; // Crea assessment + guarda perfil al confirmar datos generales const startEval = async () => { setLoading(true); setError(null); try { const { assessment_id, anon_token } = await IHA.guestStart(); setAssessmentId(assessment_id); setAnonToken(anon_token); LS.set('ih_aid', assessment_id); LS.set('ih_token', anon_token); await IHA.saveProfile(assessment_id, anon_token, { nombre: profile.nombre || '', area: profile.area || '', sucursal: profile.sucursal || '', puesto: profile.puesto || '', antiguedad: profile.antiguedad || '', }); go('eval'); } catch (e) { setError(e.message || 'Error al iniciar evaluación'); } finally { setLoading(false); } }; // Envía todas las respuestas al servidor y obtiene el resultado del scoring const finish = async () => { setLoading(true); setError(null); try { await IHA.saveAnswers(assessmentId, anonToken, answers); const res = await IHA.submit(assessmentId, anonToken); setResult(res); go('result'); } catch (e) { setError(e.message || 'Error al procesar resultados'); setLoading(false); } }; const restart = () => { setAnswers(emptyAnswers()); setBlock(0); setResult(null); setProfile({}); setAssessmentId(null); setAnonToken(null); LS.set('ih_aid', null); LS.set('ih_token', null); go('welcome'); }; const handleAdminLogin = (user) => { setAdminUser(user); go('exec'); }; const handleLogout = () => { IHA.logout().catch(() => {}); setAdminUser(null); go('welcome'); }; if (loading) { return (
Procesando…
{error &&
{error}
}
); } // Mapea el payload del API al shape que espera ScreenResult const resultProfile = result?.respondent ? { nombre: result.respondent.name, area: result.respondent.area, puesto: result.respondent.puesto, antiguedad: result.respondent.antiguedad } : profile; const resultScores = result?.scores || IHM.scoreAll(answers); switch (screen) { case 'welcome': return go('datos')} onExec={() => go('exec')} />; case 'datos': return ( <> setProfile(p => ({ ...p, [k]: v }))} onNext={startEval} onBack={() => go('welcome')} /> {error && (
{error}
)} ); case 'eval': return go('datos')} />; case 'result': return go('exec')} onPDF={() => window.print()} />; case 'exec': if (!adminUser) return go('welcome')} />; return go('welcome')} onLogout={handleLogout} onReport={(f) => { setReportFilters(f); go('report'); }} />; case 'report': return go('exec')} />; default: return go('datos')} onExec={() => go('exec')} />; } } ReactDOM.createRoot(document.getElementById('root')).render();