// diag-app.jsx — Orquesta el flujo del diagnóstico + persistencia en localStorage. const STORAGE = 'nl360_diagnostico_v1'; const EJES = window.DIAG_EJES; function loadState() { try { const raw = localStorage.getItem(STORAGE); if (raw) return JSON.parse(raw); } catch (e) {} return null; } function defaultTarget(cur) { return Math.max(3, Math.min(5, Math.round(cur) + 1)); } function App() { const saved = loadState(); const [step, setStep] = React.useState(saved?.step ?? 0); // 0 intro · 1-8 ejes · 9 metas · 10 datos · 11 results const [answers, setAnswers] = React.useState(saved?.answers ?? {}); const [targets, setTargets] = React.useState(saved?.targets ?? {}); const [data, setData] = React.useState(saved?.data ?? { nombre: '', email: '', telefono: '' }); const [hint, setHint] = React.useState(false); const [menuOpen, setMenuOpen] = React.useState(false); let resultsRec = null, resultsGrowth = null; // persist React.useEffect(() => { try { localStorage.setItem(STORAGE, JSON.stringify({ step, answers, targets, data })); } catch (e) {} }, [step, answers, targets, data]); // scroll top on step change React.useEffect(() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }, [step]); const setField = (k, v) => setData(d => ({ ...d, [k]: v })); const answer = (ejeKey, qi, val) => { setAnswers(a => { const arr = (a[ejeKey] || []).slice(); arr[qi] = val; return { ...a, [ejeKey]: arr }; }); }; const setTarget = (k, v) => setTargets(t => ({ ...t, [k]: v })); const scores = window.diagBuildScores(answers, targets); // ---- navigation ---- const ejeComplete = (ej) => { const arr = answers[ej.key] || []; return arr.filter(v => typeof v === 'number').length === ej.q.length; }; const goNextFromEje = (idx) => { const ej = EJES[idx]; if (!ejeComplete(ej)) { setHint(true); // shake unanswered requestAnimationFrame(() => { const el = document.querySelector('.q-card.pending-hint'); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' }); }); return; } setHint(false); setStep(s => s + 1); }; const enterMetas = () => { // initialize any unset targets to a sensible default above current setTargets(t => { const next = { ...t }; scores.forEach(s => { if (next[s.key] == null) next[s.key] = defaultTarget(s.current); }); return next; }); }; const restart = () => { if (!confirm('¿Borrar tus respuestas y empezar de nuevo?')) return; try { localStorage.removeItem(STORAGE); } catch (e) {} setStep(0); setAnswers({}); setTargets({}); setData({ nombre: '', email: '', telefono: '' }); setHint(false); }; // progress for top bar const answeredTotal = EJES.reduce((acc, e) => acc + (answers[e.key] || []).filter(v => typeof v === 'number').length, 0); let progress = 0, stepLabel = ''; if (step === 0) { progress = 0; stepLabel = 'Inicio'; } else if (step >= 1 && step <= 8) { progress = (answeredTotal / 40) * 0.8; stepLabel = `Eje ${EJES[step-1].n} / 08`; } else if (step === 9) { progress = 0.86; stepLabel = 'Metas'; } else if (step === 10) { progress = 0.94; stepLabel = 'Tus datos'; } else { progress = 1; stepLabel = 'Resultados'; } // ---- render current screen ---- let screen; if (step === 0) { screen = setStep(1)} />; } else if (step >= 1 && step <= 8) { const idx = step - 1; screen = ( { setHint(false); setStep(s => s - 1); }} onNext={() => goNextFromEje(idx)} /> ); } else if (step === 9) { screen = ( setStep(8)} onNext={() => setStep(10)} /> ); } else if (step === 10) { screen = ( setStep(9)} onSubmit={() => setStep(11)} /> ); } else { const rec = window.diagRecommend(scores); const growth = window.diagBuildGrowth(scores, rec.program, rec.estWeeks); resultsRec = rec; resultsGrowth = growth; screen = ; } // initialize metas targets when arriving at step 9 React.useEffect(() => { if (step === 9) enterMetas(); /* eslint-disable-next-line */ }, [step]); return (