import React, { useState, useEffect, useRef, useCallback } from 'react'; import { ComposedChart, Area, Line, XAxis, YAxis, CartesianGrid, ReferenceArea, ReferenceLine, ResponsiveContainer, } from 'recharts'; // ── Fake demo data ────────────────────────────────────────────────────────── const STEP1_CARDS = ['Bajo', 'Medio', 'Alto', 'Perfecto']; const STEP1_BLANKS = [3, 1, 4]; // huecos asimétricos entre cartas const STEP2_TERMS = [ { name: 'Bajo', xVal: 0.08, mf: { supportStart: 0.00, coreStart: 0.00, coreEnd: 0.06, supportEnd: 0.30 } }, { name: 'Medio', xVal: 0.38, mf: { supportStart: 0.18, coreStart: 0.38, coreEnd: 0.38, supportEnd: 0.59 } }, // pico/triángulo { name: 'Alto', xVal: 0.65, mf: { supportStart: 0.52, coreStart: 0.60, coreEnd: 0.69, supportEnd: 0.77 } }, { name: 'Perfecto', xVal: 0.92, mf: { supportStart: 0.74, coreStart: 0.88, coreEnd: 1.00, supportEnd: 1.00 } }, ]; const STEP2_COLORS = ['#ef4444', '#f59e0b', '#10b981', '#3b82f6']; // Igual que interpolateY en useGraphData.js: // · Zona buffer justo fuera del soporte → 0 (ancla la línea en y=0) // · Más allá del buffer → null (corte, sin línea horizontal) const TRAP_BUF = 1.1e-4; function trapVal(x, s0, c0, c1, s1) { if (x < s0 - TRAP_BUF || x > s1 + TRAP_BUF) return null; if (x < s0 || x > s1) return 0; if (x >= c0 && x <= c1) return 1; if (x < c0 && c0 > s0) return (x - s0) / (c0 - s0); if (x > c1 && s1 > c1) return (s1 - x) / (s1 - c1); return 0; } // Solo 'Alto' es IT2 (tiene subescala). LMF es triángulo → banda "lente" visible. const STEP3_TERMS = [ { name: 'Bajo', color: '#ef4444', type: 't1', pts: [0.00, 0.00, 0.06, 0.30] }, { name: 'Medio', color: '#f59e0b', type: 't1', pts: [0.18, 0.38, 0.38, 0.59] }, { name: 'Alto', color: '#10b981', type: 't2', u: [0.49, 0.57, 0.71, 0.81], l: [0.56, 0.64, 0.64, 0.76] }, { name: 'Perfecto', color: '#3b82f6', type: 't1', pts: [0.74, 0.88, 1.00, 1.00] }, ]; // Puntos clave del trapecio (piezas lineales → basta con vértices, como en el paso 2). // Recharts interpola el trazo entre ellos con animación fluida. function getTermLineData(term) { const name = term.name; if (term.type === 't1') { const [s0, c0, c1, s1] = term.pts; const xs = new Set([s0, c0, c1, s1]); if (s0 <= 0.001) xs.add(s0 - TRAP_BUF); if (s1 >= 0.999) xs.add(s1 + TRAP_BUF); return Array.from(xs).sort((a, b) => a - b).map(x => ({ x, [name]: trapVal(x, s0, c0, c1, s1), })); } const xs = new Set([...term.u, ...term.l]); return Array.from(xs).sort((a, b) => a - b).map(x => { const upper = trapVal(x, ...term.u); const lower = trapVal(x, ...term.l); return { x, [`${name}_upper`]: upper, [`${name}_lower`]: lower, [`${name}_range`]: (lower === null && upper === null) ? null : [lower ?? 0, upper ?? 0], }; }); } const STEP_LABELS = [ { n: 1, label: 'Escala' }, { n: 2, label: 'Modelado' }, { n: 3, label: 'Espectro IT2' }, ]; // ── Step sub-components ───────────────────────────────────────────────────── function Step1Content({ count }) { const done = count >= STEP1_CARDS.length; return (

