diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0f2633d..c0cf46f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,6 +12,7 @@ "axios": "^1.13.6", "react": "^19.2.4", "react-dom": "^19.2.4", + "react-router-dom": "^7.13.2", "recharts": "^3.8.0", "tailwindcss": "^4.2.2" }, @@ -1529,6 +1530,19 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -3093,6 +3107,44 @@ } } }, + "node_modules/react-router": { + "version": "7.13.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.2.tgz", + "integrity": "sha512-tX1Aee+ArlKQP+NIUd7SE6Li+CiGKwQtbS+FfRxPX6Pe4vHOo6nr9d++u5cwg+Z8K/x8tP+7qLmujDtfrAoUJA==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.13.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.2.tgz", + "integrity": "sha512-aR7SUORwTqAW0JDeiWF07e9SBE9qGpByR9I8kJT5h/FrBKxPMS6TiC7rmVO+gC0q52Bx7JnjWe8Z1sR9faN4YA==", + "license": "MIT", + "dependencies": { + "react-router": "7.13.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/recharts": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.0.tgz", @@ -3209,6 +3261,12 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 278c666..debc10c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,6 +14,7 @@ "axios": "^1.13.6", "react": "^19.2.4", "react-dom": "^19.2.4", + "react-router-dom": "^7.13.2", "recharts": "^3.8.0", "tailwindcss": "^4.2.2" }, diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 0545d76..df64ca3 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,10 +1,8 @@ -import BasicMode from './pages/BasicMode'; +import { AppRouter } from './routers/AppRouter'; function App() { return ( -
- -
+ ); } diff --git a/frontend/src/components/AddLevelButton.jsx b/frontend/src/components/AddLevelButton.jsx index 1d39d4e..67fa95f 100644 --- a/frontend/src/components/AddLevelButton.jsx +++ b/frontend/src/components/AddLevelButton.jsx @@ -1,13 +1,11 @@ export default function AddLevelButton({ handleAddLevel }) { return ( -
- +
); } \ No newline at end of file diff --git a/frontend/src/components/BlankCardsCounter.jsx b/frontend/src/components/BlankCardsCounter.jsx index 2cabe8d..b35b7ed 100644 --- a/frontend/src/components/BlankCardsCounter.jsx +++ b/frontend/src/components/BlankCardsCounter.jsx @@ -1,36 +1,55 @@ export default function BlankCardsCounter({ index, blankCardsCount, handleBlankCardChange }) { + + const maxCardsPerRow = 7; + const rows = []; + for (let i = 0; i < blankCardsCount; i += maxCardsPerRow) { + rows.push(Array.from({ length: Math.min(maxCardsPerRow, blankCardsCount - i) })); + } + return ( -
-
+
-
- Blancas: - - - {blankCardsCount} - - +
+ + {/* Línea conectora horizontal */} +
+ + {/* Botones - y + */} +
+ + +
+ Blancas + {blankCardsCount} +
+ + +
+ {/* Cartas blancas */} {blankCardsCount > 0 && ( -
- {Array.from({ length: blankCardsCount }).map((_, i) => ( -
+
+ {rows.map((row, rowIndex) => ( +
+ {row.map((_, colIndex) => ( +
+ ))} +
))}
)} -
); } \ No newline at end of file diff --git a/frontend/src/components/CardEditor.jsx b/frontend/src/components/CardEditor.jsx index 77c0c73..c5e887f 100644 --- a/frontend/src/components/CardEditor.jsx +++ b/frontend/src/components/CardEditor.jsx @@ -1,33 +1,18 @@ -export default function CardEditor({ index, level, handleLevelChange, handleRemoveLevel, totalLevels }) { + +export default function CardEditor({ index, level, handleLevelChange, handleRemoveLevel, totalLevels, error }) { return ( -
- - {/* Botón Eliminar */} - {totalLevels > 2 && ( - - )} - - {/* Detalles tipo naipe */} - - {index + 1} - - - {index + 1} - - - handleLevelChange(index, e.target.value)} - className="w-4/5 text-center text-2xl font-bold text-slate-700 bg-transparent border-b-2 border-dashed border-slate-300 focus:border-blue-500 outline-none pb-1" - /> +
+
+ {totalLevels > 3 && ( + + )} + {index + 1} + {index + 1} + handleLevelChange(index, e.target.value)} className={`w-10/12 text-center text-lg font-bold text-slate-700 bg-transparent border-b-2 border-dashed outline-none pb-1 ${error ? 'border-red-300 focus:border-red-500 placeholder:text-red-200' : 'border-slate-300 focus:border-blue-500'}`} /> +
+
{error &&

Escribe una etiqueta

}
); } \ No newline at end of file diff --git a/frontend/src/components/CriterionInput.jsx b/frontend/src/components/CriterionInput.jsx index 300c2de..b636ede 100644 --- a/frontend/src/components/CriterionInput.jsx +++ b/frontend/src/components/CriterionInput.jsx @@ -1,16 +1,29 @@ -export default function CriterionInput({ criterionName, setCriterionName }) { +export default function CriterionInput({ criterionName, setCriterionName, error }) { return ( -
-