add: añadir modo rango en el modal para la subescala

This commit is contained in:
Alexis
2026-04-06 12:34:42 +02:00
parent 22ed6c107e
commit 2a237a51db
+101 -13
View File
@@ -4,11 +4,20 @@ import BlankCardsCounter from '../BlankCardsCounter';
export default function SubscaleModal({ onClose, onSave, targetInfo }) { export default function SubscaleModal({ onClose, onSave, targetInfo }) {
const [cardsCount, setCardsCount] = useState(targetInfo?.initialData?.cardsCount || 2); const [cardsCount, setCardsCount] = useState(targetInfo?.initialData?.cardsCount || 2);
const [blankCards, setBlankCards] = useState(targetInfo?.initialData?.blankCards || [0]);
const [blankCards, setBlankCards] = useState(() => {
const initialBlanks = targetInfo?.initialData?.blankCards || [0];
return initialBlanks.map(b => {
if (Array.isArray(b)) {
return { min: b[0], max: b[1], isRange: true };
}
return { min: b, max: b, isRange: false };
});
});
const handleAddCard = () => { const handleAddCard = () => {
setCardsCount(prev => prev + 1); setCardsCount(prev => prev + 1);
setBlankCards([...blankCards, 0]); setBlankCards([...blankCards, { min: 0, max: 0, isRange: false }]);
}; };
const handleRemoveCard = () => { const handleRemoveCard = () => {
@@ -17,16 +26,46 @@ export default function SubscaleModal({ onClose, onSave, targetInfo }) {
setBlankCards(blankCards.slice(0, -1)); setBlankCards(blankCards.slice(0, -1));
}; };
const handleBlankCardChange = (index, delta) => { const handleExactChange = (index, delta) => {
const newBlanks = [...blankCards]; const newBlanks = [...blankCards];
if (newBlanks[index] + delta >= 0) { const newVal = newBlanks[index].min + delta;
newBlanks[index] += delta; if (newVal >= 0) {
newBlanks[index].min = newVal;
newBlanks[index].max = newVal;
setBlankCards(newBlanks); setBlankCards(newBlanks);
} }
}; };
const handleMinChange = (index, delta) => {
const newBlanks = [...blankCards];
const newVal = newBlanks[index].min + delta;
if (newVal >= 0 && newVal <= newBlanks[index].max) {
newBlanks[index].min = newVal;
setBlankCards(newBlanks);
}
};
const handleMaxChange = (index, delta) => {
const newBlanks = [...blankCards];
const newVal = newBlanks[index].max + delta;
if (newVal >= newBlanks[index].min) {
newBlanks[index].max = newVal;
setBlankCards(newBlanks);
}
};
const toggleRangeMode = (index) => {
const newBlanks = [...blankCards];
newBlanks[index].isRange = !newBlanks[index].isRange;
if (!newBlanks[index].isRange) {
newBlanks[index].max = newBlanks[index].min;
}
setBlankCards(newBlanks);
};
const handleSave = () => { const handleSave = () => {
onSave(targetInfo.term, targetInfo.side, { cardsCount, blankCards }); const payloadBlanks = blankCards.map(b => b.isRange ? [b.min, b.max] : b.min);
onSave(targetInfo.term, targetInfo.side, { cardsCount, blankCards: payloadBlanks });
}; };
const handleDelete = () => { const handleDelete = () => {
@@ -35,7 +74,7 @@ export default function SubscaleModal({ onClose, onSave, targetInfo }) {
return ( return (
<div className="fixed inset-0 z-[100] flex items-center justify-center bg-slate-900/40 backdrop-blur-sm animate-fade-in"> <div className="fixed inset-0 z-[100] flex items-center justify-center bg-slate-900/40 backdrop-blur-sm animate-fade-in">
<div className="bg-white w-full max-w-5xl p-8 rounded-3xl shadow-2xl mx-4 flex flex-col"> <div className="bg-white w-full max-w-6xl p-8 rounded-3xl shadow-2xl mx-4 flex flex-col">
<div className="flex justify-between items-center mb-6 border-b pb-4"> <div className="flex justify-between items-center mb-6 border-b pb-4">
<div> <div>
@@ -47,34 +86,83 @@ export default function SubscaleModal({ onClose, onSave, targetInfo }) {
<button onClick={onClose} className="w-10 h-10 bg-slate-100 hover:bg-slate-200 text-slate-600 rounded-full font-bold transition-colors"></button> <button onClick={onClose} className="w-10 h-10 bg-slate-100 hover:bg-slate-200 text-slate-600 rounded-full font-bold transition-colors"></button>
</div> </div>
{/* Tablero */} {/* Tablero de Cartas */}
<div className="w-full py-10 overflow-x-auto flex justify-start px-4"> <div className="w-full py-10 overflow-x-auto flex justify-start px-4">
<div className="flex flex-row items-start min-w-max relative"> <div className="flex flex-row items-start min-w-max relative">
{Array.from({ length: cardsCount }).map((_, index) => ( {Array.from({ length: cardsCount }).map((_, index) => (
<React.Fragment key={index}> <React.Fragment key={index}>
{/* CARTA DE REFERENCIA */}
<div className="flex flex-col items-center mx-2 my-2 relative z-20"> <div className="flex flex-col items-center mx-2 my-2 relative z-20">
<div className="relative w-32 h-40 bg-slate-50 border-2 border-slate-300 rounded-2xl shadow-sm flex flex-col items-center justify-center group"> <div className="relative w-32 h-40 bg-slate-50 border-2 border-slate-300 rounded-2xl shadow-sm flex flex-col items-center justify-center group">
{cardsCount > 2 && index === cardsCount - 1 && ( {cardsCount > 2 && index === cardsCount - 1 && (
<button onClick={handleRemoveCard} className="absolute -top-3 -right-3 w-8 h-8 bg-white text-slate-400 rounded-full border border-slate-200 flex items-center justify-center font-bold hover:bg-red-500 hover:text-white transition-colors z-10 shadow-sm opacity-0 group-hover:opacity-100">×</button> <button onClick={handleRemoveCard} className="absolute -top-3 -right-3 w-8 h-8 bg-white text-slate-400 rounded-full border border-slate-200 flex items-center justify-center font-bold hover:bg-red-500 hover:text-white transition-colors z-10 shadow-sm opacity-0 group-hover:opacity-100"></button>
)} )}
<span className="text-4xl font-black text-slate-200">{index + 1}</span> <span className="text-4xl font-black text-slate-200">{index + 1}</span>
</div> </div>
</div> </div>
{/* HUECO ENTRE CARTAS: Representación y Controles */}
{index < cardsCount - 1 && ( {index < cardsCount - 1 && (
<BlankCardsCounter index={index} blankCardsCount={blankCards[index]} handleBlankCardChange={handleBlankCardChange} /> <div className="flex flex-col items-center justify-start mx-4 mt-2 max-w-[180px]">
{/* Representación visual de las cartas blancas Sólidas / Fantasmas */}
<div className="flex flex-wrap justify-center gap-1 min-h-[48px] mb-4">
{Array.from({ length: blankCards[index].min }).map((_, i) => (
<div key={`solid-${i}`} className="w-7 h-10 bg-white border-2 border-slate-300 rounded shadow-sm" />
))}
{blankCards[index].isRange && Array.from({ length: blankCards[index].max - blankCards[index].min }).map((_, i) => (
<div key={`ghost-${i}`} className="w-7 h-10 bg-blue-50 border-2 border-dashed border-blue-400 rounded opacity-60 flex items-center justify-center">
<span className="text-blue-500 text-[10px] font-bold">?</span>
</div>
))}
</div>
{/* Controles de números */}
{blankCards[index].isRange ? (
// MODO RANGO
<div className="flex gap-4 bg-blue-50/50 p-3 rounded-xl border border-blue-100 shadow-inner">
<div className="flex flex-col items-center">
<span className="text-xs font-bold text-slate-500 mb-1">MÍN</span>
<BlankCardsCounter index={index} blankCardsCount={blankCards[index].min} handleBlankCardChange={(idx, delta) => handleMinChange(idx, delta)} />
</div>
<div className="flex flex-col items-center">
<span className="text-xs font-bold text-slate-500 mb-1">MÁX</span>
<BlankCardsCounter index={index} blankCardsCount={blankCards[index].max} handleBlankCardChange={(idx, delta) => handleMaxChange(idx, delta)} />
</div>
</div>
) : (
// MODO EXACTO
<div className="flex flex-col items-center mt-2">
<span className="text-xs font-bold text-slate-500 mb-1">CARTAS</span>
<BlankCardsCounter index={index} blankCardsCount={blankCards[index].min} handleBlankCardChange={(idx, delta) => handleExactChange(idx, delta)} />
</div>
)}
{/* Botón Toggle */}
<button
onClick={() => toggleRangeMode(index)}
className="mt-3 text-xs font-semibold text-blue-600 hover:text-blue-800 hover:underline transition-colors text-center"
>
{blankCards[index].isRange ? "Conozco la distancia exacta" : "¿Dudas? Define un rango"}
</button>
</div>
)} )}
</React.Fragment> </React.Fragment>
))} ))}
{/* Botón Añadir Carta */}
<div className="mx-2 my-2 h-40 flex items-center"> <div className="mx-2 my-2 h-40 flex items-center">
<button onClick={handleAddCard} className="w-32 h-40 border-4 border-dashed border-slate-300 rounded-2xl flex flex-col items-center justify-center text-slate-400 font-bold hover:bg-blue-50 hover:border-blue-400 hover:text-blue-500 transition-colors"> <button onClick={handleAddCard} className="w-32 h-40 border-4 border-dashed border-slate-300 rounded-2xl flex flex-col items-center justify-center text-slate-400 font-bold hover:bg-blue-50 hover:border-blue-400 hover:text-blue-500 transition-colors group">
<span className="text-3xl">+</span> <span className="text-3xl group-hover:scale-110 transition-transform">+</span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
{/* Botones */} {/* Botones de Acción */}
<div className="mt-8 flex justify-between items-center border-t pt-6"> <div className="mt-8 flex justify-between items-center border-t pt-6">
<button onClick={handleDelete} className="px-6 py-3 rounded-xl font-bold text-red-500 hover:bg-red-50 transition-colors"> <button onClick={handleDelete} className="px-6 py-3 rounded-xl font-bold text-red-500 hover:bg-red-50 transition-colors">
Borrar Subescala Borrar Subescala