Criterio: Calidad Investigadora

{STEP1_CARDS.map((name, i) => ( {i > 0 && (
×{STEP1_BLANKS[i - 1]}
)}
{i + 1} {i + 1} {name}
))}
✓ {STEP1_CARDS.length} niveles definidos
); } function Step2Content({ count }) { const visibleTerms = STEP2_TERMS.slice(0, count); const activeIndex = count - 1; const showSubscale = count >= 3; return (
{STEP2_TERMS.map((term, i) => { const color = STEP2_COLORS[i % STEP2_COLORS.length]; const isVisible = i < count; const isActive = i === activeIndex; return ( {term.name} {i === 2 && showSubscale && ( IT2 )} ); })}
{visibleTerms.map((term, i) => { const color = STEP2_COLORS[i % STEP2_COLORS.length]; const isActive = i === activeIndex; return ( ); })} {visibleTerms.map((term, i) => { const color = STEP2_COLORS[i % STEP2_COLORS.length]; const isActive = i === activeIndex; return ( ); })} {visibleTerms.map((term, i) => { const color = STEP2_COLORS[i % STEP2_COLORS.length]; const isActive = i === activeIndex; const trapezeData = [ { x: term.mf.supportStart, y: 0 }, { x: term.mf.coreStart, y: 1 }, { x: term.mf.coreEnd, y: 1 }, { x: term.mf.supportEnd, y: 0 }, ]; return ( ); })}
{/* Mini SubscaleModal inline */}
Diseñar Subescala · Alto · Pendiente Descendente
1
MÍN 2
MÁX 5
¿Dudas? Rango ✓
2
CARTAS 3
Distancia exacta
3
); } function Step3Content({ count }) { return (

Espectro difuso · Calidad Investigadora

{STEP3_TERMS.slice(0, count).map((term, i) => { const isNewest = i === count - 1; const data = getTermLineData(term); return ( {term.type === 't1' ? ( ) : ( <> )} ); })}
{STEP3_TERMS.map((term, i) => (
{term.name} {term.type === 't2' && i < count && ( IT2 )}
))}
); } // ── Main component ─────────────────────────────────────────────────────────── export default function AuthDemoPanel() { const [step, setStep] = useState(1); const [count, setCount] = useState(0); const [fading, setFading] = useState(false); const innerTimerRef = useRef(null); const transitionTo = useCallback((nextStep) => { if (innerTimerRef.current) clearTimeout(innerTimerRef.current); setFading(true); innerTimerRef.current = setTimeout(() => { setStep(nextStep); setCount(0); setFading(false); }, 440); }, []); useEffect(() => { let timeout; if (step === 1) { if (count < STEP1_CARDS.length) { timeout = setTimeout(() => setCount(c => c + 1), 580); } else { timeout = setTimeout(() => transitionTo(2), 950); } } else if (step === 2) { if (count < STEP2_TERMS.length) { timeout = setTimeout(() => setCount(c => c + 1), 920); } else { timeout = setTimeout(() => transitionTo(3), 1300); } } else if (step === 3) { if (count < STEP3_TERMS.length) { timeout = setTimeout(() => setCount(c => c + 1), 920); } else { timeout = setTimeout(() => transitionTo(1), 2800); } } return () => clearTimeout(timeout); }, [step, count, transitionTo]); useEffect(() => { return () => { if (innerTimerRef.current) clearTimeout(innerTimerRef.current); }; }, []); return (
{/* Step breadcrumb */}
{STEP_LABELS.map((s, i) => (
s.n ? 'bg-emerald-500 text-white' : 'bg-slate-200 text-slate-400'}`}> {step > s.n ? '✓' : s.n} s.n ? 'text-emerald-600' : 'text-slate-400'}`}> {s.label}
{i < STEP_LABELS.length - 1 && ( )}
))} En vivo
{step === 1 && } {step === 2 && } {step === 3 && }
); }