import React, { useState, useEffect, useRef } from 'react'; import CriterionInput from '../components/CriterionInput'; import CardEditor from '../components/CardEditor'; import BlankCardsCounter from '../components/BlankCardsCounter'; import AddLevelButton from '../components/AddLevelButton'; import Chart from '../components/membershipFunction/Chart'; import Controls from '../components/membershipFunction/Controls'; import { calculateValueFunction } from '../services/docService'; const COLORS = ['#ef4444', '#f59e0b', '#10b981', '#3b82f6', '#d946ef', '#06b6d4', '#8b5cf6', '#f43f5e', '#6366f1']; export default function AdvancedMode() { const [step, setStep] = useState(1); const [isLoading, setIsLoading] = useState(false); // Estados Fase 1 (Escala) const [criterionName, setCriterionName] = useState(''); const [levels, setLevels] = useState(['', '', '']); const [blankCards, setBlankCards] = useState([0, 0]); const [errors, setErrors] = useState({ criterion: false, levels: [] }); // Estado para controlar la lupa (Zoom) const [isZoomActive, setIsZoomActive] = useState(true); // Medición exacta con Refs const containerRef = useRef(null); const tableRef = useRef(null); const [dimensions, setDimensions] = useState({ container: 1000, table: 0 }); useEffect(() => { const updateMeasurements = () => { if (containerRef.current && tableRef.current) { setDimensions({ container: containerRef.current.offsetWidth, table: tableRef.current.scrollWidth }); } }; const timeoutId = setTimeout(updateMeasurements, 50); window.addEventListener('resize', updateMeasurements); return () => { clearTimeout(timeoutId); window.removeEventListener('resize', updateMeasurements); }; }, [levels, blankCards, step]); // Estados Fase 2 (Franjas) const [baseScale, setBaseScale] = useState({}); const [selectedTerm, setSelectedTerm] = useState(null); const [mfDefinitions, setMfDefinitions] = useState({}); // Manejadores de Escala const handleCriterionChange = (val) => { setCriterionName(val); if (errors.criterion) setErrors({ ...errors, criterion: false }); }; const handleLevelChange = (index, newValue) => { const newLevels = [...levels]; newLevels[index] = newValue; setLevels(newLevels); if (errors.levels[index]) setErrors({ ...errors, levels: errors.levels.map((e, i) => i === index ? false : e) }); }; const handleAddLevel = () => { setLevels([...levels, '']); setBlankCards([...blankCards, 0]); setErrors({ ...errors, levels: [...errors.levels, false] }); }; const handleRemoveLevel = (indexToRemove) => { if (levels.length <= 3) return; setLevels(levels.filter((_, i) => i !== indexToRemove)); setBlankCards(blankCards.filter((_, i) => i !== (indexToRemove === 0 ? 0 : indexToRemove - 1))); setErrors({ ...errors, levels: errors.levels.filter((_, i) => i !== indexToRemove) }); }; const handleBlankCardChange = (index, delta) => { const newCards = [...blankCards]; if (newCards[index] + delta >= 0) { newCards[index] += delta; setBlankCards(newCards); } }; const handleGenerateBaseScale = async () => { const newErrors = { criterion: !criterionName.trim(), levels: levels.map(l => !l.trim()) }; if (newErrors.criterion || newErrors.levels.includes(true)) { setErrors(newErrors); return alert("Por favor, rellena todos los campos."); } setIsLoading(true); try { const payloadBase = { criterion_name: criterionName.trim(), levels: levels.map(l => l.trim()), blank_cards: blankCards, references: { "0": 0, [(levels.length - 1).toString()]: 1 } }; const baseResult = await calculateValueFunction(payloadBase); setBaseScale(baseResult.values); const initialMfs = {}; Object.entries(baseResult.values).forEach(([name, value]) => { initialMfs[name] = { supportStart: value, coreStart: value, coreEnd: value, supportEnd: value }; }); setMfDefinitions(initialMfs); setSelectedTerm(Object.keys(baseResult.values)[0]); setStep(2); } catch (error) { alert("Error: " + error); } finally { setIsLoading(false); } }; const updateCurrentMf = (field, value) => { if (!selectedTerm) return; let numValue = parseFloat(value); setMfDefinitions(prev => { const scaleKeys = Object.keys(baseScale); const selectedIndex = scaleKeys.indexOf(selectedTerm); let prevCoreEnd = 0, prevSupportEnd = 0, nextCoreStart = 1, nextSupportStart = 1; if (selectedIndex > 0) { prevCoreEnd = prev[scaleKeys[selectedIndex - 1]].coreEnd; prevSupportEnd = prev[scaleKeys[selectedIndex - 1]].supportEnd; } if (selectedIndex < scaleKeys.length - 1) { nextCoreStart = prev[scaleKeys[selectedIndex + 1]].coreStart; nextSupportStart = prev[scaleKeys[selectedIndex + 1]].supportStart; } if (field === 'supportStart' && numValue < prevCoreEnd) numValue = prevCoreEnd; if (field === 'coreStart' && numValue < prevSupportEnd) numValue = prevSupportEnd; if (field === 'coreEnd' && numValue > nextSupportStart) numValue = nextSupportStart; if (field === 'supportEnd' && numValue > nextCoreStart) numValue = nextCoreStart; const current = { ...prev[selectedTerm], [field]: numValue }; if (field === 'supportStart' && current.supportStart > current.coreStart) current.coreStart = current.supportStart; if (field === 'coreStart') { if (current.coreStart < current.supportStart) current.supportStart = current.coreStart; if (current.coreStart > current.coreEnd) current.coreEnd = current.coreStart; } if (field === 'coreEnd') { if (current.coreEnd < current.coreStart) current.coreStart = current.coreEnd; if (current.coreEnd > current.supportEnd) current.supportEnd = current.coreEnd; } if (field === 'supportEnd' && current.supportEnd < current.coreEnd) current.coreEnd = current.supportEnd; return { ...prev, [selectedTerm]: current }; }); }; const handleFinalSubmit = () => { console.log("PAYLOAD DOC-MF:", { base_scale: baseScale, membership_functions: mfDefinitions }); alert("¡Mira la consola! JSON preparado."); }; const scaleKeys = Object.keys(baseScale); const selectedColor = COLORS[scaleKeys.indexOf(selectedTerm) % COLORS.length] || '#2563eb'; const needsZoom = dimensions.table > dimensions.container; const dynamicScale = needsZoom ? (dimensions.container / dimensions.table) * 0.95 : 1; const currentScale = isZoomActive && needsZoom ? dynamicScale : 1; return (