Traducción pagina coach y cierre de sesión
This commit is contained in:
parent
874ebd1b90
commit
b22538e4aa
|
@ -3,96 +3,95 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<title>Crear Rutina – SwimmingArt</title>
|
<title data-i18n="title">Crear Rutina – SwimmingArt</title>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
|
||||||
<style>
|
<link rel="stylesheet" href="css/navbar.css">
|
||||||
body {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
}
|
|
||||||
.navbar {
|
|
||||||
background-color: #0d6efd;
|
|
||||||
}
|
|
||||||
.navbar a {
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
.form-section {
|
|
||||||
background: white;
|
|
||||||
padding: 2rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
||||||
max-width: 800px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
.form-title {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-primary sticky-top shadow-sm px-4 py-3">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary sticky-top shadow-sm px-4 py-3">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand fw-bold text-white" href="#">SwimArt</a>
|
<a class="navbar-brand fw-bold text-white" href="#">SwimArt</a>
|
||||||
<div class="ms-auto d-flex gap-4">
|
<div class="ms-auto d-flex gap-4 align-items-center">
|
||||||
<a href="coach.html" class="nav-link text-white">Inicializar Rutina</a>
|
<a href="coach.html" class="nav-link text-white" data-i18n="nav.init">Inicializar Rutina</a>
|
||||||
<a href="equipoDisponibles.html" class="nav-link text-white">Equipos Disponibles</a>
|
<a href="equipoDisponibles.html" class="nav-link text-white" data-i18n="nav.equip">Equipos Disponibles</a>
|
||||||
<a href="piscina.html" class="nav-link text-white">Piscina</a>
|
<a href="piscina.html" class="nav-link text-white" data-i18n="nav.pool">Piscina</a>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-outline-light dropdown-toggle d-flex align-items-center gap-2 px-3 py-1" type="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-person-circle" viewBox="0 0 16 16">
|
||||||
|
<path d="M11 10a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
|
||||||
|
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-4.546 12.174c.03-.256.071-.512.124-.767C4.28 10.798 5.94 10 8 10s3.72.798 4.422 2.407c.053.255.094.511.124.767A7 7 0 0 0 8 1z"/>
|
||||||
|
</svg>
|
||||||
|
<span id="nombreUsuarioHeader" class="fw-semibold">Usuario</span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end text-center p-3"
|
||||||
|
aria-labelledby="userDropdown"
|
||||||
|
style="background-color: #0d6efd; color: white; border-radius: 0 0 8px 8px; min-width: 100%; max-width: 250px;">
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<select id="langSelector" class="form-select form-select-sm mb-3"
|
||||||
|
style="border: none; border-radius: 6px; background-color: white; color: black; padding: 0.4rem 0.5rem;">
|
||||||
|
<option value="es">Español</option>
|
||||||
|
<option value="en">English</option>
|
||||||
|
<option value="fr">Français</option>
|
||||||
|
</select>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<button class="btn btn-danger btn-sm w-100" onclick="logout()">Salir</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="px-5 my-4" style="max-width: 90%; margin: 0 auto;">
|
<main class="px-5 my-4" style="max-width: 90%; margin: 0 auto;">
|
||||||
<div class="bg-white p-4 shadow-sm rounded" style="max-width: 900px; margin: auto;">
|
<div class="bg-white p-4 shadow-sm rounded" style="max-width: 900px; margin: auto; margin-top: 125px;">
|
||||||
<h3 class="fw-bold text-center mb-4">Inicializar Nueva Rutina</h3>
|
<h3 class="fw-bold text-center mb-4" data-i18n="form.title">Inicializar Nueva Rutina</h3>
|
||||||
<form id="rutinaForm">
|
<form id="rutinaForm">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="title" class="form-label">Título de la rutina</label>
|
<label for="title" class="form-label" data-i18n="form.routineTitle">Título de la rutina</label>
|
||||||
<input type="text" class="form-control" id="title" required />
|
<input type="text" class="form-control" id="title" required />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-6">
|
||||||
<label for="duration" class="form-label">Duración (segundos)</label>
|
<label for="duration" class="form-label" data-i18n="form.duration">Duración</label>
|
||||||
<input type="number" class="form-control" id="duration" required />
|
<input type="text" class="form-control" id="duration" placeholder="Selecciona tipo de competencia y modalidad" readonly />
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label for="language" class="form-label">Idioma</label>
|
|
||||||
<select id="language" class="form-select" required>
|
|
||||||
<option value="es">Español</option>
|
|
||||||
<option value="en">Inglés</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="music" class="form-label">Subir música (mp3)</label>
|
<label for="music" class="form-label" data-i18n="form.music">Subir música (mp3)</label>
|
||||||
<input type="file" class="form-control" id="music" accept=".mp3" />
|
<input type="file" class="form-control" id="music" accept=".mp3" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="nombreCompetencia" class="form-label">Nombre de la competencia</label>
|
<label for="nombreCompetencia" class="form-label" data-i18n="form.competition">Nombre de la competencia</label>
|
||||||
<input type="text" class="form-control" id="nombreCompetencia" required />
|
<input type="text" class="form-control" id="nombreCompetencia" required />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="tipoCompetencia" class="form-label">Tipo de competencia</label>
|
<label for="tipoCompetencia" class="form-label" data-i18n="form.type">Tipo de competencia</label>
|
||||||
<select class="form-select" id="tipoCompetencia" required>
|
<select class="form-select" id="tipoCompetencia" required>
|
||||||
<option value="libre">Libre</option>
|
<option value="libre" data-i18n="form.free">Libre</option>
|
||||||
<option value="técnica">Técnica</option>
|
<option value="técnica" data-i18n="form.technical">Técnica</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="modalidad" class="form-label">Modalidad</label>
|
<label for="modalidad" class="form-label" data-i18n="form.mode">Modalidad</label>
|
||||||
<select class="form-select" id="modalidad" required>
|
<select class="form-select" id="modalidad" required>
|
||||||
<option value="solo">Solo</option>
|
<option value="solo" data-i18n="form.solo">Solo</option>
|
||||||
<option value="duo">Dúo</option>
|
<option value="duo" data-i18n="form.duo">Dúo</option>
|
||||||
<option value="equipo">Equipo</option>
|
<option value="equipo" data-i18n="form.team">Equipo</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4 text-center">
|
<div class="mt-4 text-center">
|
||||||
<button type="submit" class="btn btn-success px-5">Guardar Rutina</button>
|
<button type="submit" class="btn btn-success px-5" data-i18n="form.save">Guardar Rutina</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="js/coach.js"></script>
|
<script src="js/coach.js"></script>
|
||||||
</body>
|
<script src="js/traduccionCoach.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
body {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
background-color: #0d6efd;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar a {
|
||||||
|
color: white !important;
|
||||||
|
transition: 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #e6e6e6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-section {
|
||||||
|
background: white;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
max-width: 800px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ======== USER DROPDOWN ========= */
|
||||||
|
#userDropdown {
|
||||||
|
background-color: #0d6efd;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#userDropdown:hover {
|
||||||
|
background-color: #0b5ed7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Menú del dropdown azul continuo */
|
||||||
|
.dropdown-menu {
|
||||||
|
margin-top: 0;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
background-color: #0d6efd;
|
||||||
|
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
min-width: 200px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Eliminar nombre superior */
|
||||||
|
.dropdown-menu strong {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Selector de idioma estilizado */
|
||||||
|
.dropdown-menu select,
|
||||||
|
#langSelector {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.4rem 2rem 0.4rem 0.75rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: white;
|
||||||
|
color: #212529;
|
||||||
|
border: none;
|
||||||
|
appearance: none;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg fill='gray' height='16' viewBox='0 0 20 20' width='16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 7l5 5 5-5z'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right 0.6rem center;
|
||||||
|
background-size: 1rem;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#langSelector:hover {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#langSelector:focus {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 0.15rem rgba(13,110,253,.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Botón de cerrar sesión rojo sólido */
|
||||||
|
.dropdown-menu .btn-danger {
|
||||||
|
width: 100%;
|
||||||
|
color: white;
|
||||||
|
background-color: #dc3545;
|
||||||
|
border: none;
|
||||||
|
font-weight: 500;
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu .btn-danger:hover {
|
||||||
|
background-color: #b02a37;
|
||||||
|
}
|
|
@ -1,15 +1,47 @@
|
||||||
|
const duracionesPorModalidadYTipo = {
|
||||||
|
solo: {
|
||||||
|
técnica: { texto: "2:00", valor: 120 },
|
||||||
|
libre: { texto: "2:15", valor: 135 }
|
||||||
|
},
|
||||||
|
duo: {
|
||||||
|
técnica: { texto: "2:20", valor: 140 },
|
||||||
|
libre: { texto: "2:45", valor: 165 }
|
||||||
|
},
|
||||||
|
equipo: {
|
||||||
|
técnica: { texto: "2:50", valor: 170 },
|
||||||
|
libre: { texto: "3:30", valor: 210 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function actualizarDuracionTexto() {
|
||||||
|
const tipo = document.getElementById("tipoCompetencia").value;
|
||||||
|
const modalidad = document.getElementById("modalidad").value;
|
||||||
|
const input = document.getElementById("duration");
|
||||||
|
|
||||||
|
if (duracionesPorModalidadYTipo[modalidad] && duracionesPorModalidadYTipo[modalidad][tipo]) {
|
||||||
|
input.value = duracionesPorModalidadYTipo[modalidad][tipo].texto;
|
||||||
|
input.dataset.segundos = duracionesPorModalidadYTipo[modalidad][tipo].valor;
|
||||||
|
} else {
|
||||||
|
input.value = traducciones[langActual].form.durationPlaceholder;
|
||||||
|
input.dataset.segundos = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("tipoCompetencia").addEventListener("change", actualizarDuracionTexto);
|
||||||
|
document.getElementById("modalidad").addEventListener("change", actualizarDuracionTexto);
|
||||||
|
|
||||||
|
// Envío del formulario
|
||||||
document.getElementById('rutinaForm').addEventListener('submit', async function (e) {
|
document.getElementById('rutinaForm').addEventListener('submit', async function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const title = document.getElementById('title').value.trim();
|
const title = document.getElementById('title').value.trim();
|
||||||
const duration = parseInt(document.getElementById('duration').value.trim());
|
const duration = parseInt(document.getElementById('duration').dataset.segundos);
|
||||||
const language = document.getElementById('language').value;
|
|
||||||
const nombreCompetencia = document.getElementById('nombreCompetencia').value.trim();
|
const nombreCompetencia = document.getElementById('nombreCompetencia').value.trim();
|
||||||
const tipoCompetencia = document.getElementById('tipoCompetencia').value;
|
const tipoCompetencia = document.getElementById('tipoCompetencia').value;
|
||||||
const modalidad = document.getElementById('modalidad').value;
|
const modalidad = document.getElementById('modalidad').value;
|
||||||
const musicFile = document.getElementById('music').files[0];
|
const musicFile = document.getElementById('music').files[0];
|
||||||
|
|
||||||
if (!title || isNaN(duration) || !language || !nombreCompetencia || !tipoCompetencia || !modalidad) {
|
if (!title || isNaN(duration) || !nombreCompetencia || !tipoCompetencia || !modalidad) {
|
||||||
alert("Completa todos los campos.");
|
alert("Completa todos los campos.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +75,6 @@ document.getElementById('rutinaForm').addEventListener('submit', async function
|
||||||
const routine = {
|
const routine = {
|
||||||
title,
|
title,
|
||||||
duration,
|
duration,
|
||||||
language,
|
|
||||||
nombreCompetencia,
|
nombreCompetencia,
|
||||||
tipoCompetencia,
|
tipoCompetencia,
|
||||||
modalidad,
|
modalidad,
|
||||||
|
@ -74,3 +105,32 @@ document.getElementById('rutinaForm').addEventListener('submit', async function
|
||||||
alert("Error al guardar la rutina.");
|
alert("Error al guardar la rutina.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
sessionStorage.clear();
|
||||||
|
alert("Sesión cerrada");
|
||||||
|
window.location.href = "../index.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mostrar nombre del usuario logueado en el header
|
||||||
|
window.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
const userId = sessionStorage.getItem("userId");
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
alert("Sesión expirada, inicia sesión de nuevo.");
|
||||||
|
window.location.href = "index.html";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/users/${userId}`);
|
||||||
|
const user = await res.json();
|
||||||
|
|
||||||
|
if (user?.name) {
|
||||||
|
document.getElementById("nombreUsuarioHeader").textContent = user.name;
|
||||||
|
document.getElementById("nombreUsuarioDropdown").textContent = "Coach " + user.name;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("❌ Error al obtener datos del usuario:", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
const traducciones = {
|
||||||
|
es: {
|
||||||
|
title: "Crear Rutina – SwimmingArt",
|
||||||
|
nav: {
|
||||||
|
init: "Inicializar Rutina",
|
||||||
|
equip: "Equipos Disponibles",
|
||||||
|
pool: "Piscina"
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
title: "Inicializar Nueva Rutina",
|
||||||
|
routineTitle: "Título de la rutina",
|
||||||
|
duration: "Duración",
|
||||||
|
durationPlaceholder: "Selecciona tipo de competencia y modalidad",
|
||||||
|
music: "Subir música (mp3)",
|
||||||
|
competition: "Nombre de la competencia",
|
||||||
|
type: "Tipo de competencia",
|
||||||
|
free: "Libre",
|
||||||
|
technical: "Técnica",
|
||||||
|
mode: "Modalidad",
|
||||||
|
solo: "Solo",
|
||||||
|
duo: "Dúo",
|
||||||
|
team: "Equipo",
|
||||||
|
save: "Guardar Rutina"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
title: "Create Routine – SwimmingArt",
|
||||||
|
nav: {
|
||||||
|
init: "Initialize Routine",
|
||||||
|
equip: "Available Equipment",
|
||||||
|
pool: "Pool"
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
title: "Initialize New Routine",
|
||||||
|
routineTitle: "Title of the routine",
|
||||||
|
duration: "Duration",
|
||||||
|
durationPlaceholder: "Select type and modality",
|
||||||
|
music: "Upload music (mp3)",
|
||||||
|
competition: "Name of the competition",
|
||||||
|
type: "Type of competition",
|
||||||
|
free: "Free",
|
||||||
|
technical: "Technical",
|
||||||
|
mode: "Mode",
|
||||||
|
solo: "Only",
|
||||||
|
duo: "Duo",
|
||||||
|
team: "Team",
|
||||||
|
save: "Save Routine"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fr: {
|
||||||
|
title: "Créer une Routine – SwimmingArt",
|
||||||
|
nav: {
|
||||||
|
init: "Initialiser la Routine",
|
||||||
|
equip: "Équipements Disponibles",
|
||||||
|
pool: "Piscine"
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
title: "Initialiser une Nouvelle Routine",
|
||||||
|
routineTitle: "Titre de la routine",
|
||||||
|
duration: "Durée",
|
||||||
|
durationPlaceholder: "Sélectionnez le type et la modalité",
|
||||||
|
music: "Télécharger musique (mp3)",
|
||||||
|
competition: "Nom de la compétition",
|
||||||
|
type: "Type de compétition",
|
||||||
|
free: "Libre",
|
||||||
|
technical: "Technique",
|
||||||
|
mode: "Modalité",
|
||||||
|
solo: "Solo",
|
||||||
|
duo: "Duo",
|
||||||
|
team: "Équipe",
|
||||||
|
save: "Enregistrer la Routine"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let langActual = "es";
|
||||||
|
|
||||||
|
function updateLanguage(lang) {
|
||||||
|
langActual = lang;
|
||||||
|
const t = traducciones[lang];
|
||||||
|
document.querySelector("title").innerText = t.title;
|
||||||
|
|
||||||
|
document.querySelectorAll("[data-i18n]").forEach(el => {
|
||||||
|
const keys = el.getAttribute("data-i18n").split(".");
|
||||||
|
let value = t;
|
||||||
|
for (let k of keys) value = value[k];
|
||||||
|
if (el.tagName === "OPTION") {
|
||||||
|
el.text = value;
|
||||||
|
} else if (el.tagName === "INPUT" && el.placeholder !== undefined) {
|
||||||
|
el.placeholder = value;
|
||||||
|
} else {
|
||||||
|
el.textContent = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// actualizar el texto si la duración está vacía
|
||||||
|
const input = document.getElementById("duration");
|
||||||
|
if (input && !input.dataset.segundos) {
|
||||||
|
input.value = traducciones[langActual].form.durationPlaceholder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("langSelector").addEventListener("change", function () {
|
||||||
|
updateLanguage(this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.onload = () => updateLanguage("es");
|
|
@ -36,14 +36,6 @@
|
||||||
<option value="athlete">Atleta</option>
|
<option value="athlete">Atleta</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
|
||||||
<label for="language" class="form-label">Idioma</label>
|
|
||||||
<select class="form-select" id="language" name="language">
|
|
||||||
<option value="es">Español</option>
|
|
||||||
<option value="en">Inglés</option>
|
|
||||||
<option value="fr">Francés</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-success w-100">Registrarse</button>
|
<button type="submit" class="btn btn-success w-100">Registrarse</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="text-center mt-3">
|
<div class="text-center mt-3">
|
||||||
|
|
|
@ -18,7 +18,6 @@ const userSchema = new mongoose.Schema({
|
||||||
email: { type: String, unique: true, required: true },
|
email: { type: String, unique: true, required: true },
|
||||||
passwordHash: String,
|
passwordHash: String,
|
||||||
role: { type: String, enum: ['coach', 'athlete'], required: true },
|
role: { type: String, enum: ['coach', 'athlete'], required: true },
|
||||||
language: { type: String, enum: ['es', 'en', 'fr'], default: 'es' },
|
|
||||||
createdAt: { type: Date, default: Date.now }
|
createdAt: { type: Date, default: Date.now }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,14 +25,14 @@ const User = mongoose.model('User', userSchema);
|
||||||
|
|
||||||
// === Ruta: Registro de usuario ===
|
// === Ruta: Registro de usuario ===
|
||||||
router.post('/register', async (req, res) => {
|
router.post('/register', async (req, res) => {
|
||||||
const { name, username, email, password, role, language } = req.body;
|
const { name, username, email, password, role } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const existing = await User.findOne({ email });
|
const existing = await User.findOne({ email });
|
||||||
if (existing) return res.status(400).send('Correo ya registrado');
|
if (existing) return res.status(400).send('Correo ya registrado');
|
||||||
|
|
||||||
const passwordHash = await bcrypt.hash(password, 10);
|
const passwordHash = await bcrypt.hash(password, 10);
|
||||||
const user = new User({ name, username, email, passwordHash, role, language });
|
const user = new User({ name, username, email, passwordHash, role });
|
||||||
await user.save();
|
await user.save();
|
||||||
|
|
||||||
res.redirect('/index.html');
|
res.redirect('/index.html');
|
||||||
|
|
|
@ -5,7 +5,6 @@ const router = express.Router();
|
||||||
const routineSchema = new mongoose.Schema({
|
const routineSchema = new mongoose.Schema({
|
||||||
title: String,
|
title: String,
|
||||||
createdBy: { type: String, default: "coach-id-ejemplo" },
|
createdBy: { type: String, default: "coach-id-ejemplo" },
|
||||||
language: { type: String, enum: ['es', 'en', 'fr'], default: 'es' },
|
|
||||||
duration: Number,
|
duration: Number,
|
||||||
musicUrl: { type: String, default: "" },
|
musicUrl: { type: String, default: "" },
|
||||||
nombreCompetencia: String,
|
nombreCompetencia: String,
|
||||||
|
|
|
@ -30,7 +30,6 @@ const upload = multer({
|
||||||
const routineSchema = new mongoose.Schema({
|
const routineSchema = new mongoose.Schema({
|
||||||
title: String,
|
title: String,
|
||||||
createdBy: { type: String, default: "coach-id-ejemplo" },
|
createdBy: { type: String, default: "coach-id-ejemplo" },
|
||||||
language: { type: String, enum: ['es', 'en', 'fr'], default: 'es' },
|
|
||||||
duration: Number,
|
duration: Number,
|
||||||
musicUrl: { type: String, default: "" },
|
musicUrl: { type: String, default: "" },
|
||||||
nombreCompetencia: String,
|
nombreCompetencia: String,
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const { MongoClient } = require('mongodb');
|
const { MongoClient, ObjectId } = require('mongodb');
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
const uri = process.env.MONGO_URI;
|
const uri = process.env.MONGO_URI;
|
||||||
const client = new MongoClient(uri);
|
const client = new MongoClient(uri);
|
||||||
|
|
||||||
|
// Obtener todos los atletas
|
||||||
router.get('/athletes', async (req, res) => {
|
router.get('/athletes', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await client.connect();
|
await client.connect();
|
||||||
|
@ -22,4 +23,23 @@ router.get('/athletes', async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Obtener usuario por ID
|
||||||
|
router.get('/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await client.connect();
|
||||||
|
const db = client.db('swimartdb');
|
||||||
|
const user = await db.collection('users')
|
||||||
|
.findOne({ _id: new ObjectId(req.params.id) }, { projection: { name: 1, email: 1, role: 1 } });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({ error: 'Usuario no encontrado' });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(user);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error al obtener usuario:', error);
|
||||||
|
res.status(500).json({ error: 'Error al obtener usuario', details: error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue