diff --git a/public/css/editorPiscina.css b/public/css/editorPiscina.css index ad63cd3..281ee39 100644 --- a/public/css/editorPiscina.css +++ b/public/css/editorPiscina.css @@ -1,3 +1,4 @@ +/* GENERAL */ body { font-family: 'Inter', sans-serif; background-color: #f9fafb; @@ -6,45 +7,93 @@ body { padding: 0; } +/* TARJETAS */ .card { - height: auto !important; + border: none; + border-radius: 1rem; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); + background-color: #fff; overflow: visible; - display: block; } -/* Asegura que la tarjeta se expanda al contenido */ .card-body { - height: auto !important; overflow: visible; - display: block; } -/* Multimedia */ +/* FORMULARIOS */ +.form-control, +.form-select { + border-radius: 0.75rem; + font-size: 1rem; + transition: border-color 0.3s ease, box-shadow 0.3s ease; +} + +.form-control:focus, +.form-select:focus { + border-color: #0d6efd; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.15); +} + +/* BOTONES */ +button, +.btn { + border-radius: 0.75rem; + transition: all 0.25s ease; + font-weight: 600; +} + +.btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 10px rgba(0,0,0,0.06); +} + +#btnAgregarAtleta, +#btnActualizarPiscina, +#btnGuardarFormacion, +#playPauseBtn { + padding: 0.75rem 1rem; + font-size: 1rem; +} + +#playPauseBtn { + background-color: #0d6efd; + color: white; + font-weight: 500; + border: none; + border-radius: 8px; + box-shadow: 0 2px 5px rgba(0,0,0,0.1); +} + +#playPauseBtn:hover { + background-color: #084298; + transform: scale(1.05); +} + +/* MULTIMEDIA */ #waveform { width: 100%; height: 100px; margin-bottom: 10px; } + #audioPlayer { display: none; } -/* Contenedor de la piscina */ +/* PISCINA */ #piscinaContainer { background-color: #e6f7ff; border: 2px dashed #007bff; - transition: all 0.3s ease; - overflow: visible; padding: 1rem; + border-radius: 0.75rem; width: fit-content; height: fit-content; min-width: 300px; min-height: 200px; - box-sizing: border-box; max-width: 100%; + box-sizing: border-box; } -/* Lienzo de piscina Konva */ #piscina { display: block; width: 100% !important; @@ -60,7 +109,7 @@ body { overflow: hidden; } -/* Línea de tiempo */ +/* TIMELINE */ .timeline-placeholder { display: flex; overflow-x: auto; @@ -68,7 +117,7 @@ body { padding: 1rem; border: 1px solid #ddd; background: #ffffff; - border-radius: 8px; + border-radius: 0.75rem; box-shadow: 0 1px 4px rgba(0,0,0,0.05); } @@ -80,9 +129,9 @@ body { border-radius: 8px; text-align: center; cursor: pointer; - box-shadow: 1px 1px 3px rgba(0,0,0,0.05); font-size: 0.85rem; transition: all 0.2s ease; + box-shadow: 1px 1px 3px rgba(0,0,0,0.05); } .timeline-placeholder .step:hover { @@ -91,7 +140,13 @@ body { transform: scale(1.03); } -/* Autocompletado */ +.step.active { + background-color: #0d6efd !important; + color: white !important; + font-weight: bold; +} + +/* AUTOCOMPLETADO */ #sugerenciasFigura { margin-top: 4px; padding: 6px 0; @@ -125,7 +180,7 @@ body { font-weight: 500; } -/* Vista previa */ +/* VISTA PREVIA FIGURA */ #previewFigura img { margin-top: 8px; max-width: 100%; @@ -140,32 +195,7 @@ body { margin-top: 4px; } -#playPauseBtn { - background-color: #0d6efd; - color: white; - font-weight: 500; - padding: 10px 20px; - border: none; - border-radius: 8px; - font-size: 1rem; - cursor: pointer; - box-shadow: 0 2px 5px rgba(0,0,0,0.1); - transition: background-color 0.3s ease, transform 0.2s ease; -} - -#playPauseBtn:hover { - background-color: #084298; - transform: scale(1.05); -} - -.step.active { - background-color: #0d6efd !important; - color: white !important; - font-weight: bold; -} - - -/* Responsivo */ +/* RESPONSIVO */ @media (max-width: 768px) { #piscina { min-height: 300px; @@ -175,11 +205,113 @@ body { min-width: 80px; font-size: 0.75rem; } - - .step.active { - background-color: #0d6efd !important; - color: white !important; - font-weight: bold; +} +/* ---------- ESTILO GLOBAL 2025 ---------- */ +:root { + --color-primary: #0d6efd; + --color-success: #198754; + --radius-lg: 0.75rem; + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08); + --transition-fast: all 0.25s ease; + --font-family: 'Inter', sans-serif; } +/* Fuentes y cuerpo */ +body { + font-family: var(--font-family); + font-size: clamp(1rem, 1vw + 0.2rem, 1.125rem); + line-height: 1.7; + background-color: #f9fafb; + color: #212529; +} + +/* Botones unificados */ +button, +.btn { + border-radius: var(--radius-lg); + padding: 0.6rem 1.2rem; + font-weight: 600; + font-size: 1rem; + transition: var(--transition-fast); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); +} + +.btn-primary, +.btn-success, +.btn-outline-primary, +.btn-outline-secondary { + border-width: 2px; +} + +.btn-primary { + background-color: var(--color-primary); + border-color: var(--color-primary); + color: #fff; +} + +.btn-primary:hover { + background-color: #084298; + border-color: #084298; +} + +.btn-success { + background-color: var(--color-success); + border-color: var(--color-success); + color: white; +} + +.btn-success:hover { + background-color: #145c32; + border-color: #145c32; +} + +.btn-outline-primary { + color: var(--color-primary); + border-color: var(--color-primary); + background-color: white; +} + +.btn-outline-primary:hover { + background-color: var(--color-primary); + color: white; +} + +.btn-outline-secondary { + color: #6c757d; + border-color: #6c757d; + background-color: white; +} + +.btn-outline-secondary:hover { + background-color: #6c757d; + color: white; +} + +/* Formulario */ +.form-control, +.form-select { + border-radius: var(--radius-lg); + border: 1px solid #ced4da; + transition: var(--transition-fast); +} + +.form-control:focus, +.form-select:focus { + border-color: var(--color-primary); + box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.15); +} + +/* Tarjetas */ +.card { + border: none; + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + background-color: white; +} + +/* Botón desactivado coherente */ +button:disabled, +.btn:disabled { + opacity: 0.65; + cursor: not-allowed; } diff --git a/public/js/piscina.js b/public/js/piscina.js index 706a045..cada04f 100644 --- a/public/js/piscina.js +++ b/public/js/piscina.js @@ -77,8 +77,20 @@ document.addEventListener('DOMContentLoaded', async () => { } catch (err) { console.warn('❌ No se pudo cargar el catálogo FINA:', err); } - const piscinaWidth = rutina.piscina?.width || 850; - const piscinaHeight = rutina.piscina?.height || 400; + const tipoPiscinaSelect = document.getElementById('tipoPiscina'); + + const medidasPiscina = { + olimpica: { width: 1000, height: 500 }, + semiolimpica: { width: 750, height: 375 }, + fosa: { width: 600, height: 600 } + }; + + const tipoSeleccionado = rutina.tipoPiscina || 'olimpica'; + tipoPiscinaSelect.value = tipoSeleccionado; + + const piscinaWidth = medidasPiscina[tipoSeleccionado].width; + const piscinaHeight = medidasPiscina[tipoSeleccionado].height; + // Escalas de conversión a metros const escalaX = 25 / piscinaWidth; const escalaY = 20 / piscinaHeight; @@ -421,7 +433,10 @@ document.addEventListener('DOMContentLoaded', async () => { direccion: a.direccion, figura: a.figura, tipoElemento: a.tipoElemento, - codigoElemento: a.codigoElemento + codigoElemento: a.codigoElemento, + tipoPiscina: tipoPiscinaSelect.value, + + })) }; @@ -545,17 +560,7 @@ formaciones.forEach((f, i) => { } }); - document.getElementById('btnActualizarPiscina').addEventListener('click', async () => { - const newWidth = parseInt(document.getElementById('inputWidth').value); - const newHeight = parseInt(document.getElementById('inputHeight').value); - if (isNaN(newWidth) || isNaN(newHeight) || newWidth < 300 || newHeight < 200) { - return Swal.fire({ - icon: 'warning', - title: 'Valores no válidos', - text: 'El ancho mínimo es 300px y el alto mínimo es 200px.' - }); - } try { const res = await fetch(`/api/rutinas/${rutinaId}/piscina`, { diff --git a/public/piscina.html b/public/piscina.html index 003360c..181b50a 100644 --- a/public/piscina.html +++ b/public/piscina.html @@ -79,21 +79,15 @@
🏊 Vista de la Piscina
- -
-
🛠 Ajustar tamaño de la piscina
-
-
- -
-
- -
-
- -
-
-
+
+ + +
+
diff --git a/routes/routines.js b/routes/routines.js index 02de879..d831f76 100644 --- a/routes/routines.js +++ b/routes/routines.js @@ -36,6 +36,7 @@ const routineSchema = new mongoose.Schema({ nombreCompetencia: String, tipoCompetencia: { type: String, enum: ['libre', 'técnica'], default: 'libre' }, modalidad: { type: String, enum: ['solo', 'duo', 'equipo'], default: 'solo' }, + tipoPiscina: { type: String, enum: ['olimpica', 'semiolimpica', 'fosa'], default: 'olimpica' }, participantes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }], elements: [], formaciones: [