30 Commits

Author SHA1 Message Date
profesor 78b7a5816d revert b22f3021f0
revert Subir archivos a "/"
2026-09-29 14:17:35 +02:00
profesor 0147a0f3d1 revert b22f3021f0
revert Subir archivos a "/"
2026-09-29 14:16:28 +02:00
profesor 61f83c2ebb revert b22f3021f0
revert Subir archivos a "/"
2026-09-29 14:16:02 +02:00
dbvictor2002 8156738bd0 Subir archivos a "controladores" 2026-09-29 13:16:37 +02:00
dbvictor2002 b22f3021f0 Subir archivos a "/" 2026-09-29 13:16:17 +02:00
victordiamar8 5420c83b30 base de datos con insert partida corregido 2026-09-29 11:15:26 +02:00
victordiamar8 d28fbc7160 Mofificar base de datos y clase Partida 2026-09-29 10:13:25 +02:00
jorge 4efb831b7a Reparado inicio y registro de momento 2026-09-28 13:13:05 +02:00
jorge 22f38f924f Merge branch 'pruebasJorge' 2026-09-28 12:37:07 +02:00
jorge 01aa2643f6 Actualizando a 12:24 2026-09-28 12:23:45 +02:00
jorge 07c1f79474 Merge branch 'main' of https://git.desarrolloalcala.com/jorge/triviagmatico 2026-09-28 10:28:26 +02:00
jorge 54b6b0d67b Changes to cabecera & sala 2026-09-28 10:09:26 +02:00
profesor 57e3dfc444 grafico E-R, no afecta en nada 2026-09-28 10:04:35 +02:00
Isaac 8c7958ad96 Merge branch 'main' of https://git.desarrolloalcala.com/jorge/triviagmatico 2026-09-28 09:43:03 +02:00
Isaac bf2361ad43 crear pregunta (y select de categorias) 2026-09-28 09:42:58 +02:00
jorge 03715d621e Corregida ruta jquery en buscadorSala 2026-09-28 09:03:36 +02:00
Isaac 6da20872c6 arreglado crear sala 2026-09-28 08:50:54 +02:00
Isaac 26a46c29e8 Funcionalidad de crear Sala.
Crear ClaseEquipoxPartida.php
Modificar controladorPartida.php
2026-09-25 14:11:29 +02:00
daniel 9a5575fe25 Add unirse a sala completo 2026-09-25 14:09:23 +02:00
daniel 0518cecd1e Add unirse a sala 2026-09-25 14:07:48 +02:00
Isaac d6e1cd8c2d crear sala (crear clase EquipoxPartida y modificar controladorPartida) 2026-09-25 13:57:37 +02:00
jorge 4e345fa01d Ranking 2026-09-25 13:53:22 +02:00
daniel 413d9552f2 Merge branch 'frontend' of https://git.desarrolloalcala.com/jorge/triviagmatico into frontend 2026-09-25 13:00:29 +02:00
daniel 6beb655e83 Add buscadorSala recupera las salas de la bbdd 2026-09-25 12:59:55 +02:00
Isaac 7292b932dd actualizado favicon e icono cabecera 2026-09-25 12:54:20 +02:00
alexis 36fb2d96fc add favicom 2026-09-25 12:46:47 +02:00
Isaac 9c67d76265 cambiar avatar y nombre en perfil.php 2026-09-25 11:35:05 +02:00
daniel 8d6272c664 Merge branch 'main' into frontend 2026-09-25 11:00:21 +02:00
Isaac 859f86aeb1 funcionalidad de perfil (estadisticas y nombre) 2026-09-25 10:30:54 +02:00
jorge f729a54bc2 SQL con equipos y partidas
Añadidos equipos y partidas de prueba a la bd para hacer pruebas.
2026-09-25 10:01:39 +02:00
25 changed files with 2543 additions and 1062 deletions
+59 -95
View File
@@ -4,138 +4,102 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Trivial - Lobby</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet">
<link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="css/buscadorSala.css">
</head>
<body>
<?php
include_once("cabecera.php");
?>
<?php include_once("cabecera.php"); ?>
<main class="container py-5">
<main class="container py-4">
<div class="text-center mb-5">
<button
type="button"
class="btn btn-play-kahoot btn-crear-sala"
data-bs-toggle="modal"
data-bs-target="#modalCrearSala">
<span>+</span>
Crear sala
<!-- Botón Volver -->
<div class="mb-4">
<a href="index.php" class="btn btn-outline-secondary d-inline-flex align-items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
</svg>
Volver al Inicio
</a>
</div>
<!-- Botón Crear Sala -->
<div id="contenedorCrearSala" class="text-center mb-5">
<button type="button" class="btn btn-play-kahoot btn-crear-sala" data-bs-toggle="modal" data-bs-target="#modalCrearSala">
<span>+</span> Crear sala
</button>
</div>
<div
id="contenedorSalas"
class="row justify-content-center g-4">
<!-- Contenedor Principal de Salas -->
<div id="contenedorSalas" class="row justify-content-center g-4">
<div id="cargandoSalas" class="col-12 text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Cargando...</span>
</div>
<p class="mt-3 text-muted">Cargando salas...</p>
</div>
</div>
</main>
<div
class="modal fade"
id="modalCrearSala"
tabindex="-1"
aria-labelledby="modalCrearSalaLabel"
aria-hidden="true">
<!-- Modal Crear Sala -->
<div class="modal fade" id="modalCrearSala" tabindex="-1" aria-labelledby="modalCrearSalaLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content modal-kahoot">
<div class="modal-header modal-kahoot-header">
<h5
class="modal-title"
id="modalCrearSalaLabel">
Crear sala
</h5>
<button
type="button"
class="btn-close btn-close-white"
data-bs-dismiss="modal"
aria-label="Cerrar">
</button>
<h5 class="modal-title" id="modalCrearSalaLabel">Crear sala</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Cerrar"></button>
</div>
<div class="modal-body p-4">
<div class="mb-3">
<label
for="nombreSala"
class="form-label">
Nombre de la sala
</label>
<input
type="text"
id="nombreSala"
class="form-control input-kahoot"
name="nombreSala"
placeholder="Ej. Noche de Trivial">
<label for="nombreSala" class="form-label">Nombre de la sala</label>
<input type="text" id="nombreSala" class="form-control input-kahoot" name="nombreSala" placeholder="Ej. Noche de Trivial" maxlength="100">
</div>
<div class="mb-3">
<label
for="nombreEquipo1"
class="form-label">
Nombre del equipo 1
</label>
<input
type="text"
id="nombreEquipo1"
name="nombreEquipo1"
class="form-control input-kahoot"
placeholder="Ej. Los cerebritos">
<label for="nombreEquipo1" class="form-label">Nombre del equipo 1</label>
<input type="text" id="nombreEquipo1" name="nombreEquipo1" class="form-control input-kahoot" placeholder="Ej. Los cerebritos" maxlength="50">
</div>
<div class="mb-3">
<label
for="nombreEquipo2"
class="form-label">
Nombre del equipo 2
</label>
<input
type="text"
id="nombreEquipo2"
name="nombreEquipo2"
class="form-control input-kahoot"
placeholder="Ej. Los campeones">
<label for="nombreEquipo2" class="form-label">Nombre del equipo 2</label>
<input type="text" id="nombreEquipo2" name="nombreEquipo2" class="form-control input-kahoot" placeholder="Ej. Los campeones" maxlength="50">
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-kahoot-login" id="btnCrearSala">Crear sala</button>
</div>
</div>
</div>
</div>
<!--MODAL ABANDONAR SALA -->
<!-- Modal Confirmar Abandonar Sala -->
<div class="modal fade" id="modalAbandonarSala" tabindex="-1" aria-labelledby="modalAbandonarSalaLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content modal-kahoot text-center p-3">
<div class="modal-body">
<div class="mb-3 fs-1">⚠️</div>
<h4 class="modal-title mb-2 fw-bold text-white" id="modalAbandonarSalaLabel">¿Abandonar la sala?</h4>
<p class="text-white-50">Si sales de la sala, perderás tu lugar en el equipo.</p>
</div>
<div class="modal-footer justify-content-center border-0 gap-2">
<button type="button" class="btn btn-secondary px-4 py-2" data-bs-dismiss="modal">
Cancelar
</button>
<button
type="button"
class="btn btn-kahoot-login"
id="btnCrearSala">
Crear sala
<button type="button" id="btnConfirmarAbandonar" class="btn btn-danger px-4 py-2">
Sí, salir
</button>
</div>
</div>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js">
</script>
<script src="js/lobbyDummy.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="js/jquery-4.0.0.min.js"></script>
<script src="js/buscadorSala.js"></script>
</body>
</html>
+14 -210
View File
@@ -1,13 +1,3 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Comprobación de sesión
$isLoggedIn = isset($_SESSION['idUsuario']) && !empty($_SESSION['idUsuario']);
$username = $isLoggedIn ? $_SESSION['nombreUsuario'] : '';
?>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- FontAwesome para iconos -->
@@ -16,16 +6,14 @@ $username = $isLoggedIn ? $_SESSION['nombreUsuario'] : '';
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/index.css">
<script src="js/jquery-4.0.0.min.js"></script>
<style>
</style>
<nav class="navbar navbar-expand-lg navbar-kahoot py-3 mb-4">
<div class="container">
<a class="navbar-brand" href="index.php">
<i class="fa-solid fa-gamepad me-2"></i>TRIVIAGMÁTICO
<img src="img/favicon/favicon.svg" alt="TRIVIAGMÁTICO" class="me-2" style="height: 35px;">
TRIVIAGMÁTICO
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarContent">
<span class="navbar-toggler-icon"></span>
</button>
@@ -33,44 +21,8 @@ $username = $isLoggedIn ? $_SESSION['nombreUsuario'] : '';
<div class="collapse navbar-collapse" id="navbarContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
<div class="d-flex align-items-center gap-3">
<?php if ($isLoggedIn): ?>
<!-- Menú desplegable cuando la sesión está iniciada -->
<div class="dropdown">
<button class="btn user-dropdown-btn dropdown-toggle d-flex align-items-center gap-2"
type="button"
id="userDropdown"
data-bs-toggle="dropdown"
aria-expanded="false">
<i class="fa-solid fa-circle-user fa-lg text-warning"></i>
<span><?= htmlspecialchars($username) ?></span>
</button>
<ul class="dropdown-menu dropdown-menu-end user-dropdown-menu" aria-labelledby="userDropdown">
<li>
<a class="dropdown-item d-flex align-items-center gap-2" href="perfil.php">
<i class="fa-solid fa-user text-primary"></i> Perfil
</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<a class="dropdown-item logout-item d-flex align-items-center gap-2" href="#" id="botonCerrarSesion">
<i class="fa-solid fa-right-from-bracket"></i> Cerrar Sesión
</a>
</li>
</ul>
</div>
<?php else: ?>
<!-- Botones que abren los modales cuando NO hay sesión iniciada -->
<button type="button" class="btn btn-kahoot-login rounded-pill px-4" data-bs-toggle="modal" data-bs-target="#modalLogin">
<i class="fa-solid fa-right-to-bracket me-1"></i> Iniciar Sesión
</button>
<button type="button" class="btn btn-kahoot-register rounded-pill px-4" data-bs-toggle="modal" data-bs-target="#modalRegistro">
<i class="fa-solid fa-user-plus me-1"></i> Registrarse
</button>
<?php endif; ?>
<!-- Contenedor dinámico cargado por js/cabecera.js -->
<div class="d-flex align-items-center gap-3" id="contenedorUsuarioCabecera">
</div>
</div>
</div>
@@ -96,11 +48,6 @@ $username = $isLoggedIn ? $_SESSION['nombreUsuario'] : '';
<input type="password" class="form-control border-dark" id="loginPassword" name="contrasena" placeholder="Contraseña" required>
<label for="loginPassword">Contraseña</label>
</div>
<div class="form-check">
<input class="form-check-input" id="recordar" name="recordar" type="checkbox" />
<label for="recordar" class="small">Recuérdeme durante 10 días</label>
</div>
<input type="hidden" name="orden" value="validar">
</form>
<div id="errorLogin" class="text-danger fw-bold mt-2"></div>
</div>
@@ -140,7 +87,14 @@ $username = $isLoggedIn ? $_SESSION['nombreUsuario'] : '';
<input type="password" class="form-control border-dark" id="regPasswordConfirm" name="contrasenaConfirm" placeholder="Confirmar contraseña" required>
<label for="regPasswordConfirm">Confirmar contraseña</label>
</div>
<input type="hidden" name="orden" value="registrar">
<!-- Checkbox Recuérdame -->
<div class="form-check mb-3">
<input class="form-check-input border-dark" type="checkbox" value="" id="recuerdameCheck">
<label class="form-check-label fw-semibold" for="recuerdameCheck">
Recuérdame en 10 días
</label>
</div>
</form>
<div id="errorRegistro" class="text-danger fw-bold mt-2"></div>
</div>
@@ -152,154 +106,4 @@ $username = $isLoggedIn ? $_SESSION['nombreUsuario'] : '';
</div>
</div>
<script>
// Registro
$('#botonAceptarRegistro').click(function(event) {
event.preventDefault();
console.log('hola');
let nombreUsuario = $('#regNombre').val().trim();
let email = $('#regEmail').val().trim();
let contrasena = $('#regPassword').val();
let contrasenaConfirmacion = $('#regPasswordConfirm').val();
// Limpiamos errores anteriores
$('#regNombre').removeClass('is-invalid');
$('#regEmail').removeClass('is-invalid');
$('#regPassword').removeClass('is-invalid');
$('#regPasswordConfirm').removeClass('is-invalid');
$('#errorRegistro').text('');
// Comprobamos que las contraseñas coincidan
if (contrasena !== contrasenaConfirmacion) {
$('#regPassword').addClass('is-invalid');
$('#regPasswordConfirm').addClass('is-invalid');
$('#errorRegistro').text('Las contraseñas no coinciden.');
return;
}
$.ajax({
method: "POST",
url: "controladores/controladorUsuario.php",
data: {
'nombreUsuario': nombreUsuario,
'email': email,
'contrasena': contrasena,
'orden': 'registrarUsuario'
}
}).done(function(respuesta) {
//console.log(respuesta);
respuesta = JSON.parse(respuesta);
if (respuesta.error) {
$('#errorRegistro').text(respuesta.error);
// Marcamos los campos si hay error
$('#regNombre').addClass('is-invalid');
$('#regEmail').addClass('is-invalid');
} else {
// Registro correcto
$('#errorRegistro')
.removeClass('text-danger')
.addClass('text-success')
.text(respuesta.exito);
// Limpiamos formulario
$('#formRegistro')[0].reset();
// Cerramos modal después de un segundo
setTimeout(function() {
location.reload();
}, 1000);
}
}); // Fin función ajax
});
// Login
$('#botonAceptarLogin').click(function(event) {
event.preventDefault();
let email = $('#loginEmail').val().trim();
let contrasena = $('#loginPassword').val();
// Limpiamos errores anteriores
$('#loginEmail').removeClass('is-invalid');
$('#loginPassword').removeClass('is-invalid');
$('#errorLogin').text('');
// Comprobación básica
if (email === '' || contrasena === '') {
$('#errorLogin').text('Todos los campos son obligatorios.');
if (email === '') {
$('#loginEmail').addClass('is-invalid');
}
if (contrasena === '') {
$('#loginPassword').addClass('is-invalid');
}
return;
}
$.ajax({
method: "POST",
url: "controladores/controladorUsuario.php",
data: {
'email': email,
'contrasena': contrasena,
'orden': 'comprobarUsuario'
}
}).done(function(respuesta) {
//console.log(respuesta);
respuesta = JSON.parse(respuesta);
if (respuesta.error) {
$('#loginEmail').addClass('is-invalid');
$('#loginPassword').addClass('is-invalid');
$('#errorLogin').text(respuesta.error);
} else {
location.reload();
}
}); // Fin función ajax
});
// Cerrar sesión
$('#botonCerrarSesion').click(function(event) {
event.preventDefault();
$.ajax({
method: "POST",
url: "controladores/controladorUsuario.php",
data: {
'orden': 'cerrarSesion'
}
}).done(function(respuesta) {
//console.log(respuesta);
respuesta = JSON.parse(respuesta);
if (respuesta.error) {
console.log(respuesta.error);
} else {
// Sesión cerrada correctamente
location.reload();
}
}); // Fin función ajax
}); // Fin función click
</script>
<script src="js/cabecera.js"></script>
+20 -15
View File
@@ -2,37 +2,44 @@
require_once __DIR__ . '/../includes/conexionBD.php';
class Equipo{
class Equipo
{
public $idEquipo;
public $nombreEquipo;
function __construct($idEquipo=null, $nombreEquipo=null){
function __construct($idEquipo = null, $nombreEquipo = null)
{
$this->idEquipo = $idEquipo;
$this->nombreEquipo = $nombreEquipo;
}
function crear(){
function crear()
{
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
} else {
try {
$consulta = $conexion->prepare("INSERT INTO equipo (nombreEquipo) VALUES (:nombreEquipo)");
$consulta = $conexion->prepare(
"INSERT INTO equipo (nombreEquipo) VALUES (:nombreEquipo)"
);
$consulta->bindParam(':nombreEquipo', $this->nombreEquipo);
$consulta->execute();
// Guardamos el ID generado por la BD
$this->idEquipo = (int)$conexion->lastInsertId();
$respuesta = [
'exito' => 'Equipo creado correctamente',
'exito_tecnico' => $this->nombreEquipo
'exito_tecnico' => $this->idEquipo
];
return $respuesta;
} catch (PDOException $error) {
$respuesta = [
'error' => 'Ocurrió un error al guardar el equipo.',
@@ -46,7 +53,9 @@ class Equipo{
}
function listar(){
function listar()
{
$conexion = conexionBD();
if (is_array($conexion)) {
@@ -61,7 +70,6 @@ class Equipo{
$resultado = $consulta->fetchAll(PDO::FETCH_ASSOC);
return $resultado;
} catch (PDOException $error) {
$respuesta = [
'error' => 'Ocurrió un error al obtener el listado de equipos.',
@@ -75,7 +83,8 @@ class Equipo{
}
function buscar(){
function buscar()
{
$conexion = conexionBD();
if (is_array($conexion)) {
@@ -91,7 +100,6 @@ class Equipo{
$resultado = $consulta->fetch(PDO::FETCH_ASSOC);
return $resultado;
} catch (PDOException $error) {
$respuesta = [
'error' => 'Ocurrió un error al buscar el equipo.',
@@ -105,7 +113,8 @@ class Equipo{
}
function borrar(){
function borrar()
{
$conexion = conexionBD();
if (is_array($conexion)) {
@@ -131,7 +140,6 @@ class Equipo{
}
return $respuesta;
} catch (PDOException $error) {
$respuesta = [
'error' => 'Ocurrió un error al eliminar el equipo.',
@@ -143,7 +151,4 @@ class Equipo{
}
}
}
}
?>
+60
View File
@@ -0,0 +1,60 @@
<?php
require_once __DIR__ . '/../includes/conexionBD.php';
class EquipoxPartida
{
public $idEquipoxPartida;
public $idEquipo;
public $idPartida;
public function __construct(
$idEquipoxPartida = null,
$idEquipo = null,
$idPartida = null
) {
$this->idEquipoxPartida = $idEquipoxPartida;
$this->idEquipo = $idEquipo;
$this->idPartida = $idPartida;
}
public function insertar()
{
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$sql = "
INSERT INTO equipoxpartida
(idEquipo, idPartida)
VALUES
(:idEquipo, :idPartida)
";
$consulta = $conexion->prepare($sql);
$consulta->bindParam(':idEquipo', $this->idEquipo);
$consulta->bindParam(':idPartida', $this->idPartida);
$consulta->execute();
$this->idEquipoxPartida = (int)$conexion->lastInsertId();
return [
'exito' => 'Equipo vinculado a la partida correctamente.',
'exito_tecnico' => $this->idEquipoxPartida
];
} catch (PDOException $error) {
return [
'error' => 'Ocurrió un error al vincular el equipo con la partida.',
'error_tecnico' => $error->getMessage()
];
}
}
}
+92 -4
View File
@@ -2,18 +2,21 @@
require_once __DIR__ . '/../includes/conexionBD.php';
class EquipoxUsuario {
class EquipoxUsuario
{
public $idEquipoxUsuario;
public $idUsuario;
public $idEquipo;
public function __construct($idEquipoxUsuario = null, $idUsuario = null, $idEquipo = null) {
public function __construct($idEquipoxUsuario = null, $idUsuario = null, $idEquipo = null)
{
$this->idEquipoxUsuario = $idEquipoxUsuario;
$this->idUsuario = $idUsuario;
$this->idEquipo = $idEquipo;
}
public function registrarUsuarioEnEquipo() {
public function registrarUsuarioEnEquipo()
{
$conexion = conexionBD();
if (is_array($conexion)) return $conexion;
@@ -36,7 +39,8 @@ class EquipoxUsuario {
}
}
public static function listarUsuariosPorEquipo($idEquipo) {
public static function listarUsuariosPorEquipo($idEquipo)
{
$conexion = conexionBD();
if (is_array($conexion)) return $conexion;
@@ -56,4 +60,88 @@ class EquipoxUsuario {
];
}
}
public function obtenerSalaUsuario($idUsuario)
{
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$sql = "
SELECT
exu.idEquipo,
exp.idPartida
FROM equipoxusuario exu
INNER JOIN equipoxpartida exp
ON exu.idEquipo = exp.idEquipo
WHERE exu.idUsuario = :idUsuario
LIMIT 1
";
$consulta = $conexion->prepare($sql);
$consulta->bindParam(
':idUsuario',
$idUsuario,
PDO::PARAM_INT
);
$consulta->execute();
$resultado = $consulta->fetch(PDO::FETCH_ASSOC);
if (!$resultado) {
return [
'asociado' => false
];
}
return [
'asociado' => true,
'idEquipo' => $resultado['idEquipo'],
'idPartida' => $resultado['idPartida']
];
} catch (PDOException $error) {
return [
'error' => 'Ocurrió un error al obtener la sala del usuario.',
'error_tecnico' => $error->getMessage()
];
}
}
public static function salirDeSala($idUsuario)
{
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$sql = "DELETE FROM equipoxusuario WHERE idUsuario = :idUsuario";
$consulta = $conexion->prepare($sql);
$consulta->bindParam(':idUsuario', $idUsuario, PDO::PARAM_INT);
$consulta->execute();
return [
'exito' => true,
'mensaje' => 'Usuario eliminado de la sala correctamente.'
];
} catch (PDOException $error) {
return [
'error' => 'Ocurrió un error al salir de la sala.',
'error_tecnico' => $error->getMessage()
];
}
}
}
+163 -152
View File
@@ -7,17 +7,27 @@ class Partida
public $idPartida;
public $nombrePartida;
public $idUsuario;
public $fechaCreacion;
public $fechaInicio;
public $fechaFin;
public function __construct(
$idPartida = null,
$nombrePartida = null,
$idUsuario = null
$idUsuario = null,
$fechaCreacion = null,
$fechaInicio = null,
$fechaFin = null
) {
$this->idPartida = $idPartida;
$this->nombrePartida = $nombrePartida;
$this->idUsuario = $idUsuario;
$this->fechaCreacion = $fechaCreacion;
$this->fechaInicio = $fechaInicio;
$this->fechaFin = $fechaFin;
}
public function insertar()
{
$conexion = conexionBD();
@@ -25,12 +35,7 @@ class Partida
return $conexion;
}
try {
$consulta = $conexion->prepare("
INSERT INTO partida
(nombrePartida,idUsuario)
VALUES
(:nombrePartida,:idUsuario)
");
$consulta = $conexion->prepare("INSERT INTO partida (nombrePartida,idUsuario) VALUES (:nombrePartida,:idUsuario)");
$consulta->bindParam(":nombrePartida", $this->nombrePartida);
$consulta->bindParam(":idUsuario", $this->idUsuario);
$consulta->execute();
@@ -46,8 +51,7 @@ class Partida
}
}
public function listar()
{
public function listar(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
@@ -64,18 +68,13 @@ class Partida
}
}
public function buscar()
{
public function buscar(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
SELECT *
FROM partida
WHERE idPartida=:idPartida
");
$consulta = $conexion->prepare("SELECT * FROM partida WHERE idPartida=:idPartida");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->execute();
return $consulta->fetch(PDO::FETCH_ASSOC);
@@ -87,20 +86,14 @@ class Partida
}
}
public function editar()
{
public function editar(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
UPDATE partida
SET
nombrePartida=:nombrePartida,
idUsuario=:idUsuario
WHERE idPartida=:idPartida
");
$consulta = $conexion->prepare("UPDATE partida SET nombrePartida=:nombrePartida, idUsuario=:idUsuario WHERE idPartida=:idPartida");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->bindParam(":nombrePartida", $this->nombrePartida);
$consulta->bindParam(":idUsuario", $this->idUsuario);
@@ -117,17 +110,13 @@ class Partida
}
}
public function eliminar()
{
public function eliminar(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
DELETE FROM partida
WHERE idPartida=:idPartida
");
$consulta = $conexion->prepare("DELETE FROM partida WHERE idPartida=:idPartida");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->execute();
return [
@@ -142,27 +131,121 @@ class Partida
}
}
/**
* Devuelve las preguntas asignadas a la partida, junto con el
* idPartidaxPregunta (necesario para guardar respuestas después).
*/
public function getPreguntas()
{
public function iniciarPartida(){
$conexion = conexionBD();
if (is_array($conexion)){
return $conexion;
}
try {
$consulta = $conexion->prepare("
SELECT
pxp.idPartidaxPregunta,
p.*
FROM partidaxpregunta pxp
INNER JOIN pregunta p
ON pxp.idPregunta=p.idPregunta
WHERE pxp.idPartida=:idPartida
ORDER BY pxp.idPartidaxPregunta
");
$consulta = $conexion->prepare("UPDATE partida SET fechaInicio=NOW() WHERE idPartida=:idPartida AND fechaInicio IS NULL");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->execute();
return [
"exito" => "La partida ha comenzado.",
"exito_tecnico" => $this->idPartida
];
} catch (PDOException $error) {
return [
"error" => "Ocurrió un error al iniciar la partida.",
'error_tecnico' => $error->getMessage()
];
}
}
public function finalizar(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("UPDATE partida SET fechaFin=NOW() WHERE idPartida=:idPartida AND fechaFin IS NULL");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->execute();
return [
"exito" => "La partida se finalizó correctamente.",
"exito_tecnico" => $this->idPartida
];
} catch (PDOException $error) {
return [
"error" => "Ocurrió un error al finalizar la partida.",
'error_tecnico' => $error->getMessage()
];
}
}
//true si la partida ya tiene fecha de fin (fechaFin no es NULL)
//Devuelve false si la partida no existe
public function estaFinalizada() {
$datos = $this->buscar();
if (is_array($datos) && isset($datos["error"])) {
return $datos;
}
if (!$datos) {
return false;
}
return $datos["fechaFin"] !== null;
}
//Devuelve la partida más reciente del usuario que aún no ha
//terminado (fechaFin NULL), o false si no tiene ninguna.
//Incluye también las salas que todavía no han empezado.
public function partidaEnCursoDeUsuario(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("SELECT * FROM partida WHERE idUsuario=:idUsuario AND fechaFin IS NULL ORDER BY idPartida DESC LIMIT 1");
$consulta->bindParam(":idUsuario", $this->idUsuario);
$consulta->execute();
return $consulta->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $error) {
return [
"error" => "Ocurrió un error al buscar la partida en curso.",
'error_tecnico' => $error->getMessage()
];
}
}
public function listarSalasAbiertas() {
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("SELECT p.idPartida, p.nombrePartida, e.idEquipo, e.nombreEquipo, u.idUsuario, u.nombreUsuario
FROM partida p INNER JOIN equipoxpartida exp ON exp.idPartida=p.idPartida INNER JOIN equipo e ON e.idEquipo=exp.idEquipo
LEFT JOIN equipoxusuario exu ON exu.idEquipo=e.idEquipo LEFT JOIN usuario u ON u.idUsuario=exu.idUsuario WHERE p.fechaInicio IS NULL
AND p.fechaFin IS NULL ORDER BY p.idPartida DESC, e.idEquipo ASC");
$consulta->execute();
return $consulta->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $error) {
return [
"error" => "Ocurrió un error al recuperar las salas abiertas.",
'error_tecnico' => $error->getMessage()
];
}
}
/**
* Devuelve las preguntas asignadas a la partida, junto con el
* idPartidaxPregunta (necesario para guardar respuestas después).
*/
public function getPreguntas(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("SELECT pxp.idPartidaxPregunta, p.* FROM partidaxpregunta pxp INNER JOIN pregunta p ON pxp.idPregunta=p.idPregunta
WHERE pxp.idPartida=:idPartida ORDER BY pxp.idPartidaxPregunta");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->execute();
return $consulta->fetchAll(PDO::FETCH_ASSOC);
@@ -174,22 +257,14 @@ class Partida
}
}
/**
* Asocia una pregunta ya existente a esta partida.
*/
public function asignarPregunta($idPregunta)
{
public function asignarPregunta($idPregunta) {
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
INSERT INTO partidaxpregunta
(idPartida,idPregunta)
VALUES
(:idPartida,:idPregunta)
");
$consulta = $conexion->prepare("INSERT INTO partidaxpregunta (idPartida,idPregunta) VALUES (:idPartida,:idPregunta)");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->bindParam(":idPregunta", $idPregunta);
$consulta->execute();
@@ -205,18 +280,13 @@ class Partida
}
}
//Cuenta cuántas preguntas tiene la partida en total. Es la primera mitad de la comprobación "¿ha terminado el usuario de jugar?".
public function contarPreguntasAsignadas()
{
public function contarPreguntasAsignadas() {
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
SELECT COUNT(*) AS total
FROM partidaxpregunta
WHERE idPartida=:idPartida
");
$consulta = $conexion->prepare("SELECT COUNT(*) AS total FROM partidaxpregunta WHERE idPartida=:idPartida");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->execute();
$fila = $consulta->fetch(PDO::FETCH_ASSOC);
@@ -229,21 +299,14 @@ class Partida
}
}
public function contarRespuestasUsuario($idUsuario)
{
public function contarRespuestasUsuario($idUsuario){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
SELECT COUNT(*) AS total
FROM respuestaalmacenada ra
INNER JOIN partidaxpregunta pxp
ON ra.idPartidaxPregunta=pxp.idPartidaxPregunta
WHERE pxp.idPartida=:idPartida
AND ra.idUsuario=:idUsuario
");
$consulta = $conexion->prepare("SELECT COUNT(*) AS total FROM respuestaalmacenada ra INNER JOIN partidaxpregunta pxp
ON ra.idPartidaxPregunta=pxp.idPartidaxPregunta WHERE pxp.idPartida=:idPartida AND ra.idUsuario=:idUsuario");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->bindParam(":idUsuario", $idUsuario);
$consulta->execute();
@@ -258,11 +321,11 @@ class Partida
}
/**
* Sustituye al antiguo campo `terminada`: compara cuántas preguntas
* tiene la partida contra cuántas ha respondido este usuario.
* Indica si ESTE usuario ya ha respondido todas las preguntas:
* compara cuántas preguntas tiene la partida contra cuántas ha
* respondido él. (La partida completa se marca con finalizar().)
*/
public function estaFinalizadaParaUsuario($idUsuario)
{
public function estaFinalizadaParaUsuario($idUsuario){
$totalPreguntas = $this->contarPreguntasAsignadas();
if (is_array($totalPreguntas)) {
return $totalPreguntas;
@@ -277,19 +340,13 @@ class Partida
/**
* Partidas creadas por un usuario, de más reciente a más antigua.
*/
public function listarDelUsuario()
{
public function listarDelUsuario(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
SELECT *
FROM partida
WHERE idUsuario=:idUsuario
ORDER BY idPartida DESC
");
$consulta = $conexion->prepare("SELECT * FROM partida WHERE idUsuario=:idUsuario ORDER BY idPartida DESC");
$consulta->bindParam(":idUsuario", $this->idUsuario);
$consulta->execute();
return $consulta->fetchAll(PDO::FETCH_ASSOC);
@@ -301,22 +358,13 @@ class Partida
}
}
public function preguntaAsignada($idPregunta)
{
public function preguntaAsignada($idPregunta) {
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$consulta = $conexion->prepare("
SELECT COUNT(*) AS total
FROM partidaxpregunta
WHERE idPartida=:idPartida
AND idPregunta=:idPregunta
");
$consulta = $conexion->prepare("SELECT COUNT(*) AS total FROM partidaxpregunta WHERE idPartida=:idPartida AND idPregunta=:idPregunta");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->bindParam(":idPregunta", $idPregunta);
$consulta->execute();
@@ -337,22 +385,12 @@ class Partida
* Permite registrar qué grupos están participando en este torneo.
*/
public function registrarEquipoEnPartida($idEquipo){
$conexion = conexionBD(); // Obtenemos la conexión modular del proyecto
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion; // Si hay error en la conexión, lo devuelve
return $conexion;
}
try {
// Preparamos la consulta para insertar la relación en la tabla intermedia real
$consulta = $conexion->prepare("
INSERT INTO equipoxpartida
(idPartida, idEquipo)
VALUES
(:idPartida, :idEquipo)
");
// Vinculamos los parámetros con el objeto de la partida actual y el equipo recibido
$consulta = $conexion->prepare("INSERT INTO equipoxpartida (idPartida, idEquipo) VALUES (:idPartida, :idEquipo)");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->bindParam(":idEquipo", $idEquipo);
$consulta->execute();
@@ -362,7 +400,6 @@ class Partida
"exito_tecnico" => $conexion->lastInsertId()
];
} catch (PDOException $error) {
// Capturamos el error extrayendo solo el mensaje de texto limpio
return [
"error" => "Ocurrió un error al asignar el equipo a la partida.",
"error_tecnico" => $error->getMessage()
@@ -376,25 +413,12 @@ class Partida
*/
public function getEquiposParticipantes(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
// Hacemos un INNER JOIN para traer los nombres de los equipos desde la tabla intermedia
$consulta = $conexion->prepare("
SELECT
exp.idEquipoxPartida,
e.idEquipo,
e.nombreEquipo
FROM equipoxpartida exp
INNER JOIN equipo e
ON exp.idEquipo = e.idEquipo
WHERE exp.idPartida = :idPartida
ORDER BY e.nombreEquipo ASC
");
$consulta = $conexion->prepare("SELECT exp.idEquipoxPartida, e.idEquipo, e.nombreEquipo FROM equipoxpartida exp
INNER JOIN equipo e ON exp.idEquipo = e.idEquipo WHERE exp.idPartida = :idPartida ORDER BY e.nombreEquipo ASC");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta->execute();
@@ -413,40 +437,27 @@ class Partida
*/
public function getJugadoresDeLaPartida(){
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
// Cruza la partida con los equipos, y luego los equipos con los usuarios
// para saber los nombres de todas las personas que están jugando el torneo.
$consulta = $conexion->prepare("
SELECT DISTINCT
u.idUsuario,
u.nombreUsuario,
u.email,
e.nombreEquipo
FROM equipoxpartida exp
INNER JOIN equipoxusuario exu
ON exp.idEquipo = exu.idEquipo
INNER JOIN usuario u
ON exu.idUsuario = u.idUsuario
INNER JOIN equipo e
ON exu.idEquipo = e.idEquipo
WHERE exp.idPartida = :idPartida
");
$consulta->bindParam(":idPartida", $this->idPartida);
$consulta = $conexion->prepare("SELECT DISTINCT u.idUsuario, u.nombreUsuario, u.email, e.idEquipo, e.nombreEquipo
FROM equipoxpartida exp INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo INNER JOIN usuario u
ON exu.idUsuario = u.idUsuario INNER JOIN equipo e ON exu.idEquipo = e.idEquipo WHERE exp.idPartida = :idPartida
ORDER BY e.nombreEquipo ASC, u.nombreUsuario ASC");
$consulta->bindParam(
":idPartida",
$this->idPartida
);
$consulta->execute();
return $consulta->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $error) {
return [
"error" => "Ocurrió un error al obtener la lista de jugadores.",
"error_tecnico" => $error->getMessage()
"error" =>
"Ocurrió un error al obtener la lista de jugadores.",
"error_tecnico" =>
$error->getMessage()
];
}
}
}
+226 -23
View File
@@ -1,7 +1,8 @@
<?php
require_once __DIR__ . '/../includes/conexionBD.php';
class Usuario {
class Usuario
{
private ?int $idUsuario;
private string $nombreUsuario;
private string $contrasena;
@@ -34,33 +35,85 @@ class Usuario {
$this->derrotas = $derrotas;
}
public function getIdUsuario(): ?int { return $this->idUsuario; }
public function getIdUsuario(): ?int
{
return $this->idUsuario;
}
public function getNombreUsuario(): string { return $this->nombreUsuario; }
public function setNombreUsuario(string $nombreUsuario): void { $this->nombreUsuario = $nombreUsuario; }
public function getNombreUsuario(): string
{
return $this->nombreUsuario;
}
public function setNombreUsuario(string $nombreUsuario): void
{
$this->nombreUsuario = $nombreUsuario;
}
public function getContrasena(): string { return $this->contrasena; }
public function setContrasena(string $contrasena): void { $this->contrasena = $contrasena; }
public function getContrasena(): string
{
return $this->contrasena;
}
public function setContrasena(string $contrasena): void
{
$this->contrasena = $contrasena;
}
public function getEmail(): string { return $this->email; }
public function setEmail(string $email): void { $this->email = $email; }
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): void
{
$this->email = $email;
}
public function getAvatar(): ?string { return $this->avatar; }
public function setAvatar(?string $avatar): void { $this->avatar = $avatar; }
public function getAvatar(): ?string
{
return $this->avatar;
}
public function setAvatar(?string $avatar): void
{
$this->avatar = $avatar;
}
public function getCookie(): ?string { return $this->cookie; }
public function setCookie(?string $cookie): void { $this->cookie = $cookie; }
public function getCookie(): ?string
{
return $this->cookie;
}
public function setCookie(?string $cookie): void
{
$this->cookie = $cookie;
}
public function getAciertos(): int { return $this->aciertos; }
public function setAciertos(int $aciertos): void { $this->aciertos = $aciertos; }
public function getAciertos(): int
{
return $this->aciertos;
}
public function setAciertos(int $aciertos): void
{
$this->aciertos = $aciertos;
}
public function getVictorias(): int { return $this->victorias; }
public function setVictorias(int $victorias): void { $this->victorias = $victorias; }
public function getVictorias(): int
{
return $this->victorias;
}
public function setVictorias(int $victorias): void
{
$this->victorias = $victorias;
}
public function getDerrotas(): int { return $this->derrotas; }
public function setDerrotas(int $derrotas): void { $this->derrotas = $derrotas; }
public function getDerrotas(): int
{
return $this->derrotas;
}
public function setDerrotas(int $derrotas): void
{
$this->derrotas = $derrotas;
}
public function registrar() {
public function registrar()
{
$conexion = conexionBD();
if (is_array($conexion)) {
@@ -91,7 +144,6 @@ class Usuario {
'exito' => 'Usuario registrado correctamente',
'exito_tecnico' => $this->idUsuario
];
} catch (PDOException $error) {
return [
'error' => 'Ocurrió un error al registrar el usuario.',
@@ -100,7 +152,8 @@ class Usuario {
}
}
public static function buscarPorId($id) {
public static function buscarPorId($id)
{
$conexion = conexionBD();
if (is_array($conexion)) {
@@ -131,7 +184,6 @@ class Usuario {
return [
'error' => 'No se encontró ningún usuario con ese ID.'
];
} catch (PDOException $error) {
return [
'error' => 'Ocurrió un error al buscar el usuario.',
@@ -140,7 +192,8 @@ class Usuario {
}
}
public static function buscarPorEmail($email) {
public static function buscarPorEmail($email)
{
$conexion = conexionBD();
if (is_array($conexion)) {
@@ -189,6 +242,7 @@ class Usuario {
unset($_SESSION['idUsuario']);
unset($_SESSION['email']);
unset($_SESSION['nombreUsuario']);
unset($_SESSION['avatar']);
return null;
}
@@ -200,6 +254,7 @@ class Usuario {
$_SESSION['idUsuario'] = $usuario->getIdUsuario();
$_SESSION['email'] = $usuario->getEmail();
$_SESSION['nombreUsuario'] = $usuario->getNombreUsuario();
$_SESSION['avatar'] = $usuario->getAvatar();
// Devolvemos el usuario como hasta ahora
return $usuario;
@@ -209,8 +264,156 @@ class Usuario {
unset($_SESSION['idUsuario']);
unset($_SESSION['email']);
unset($_SESSION['nombreUsuario']);
unset($_SESSION['avatar']);
return null;
}
public function cambiarNombre($nuevoNombre)
{
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$sql = "UPDATE usuario
SET nombreUsuario = :nombre
WHERE idUsuario = :id";
$stmt = $conexion->prepare($sql);
$stmt->execute([
':nombre' => $nuevoNombre,
':id' => $this->idUsuario
]);
// Actualizamos también el objeto actual
$this->nombreUsuario = $nuevoNombre;
return [
'exito' => 'Nombre actualizado correctamente.'
];
} catch (PDOException $error) {
return [
'error' => 'Ocurrió un error al actualizar el nombre.',
'error_tecnico' => $error->getMessage()
];
}
}
public function cambiarAvatar($archivo)
{
$carpeta = __DIR__ . '/../img/avatars/';
// Creamos la carpeta si no existe
if (!is_dir($carpeta)) {
mkdir($carpeta, 0755, true);
}
// Obtenemos la extensión según el tipo MIME
$tipo = mime_content_type($archivo['tmp_name']);
$extensiones = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
'image/webp' => 'webp'
];
if (!isset($extensiones[$tipo])) {
return [
'error' => 'Formato de imagen no permitido.'
];
}
$extension = $extensiones[$tipo];
// Nombre único para evitar conflictos
$nombreArchivo = 'avatar_' . $this->idUsuario . '.' . $extension;
$rutaCompleta = $carpeta . $nombreArchivo;
// Guardamos la imagen
if (!move_uploaded_file($archivo['tmp_name'], $rutaCompleta)) {
return [
'error' => 'No se pudo guardar la imagen.'
];
}
// Ruta que utilizará el HTML
$rutaAvatar = 'img/avatars/' . $nombreArchivo;
$conexion = conexionBD();
if (is_array($conexion)) {
return $conexion;
}
try {
$sql = "UPDATE usuario
SET avatar = :avatar
WHERE idUsuario = :id";
$stmt = $conexion->prepare($sql);
$stmt->execute([
':avatar' => $rutaAvatar,
':id' => $this->idUsuario
]);
// Actualizamos también el objeto actual
$this->avatar = $rutaAvatar;
return [
'exito' => 'Avatar actualizado correctamente.',
'avatar' => $rutaAvatar
];
} catch (PDOException $error) {
return [
'error' => 'Ocurrió un error al actualizar el avatar.',
'error_tecnico' => $error->getMessage()
];
}
}
public static function obtenerRanking($limite = 10) {
try {
$conexion = conexionBD();
if (is_array($conexion)) {
return [];
}
$sql = "SELECT
idUsuario,
nombreUsuario,
avatar,
aciertos,
victorias,
derrotas,
CASE
WHEN (victorias + derrotas) > 0
THEN ROUND((victorias / (victorias + derrotas)) * 100, 0)
ELSE 0
END AS porcentajeVictoria
FROM usuario
ORDER BY victorias DESC, aciertos DESC
LIMIT " . (int)$limite;
$stmt = $conexion->prepare($sql);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
return [];
}
}
}
+48 -5
View File
@@ -7,26 +7,39 @@ require_once '../clases/ClaseEquipoxUsuario.php';
switch ($_POST['orden']) {
case 'registrarUsuarioEnEquipo':
if (!isset($_SESSION['idUsuario'])) {
echo json_encode([
'error' => 'No hay una sesión activa de usuario. Por favor, inicie sesión.'
]);
break;
}
$idUsuario = $_SESSION['idUsuario'];
$idEquipo = intval($_POST['idEquipo'] ?? 0);
break;
if ($idEquipo <= 0) {
echo json_encode([
'error' => 'El ID del equipo proporcionado no es válido.'
]);
break;
}
$equipoxusuario = new EquipoxUsuario();
$resultado = $equipoxusuario->registrarUsuarioEnEquipo($idEquipo, $idUsuario);
$equipoxusuario = new EquipoxUsuario(
null,
$idUsuario,
$idEquipo
);
$resultado = $equipoxusuario->registrarUsuarioEnEquipo();
echo json_encode($resultado);
break;
case 'listarUsuariosPorEquipo':
$idEquipo = intval($_POST['idEquipo'] ?? 0);
@@ -36,12 +49,42 @@ switch($_POST['orden']){
}
$equipoxusuario = new EquipoxUsuario();
$listado = $equipoxusuario->listarUsuariosPorEquipo($idEquipo);
break;
//break;
echo json_encode($listado);
break;
case 'obtenerSalaUsuario':
if (!isset($_SESSION['idUsuario'])) {
echo json_encode([
'error' => 'No hay una sesión activa de usuario.'
]);
break;
}
$idUsuario = $_SESSION['idUsuario'];
?>
$equipoxusuario = new EquipoxUsuario();
$resultado =
$equipoxusuario->obtenerSalaUsuario($idUsuario);
echo json_encode($resultado);
break;
case 'salirDeSala':
if (!isset($_SESSION['idUsuario'])) {
echo json_encode(['error' => 'Usuario no autenticado']);
exit;
}
$idUsuario = $_SESSION['idUsuario'];
$respuesta = EquipoxUsuario::salirDeSala($idUsuario);
echo json_encode($respuesta);
break;
}
+140 -16
View File
@@ -3,11 +3,9 @@
session_start();
require_once '../clases/ClasePartida.php';
require_once '../clases/ClaseEquipo.php';
require_once '../clases/ClaseEquipoxUsuario.php';
require_once '../clases/ClaseEquipoxPartida.php';
switch ($_POST['orden']) {
@@ -55,7 +53,6 @@ switch ($_POST['orden']) {
// Comprobamos que haya un usuario conectado
if (!isset($_SESSION['idUsuario'])) {
echo json_encode([
@@ -66,9 +63,7 @@ switch ($_POST['orden']) {
}
//Comprobamos que se haya introducido un nombre
// Comprobamos el nombre de la partida
if (
!isset($_POST['nombrePartida']) ||
@@ -83,26 +78,155 @@ switch ($_POST['orden']) {
}
// Comprobamos los nombres de los equipos
if (
!isset($_POST['nombreEquipo1']) ||
trim($_POST['nombreEquipo1']) === '' ||
!isset($_POST['nombreEquipo2']) ||
trim($_POST['nombreEquipo2']) === ''
) {
echo json_encode([
'error' => 'Los nombres de los equipos son obligatorios.'
]);
break;
}
//Creamos la partida
/*
* ==========================================
* 1. CREAMOS LA PARTIDA
* ==========================================
*/
$partida = new Partida();
$partida->nombrePartida = trim($_POST['nombrePartida']);
//El usuario conectado será el propietario de la partida.
// El usuario conectado será el propietario
$partida->idUsuario = $_SESSION['idUsuario'];
$resultadoPartida = $partida->insertar();
$resultado = $partida->insertar();
echo json_encode($resultado);
if (isset($resultadoPartida['error'])) {
echo json_encode($resultadoPartida);
break;
}
$idPartida = (int)$resultadoPartida['exito_tecnico'];
/*
* ==========================================
* 2. CREAMOS EL EQUIPO 1
* ==========================================
*/
$equipo1 = new Equipo();
$equipo1->nombreEquipo = trim($_POST['nombreEquipo1']);
$resultadoEquipo1 = $equipo1->crear();
if (isset($resultadoEquipo1['error'])) {
echo json_encode($resultadoEquipo1);
break;
}
/*
* ==========================================
* 3. CREAMOS EL EQUIPO 2
* ==========================================
*/
$equipo2 = new Equipo();
$equipo2->nombreEquipo = trim($_POST['nombreEquipo2']);
$resultadoEquipo2 = $equipo2->crear();
if (isset($resultadoEquipo2['error'])) {
echo json_encode($resultadoEquipo2);
break;
}
/*
* ==========================================
* 3. INSERTAMOS LOS EQUIPOS CON SU PARTIDA EN EQUIPOXPARTIDA
* ==========================================
*/
$relacionEquipo1 = new EquipoxPartida(
null,
$equipo1->idEquipo,
$idPartida
);
$resultadoRelacion1 = $relacionEquipo1->insertar();
$relacionEquipo2 = new EquipoxPartida(
null,
$equipo2->idEquipo,
$idPartida
);
$resultadoRelacion2 = $relacionEquipo2->insertar();
/*
* ==========================================
* 4. ASIGNAMOS EL USUARIO AL EQUIPO 1
* ==========================================
*/
$usuarioEquipo = new EquipoxUsuario(
null,
$_SESSION['idUsuario'],
$equipo1->idEquipo
);
$resultadoUsuarioEquipo =
$usuarioEquipo->registrarUsuarioEnEquipo();
if (isset($resultadoUsuarioEquipo['error'])) {
echo json_encode($resultadoUsuarioEquipo);
break;
}
/*
* ==========================================
* TODO CORRECTO
* ==========================================
*/
echo json_encode([
'exito' => 'Sala creada correctamente.',
'idPartida' => $resultadoPartida['exito_tecnico'],
'idEquipo1' => $equipo1->idEquipo,
'idEquipo2' => $equipo2->idEquipo
]);
break;
+106 -6
View File
@@ -3,6 +3,7 @@
session_start();
require_once '../clases/ClasePregunta.php';
require_once '../clases/ClaseRespuesta.php';
switch ($_POST['orden']) {
@@ -11,16 +12,116 @@ switch ($_POST['orden']) {
$idCategoria = intval($_POST['idCategoria'] ?? 0);
$nombrePregunta = trim($_POST['nombrePregunta'] ?? '');
if ($idCategoria <= 0 || $nombrePregunta == '') {
echo json_encode(['error' => 'La categoría y el texto de la pregunta son obligatorios']);
$respuestaCorrecta = trim($_POST['respuestaCorrecta'] ?? '');
$respuestaIncorrecta1 = trim($_POST['respuestaIncorrecta1'] ?? '');
$respuestaIncorrecta2 = trim($_POST['respuestaIncorrecta2'] ?? '');
$respuestaIncorrecta3 = trim($_POST['respuestaIncorrecta3'] ?? '');
// Comprobamos los datos
if (
$idCategoria <= 0 ||
$nombrePregunta === '' ||
$respuestaCorrecta === '' ||
$respuestaIncorrecta1 === '' ||
$respuestaIncorrecta2 === '' ||
$respuestaIncorrecta3 === ''
) {
echo json_encode([
'error' => 'La categoría, la pregunta y todas las respuestas son obligatorias.'
]);
break;
}
$pregunta = new Pregunta($idCategoria, $nombrePregunta);
$resultado = $pregunta->guardar();
echo json_encode($resultado);
/*
* ==========================================
* 1. CREAMOS LA PREGUNTA
* ==========================================
*/
$pregunta = new Pregunta(
$idCategoria,
$nombrePregunta
);
$resultadoPregunta = $pregunta->guardar();
if (isset($resultadoPregunta['error'])) {
echo json_encode($resultadoPregunta);
break;
}
// Obtenemos el ID de la pregunta creada
$idPregunta = (int)$resultadoPregunta['exito_tecnico'];
/*
* ==========================================
* 2. CREAMOS LAS RESPUESTAS
* ==========================================
*/
$respuestas = [
[
'texto' => $respuestaCorrecta,
'correcta' => 1
],
[
'texto' => $respuestaIncorrecta1,
'correcta' => 0
],
[
'texto' => $respuestaIncorrecta2,
'correcta' => 0
],
[
'texto' => $respuestaIncorrecta3,
'correcta' => 0
]
];
foreach ($respuestas as $respuesta) {
$objRespuesta = new Respuesta(
null,
$idPregunta,
$respuesta['texto'],
$respuesta['correcta']
);
$resultadoRespuesta = $objRespuesta->insertar();
if (isset($resultadoRespuesta['error'])) {
echo json_encode($resultadoRespuesta);
break 2;
}
}
/*
* ==========================================
* 3. TODO CORRECTO
* ==========================================
*/
echo json_encode([
'exito' => 'Pregunta creada correctamente.',
'idPregunta' => $idPregunta
]);
break;
case 'obtenerPreguntasPorCategoria':
@@ -49,5 +150,4 @@ switch ($_POST['orden']) {
echo json_encode($listado);
break;
}
+166
View File
@@ -0,0 +1,166 @@
<?php
session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/triviagmatico/includes/conexionBD.php';
header('Content-Type: application/json; charset=utf-8');
if (!isset($_SESSION['idUsuario'])) {
echo json_encode(['error' => 'Sesión no iniciada']);
exit;
}
$idPartida = intval($_POST['idPartida'] ?? 0);
$orden = $_POST['orden'] ?? '';
if ($idPartida <= 0) {
echo json_encode(['error' => 'Partida no válida']);
exit;
}
$conexion = conexionBD();
if (is_array($conexion)) {
echo json_encode($conexion);
exit;
}
switch ($orden) {
case 'comprobarEstado':
try {
// Contar jugadores totales apuntados en los equipos de esta partida
$stmt = $conexion->prepare("
SELECT COUNT(exu.idUsuario) AS total_jugadores
FROM equipoxpartida exp
INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo
WHERE exp.idPartida = :idPartida
");
$stmt->execute([':idPartida' => $idPartida]);
$totalJugadores = (int)$stmt->fetchColumn();
$preguntasTotalesEsperadas = $totalJugadores * 10;
// Contar respuestas dadas en la partida
$stmtRespuestas = $conexion->prepare("
SELECT COUNT(*)
FROM respuestaalmacenada ra
INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta
WHERE pxp.idPartida = :idPartida
");
$stmtRespuestas->execute([':idPartida' => $idPartida]);
$respuestasRespondidas = (int)$stmtRespuestas->fetchColumn();
$terminada = ($respuestasRespondidas >= $preguntasTotalesEsperadas && $preguntasTotalesEsperadas > 0);
// Cuando la partida finaliza, se actualizan los históricos
if ($terminada && !isset($_SESSION['partidas_procesadas'][$idPartida])) {
$conexion->beginTransaction();
// CÁLCULO DE VELOCIDAD PREGUNTA A PREGUNTA EN SESIÓN
if (!isset($_SESSION['primeros_en_acertar'][$idPartida])) {
$_SESSION['primeros_en_acertar'][$idPartida] = [];
}
// Vemos quién fue el primero
$stmtVelocidad = $conexion->prepare("
SELECT ra.idPartidaxPregunta, ra.idUsuario
FROM respuestaalmacenada ra
INNER JOIN respuesta r ON ra.idRespuesta = r.idRespuesta
INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta
WHERE pxp.idPartida = :idPartida AND r.correcta = 1
ORDER BY ra.idRespuestaAlmacenada ASC
");
$stmtVelocidad->execute([':idPartida' => $idPartida]);
$todosLosAciertos = $stmtVelocidad->fetchAll(PDO::FETCH_ASSOC);
foreach ($todosLosAciertos as $acierto) {
$idPxp = $acierto['idPartidaxPregunta'];
$idU = $acierto['idUsuario'];
if (!isset($_SESSION['primeros_en_acertar'][$idPartida][$idPxp])) {
$_SESSION['primeros_en_acertar'][$idPartida][$idPxp] = $idU;
}
}
// Actualizamos la base de datos
// Buscamos los aciertos de cada jugador en la partida actual
$stmtAciertos = $conexion->prepare("
SELECT ra.idUsuario, exu.idEquipo, COUNT(*) as aciertos_partida
FROM respuestaalmacenada ra
INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta
INNER JOIN respuesta r ON ra.idRespuesta = r.idRespuesta
INNER JOIN equipoxusuario exu ON ra.idUsuario = exu.idUsuario
WHERE pxp.idPartida = :idPartida AND r.correcta = 1
GROUP BY ra.idUsuario
");
$stmtAciertos->execute([':idPartida' => $idPartida]);
$jugadoresPartida = $stmtAciertos->fetchAll(PDO::FETCH_ASSOC);
$updateAciertosGlobales = $conexion->prepare("
UPDATE usuario
SET aciertos = aciertos + :nuevos_aciertos
WHERE idUsuario = :idUsuario
");
$puntosEquipos = [];
foreach ($jugadoresPartida as $jp) {
$idU = (int)$jp['idUsuario'];
$idE = (int)$jp['idEquipo'];
$nuevosAciertos = (int)$jp['aciertos_partida'];
// Sumamos los aciertos al perfil del usuario
$updateAciertos->execute([
':nuevos_aciertos' => $nuevosAciertos,
':idUsuario' => $idU
]);
if (!isset($puntosEquipos[$idE])) {
$puntosEquipos[$idE] = 0;
}
$puntosEquipos[$idE] += $nuevosAciertos;
}
// Determinamos qué equipo ha obtenido más aciertos en la partida
arsort($puntosEquipos);
$idEquipoGanador = key($puntosEquipos);
// Obtenemos todos los usuarios de la partida para asignar victorias/derrotas
$stmtMiembros = $conexion->prepare("
SELECT exu.idUsuario, exu.idEquipo
FROM equipoxpartida exp
INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo
WHERE exp.idPartida = :idPartida
");
$stmtMiembros->execute([':idPartida' => $idPartida]);
$todosLosMiembros = $stmtMiembros->fetchAll(PDO::FETCH_ASSOC);
$updateVictoria = $conexion->prepare("UPDATE usuario SET victorias = victorias + 1 WHERE idUsuario = :idUsuario");
$updateDerrota = $conexion->prepare("UPDATE usuario SET derrotas = derrotas + 1 WHERE idUsuario = :idUsuario");
foreach ($todosLosMiembros as $miembro) {
$idU = (int)$miembro['idUsuario'];
$idE = (int)$miembro['idEquipo'];
if ($idE === $idEquipoGanador) {
$updateVictoria->execute([':idUsuario' => $idU]);
} else {
$updateDerrota->execute([':idUsuario' => $idU]);
}
}
$conexion->commit();
$_SESSION['partidas_procesadas'][$idPartida] = true;
}
echo json_encode(['terminada' => $terminada]);
} catch (PDOException $e) {
if ($conexion->inTransaction()) {
$conexion->rollBack();
}
echo json_encode(['error' => $e->getMessage()]);
}
break;
default:
echo json_encode(['error' => 'Acción no permitida']);
break;
}
+165 -1
View File
@@ -35,7 +35,8 @@ switch ($_POST['orden']) {
$usuario = new Usuario(
$nombreUsuario,
$contrasena,
$email
$email,
'img/avatars/defaultProfile.jpeg'
);
$resultado = $usuario->registrar();
@@ -54,6 +55,12 @@ switch ($_POST['orden']) {
if ($resultado instanceof Usuario) {
// === AÑADIR ESTAS LÍNEAS PARA GUARDAR EN SESIÓN ===
$_SESSION['idUsuario'] = $resultado->getIdUsuario();
$_SESSION['nombreUsuario'] = $resultado->getNombreUsuario();
$_SESSION['email'] = $resultado->getEmail();
// =================================================
echo json_encode([
'exito' => 'Login correcto',
'idUsuario' => $resultado->getIdUsuario(),
@@ -85,4 +92,161 @@ switch ($_POST['orden']) {
]);
break;
case 'mostrarEstadisticas':
$usuario = Usuario::buscarPorId($_SESSION['idUsuario']);
if ($usuario instanceof Usuario) {
echo json_encode([
'victorias' => $usuario->getVictorias(),
'derrotas' => $usuario->getDerrotas(),
'aciertos' => $usuario->getAciertos()
]);
} else {
echo json_encode($usuario);
}
break;
case 'cambiarNombre':
if (!isset($_SESSION['idUsuario'])) {
echo json_encode([
'error' => 'No hay ningún usuario conectado.'
]);
break;
}
$nuevoNombre = trim($_POST['nombreUsuario'] ?? '');
if ($nuevoNombre === '') {
echo json_encode([
'error' => 'El nombre no puede estar vacío.'
]);
break;
}
$usuario = Usuario::buscarPorId($_SESSION['idUsuario']);
if (!($usuario instanceof Usuario)) {
echo json_encode([
'error' => 'No se encontró el usuario.'
]);
break;
}
$resultado = $usuario->cambiarNombre($nuevoNombre);
if (isset($resultado['error'])) {
echo json_encode($resultado);
} else {
// Actualizamos también la sesión
$_SESSION['nombreUsuario'] = $nuevoNombre;
echo json_encode([
'exito' => 'Nombre actualizado correctamente.',
'nombreUsuario' => $nuevoNombre
]);
}
break;
case 'cambiarAvatar':
if (!isset($_SESSION['idUsuario'])) {
echo json_encode([
'error' => 'No hay ningún usuario conectado.'
]);
break;
}
if (!isset($_FILES['avatar']) || $_FILES['avatar']['error'] !== UPLOAD_ERR_OK) {
echo json_encode([
'error' => 'No se ha recibido ninguna imagen.'
]);
break;
}
$archivo = $_FILES['avatar'];
$tipo = mime_content_type($archivo['tmp_name']);
$tiposPermitidos = [
'image/jpeg',
'image/png',
'image/gif',
'image/webp'
];
if (!in_array($tipo, $tiposPermitidos)) {
echo json_encode([
'error' => 'El formato de imagen no es válido.'
]);
break;
}
$usuario = Usuario::buscarPorId($_SESSION['idUsuario']);
if (!($usuario instanceof Usuario)) {
echo json_encode([
'error' => 'No se encontró el usuario.'
]);
break;
}
$resultado = $usuario->cambiarAvatar($archivo);
if (isset($resultado['error'])) {
echo json_encode($resultado);
} else {
// Actualizamos también la sesión
$_SESSION['avatar'] = $resultado['avatar'];
echo json_encode($resultado);
}
break;
case 'obtenerRanking':
$ranking = Usuario::obtenerRanking(5); //Cambiar para mostrar X jugadores en index
echo json_encode([
'exito' => true,
'ranking' => $ranking
]);
break;
case 'comprobarSesion':
if (isset($_SESSION['idUsuario']) && !empty($_SESSION['idUsuario'])) {
echo json_encode([
'activa' => true,
'usuario' => [
'idUsuario' => $_SESSION['idUsuario'],
'nombreUsuario' => $_SESSION['nombreUsuario'] ?? ''
]
]);
} else {
echo json_encode(['activa' => false]);
}
break;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.6 KiB

+10 -11
View File
@@ -1,32 +1,30 @@
<?php
include 'cabecera.php';
?>
<!DOCTYPE html>
<html lang="es-ES">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Triviagmático</title>
<link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg">
</head>
<body>
<?php include 'cabecera.php'; ?>
<div class="container my-5">
<div class="row justify-content-center align-items-center g-4">
<!-- Botón Jugar (solo se muestra si está logueado) -->
<?php if ($isLoggedIn): ?>
<div class="col-12 col-lg-5 col-xl-4">
<!-- Botón Jugar (oculto por defecto, JS lo muestra si hay sesión activa) -->
<div class="col-12 col-lg-5 col-xl-4 d-none" id="colBotonJugar">
<a href="buscadorSala.php" class="btn btn-play-kahoot" id="btnJugar">
<i class="fa-solid fa-play"></i>
<span>¡JUGAR!</span>
</a>
</div>
<?php endif; ?>
<!-- Ranking -->
<div class="col-12 <?= $isLoggedIn ? 'col-lg-7 col-xl-8' : 'col-lg-8' ?>">
<div class="col-12 col-lg-8" id="colRanking">
<div class="card ranking-card">
<div class="ranking-header">
<h3 class="m-0"><i class="fa-solid fa-trophy me-2"></i> RANKING GLOBAL DE JUGADORES</h3>
@@ -47,6 +45,7 @@ include 'cabecera.php';
<!-- JS de Bootstrap -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
+366 -65
View File
@@ -1,79 +1,380 @@
const btnCrearSala = document.getElementById("btnCrearSala");
let usuarioYaEstaEnEquipo = false;
const nombreSala = document.getElementById("nombreSala");
const nombreEquipo1 = document.getElementById("nombreEquipo1");
const nombreEquipo2 = document.getElementById("nombreEquipo2");
$(document).ready(function () {
comprobarSalaUsuario();
});
btnCrearSala.addEventListener("click", function () {
limpiarErrores();
// 1. Comprobar si el usuario actual ya pertenece a una sala
function comprobarSalaUsuario() {
$("#cargandoSalas").remove();
const sala = nombreSala.value.trim();
const equipo1 = nombreEquipo1.value.trim();
const equipo2 = nombreEquipo2.value.trim();
let formularioValido = true;
if (sala === "") {
mostrarError(nombreSala, "El nombre de la sala es obligatorio.");
formularioValido = false;
$.ajax({
url: "controladores/ControladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: { orden: "obtenerSalaUsuario" },
success: function (respuesta) {
if (respuesta.error || !respuesta.asociado) {
usuarioYaEstaEnEquipo = false;
$("#contenedorCrearSala").show();
cargarSalas();
} else {
usuarioYaEstaEnEquipo = true;
$("#contenedorCrearSala").hide(); // Ocultar "Crear Sala" si ya pertenece a una
cargarSalaUsuario(respuesta.idPartida);
}
},
error: function (xhr, status, error) {
console.error("Error al comprobar la sala del usuario:", error);
usuarioYaEstaEnEquipo = false;
cargarSalas();
},
});
}
if (equipo1 === "") {
mostrarError(nombreEquipo1, "El nombre del equipo 1 es obligatorio.");
formularioValido = false;
// 2. Cargar únicamente la sala en la que está metido el usuario
function cargarSalaUsuario(idPartida) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: { orden: "buscar", idPartida: idPartida },
success: function (partida) {
if (partida.error) {
console.error(partida.error);
return;
}
$("#contenedorSalas").empty();
cargarInformacionSala(partida);
},
error: function (xhr, status, error) {
console.error("Error al obtener la sala del usuario:", error);
},
});
}
if (equipo2 === "") {
mostrarError(nombreEquipo2, "El nombre del equipo 2 es obligatorio.");
// 3. Cargar la lista completa de todas las salas
function cargarSalas() {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: { orden: "listar" },
success: function (partidas) {
const contenedor = $("#contenedorSalas");
contenedor.empty();
formularioValido = false;
}
if (!formularioValido) {
if (!Array.isArray(partidas) || partidas.length === 0) {
contenedor.html(`
<div class="col-12 text-center">
<p class="text-muted">No hay salas disponibles actualmente.</p>
</div>
`);
return;
}
console.log("Sala:", sala);
console.log("Equipo 1:", equipo1);
console.log("Equipo 2:", equipo2);
const idSala = 1;
//TODO aqui va la peticion ayax en el futuro para crear la sala en la bbdd
window.location.href = "sala.html?id=" + idSala;
partidas.forEach(function (partida) {
cargarInformacionSala(partida);
});
function mostrarError(input, mensaje) {
input.classList.add("is-invalid");
// Comprobamos si ya existe un mensaje
let mensajeError = input.parentElement.querySelector(".invalid-feedback");
if (!mensajeError) {
mensajeError = document.createElement("div");
mensajeError.classList.add("invalid-feedback");
input.parentElement.appendChild(mensajeError);
}
mensajeError.textContent = mensaje;
}
function limpiarErrores() {
const inputs = [nombreSala, nombreEquipo1, nombreEquipo2];
inputs.forEach((input) => {
input.classList.remove("is-invalid");
const mensajeError = input.parentElement.querySelector(".invalid-feedback");
if (mensajeError) {
mensajeError.remove();
}
},
error: function (xhr, status, error) {
console.error("Error al obtener las partidas:", error);
},
});
}
// 4. Obtener equipos y jugadores asociados a una sala concreta
function cargarInformacionSala(partida) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: { orden: "getEquipos", idPartida: partida.idPartida },
success: function (equipos) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: { orden: "getJugadores", idPartida: partida.idPartida },
success: function (jugadores) {
mostrarSala(partida, equipos, jugadores);
},
error: function (xhr, status, error) {
console.error("Error al obtener jugadores:", error);
},
});
},
error: function (xhr, status, error) {
console.error("Error al obtener equipos:", error);
},
});
}
// 5. Renderizar el HTML de la sala y botones según estado
function mostrarSala(partida, equipos, jugadores) {
const contenedor = $("#contenedorSalas");
let equiposHTML = "";
equipos.forEach(function (equipo) {
const jugadoresEquipo = jugadores.filter(function (jugador) {
return jugador.idEquipo == equipo.idEquipo;
});
let jugadoresHTML = "";
if (jugadoresEquipo.length > 0) {
jugadoresEquipo.forEach(function (jugador) {
jugadoresHTML += `
<div class="jugador">
<span class="avatar">👤</span>
${escapeHTML(jugador.nombreUsuario)}
</div>
`;
});
} else {
jugadoresHTML = `<div class="text-muted small">Sin jugadores</div>`;
}
// Botón "Unirse" solo visible si NO pertenece a ningún equipo
let botonUnirseHTML = "";
if (!usuarioYaEstaEnEquipo) {
botonUnirseHTML = `
<button type="button" class="btn btn-unirse w-100 btn-unirse-equipo mt-2"
data-id-partida="${partida.idPartida}"
data-id-equipo="${equipo.idEquipo}">
Unirse
</button>
`;
}
equiposHTML += `
<div class="equipo me-2 ms-2 p-3 border rounded">
<h6>${escapeHTML(equipo.nombreEquipo)}</h6>
<div class="jugadores mb-2">
${jugadoresHTML}
</div>
${botonUnirseHTML}
</div>
`;
});
// Acciones disponibles si el usuario YA ESTÁ dentro de esta sala
let accionesSalaHTML = "";
if (usuarioYaEstaEnEquipo) {
accionesSalaHTML = `
<div class="sala-acciones text-center mt-4 pt-3 border-top d-flex justify-content-center gap-3">
<button type="button" class="btn btn-outline-danger btn-abandonar-sala" data-id-partida="${partida.idPartida}">
Abandonar sala
</button>
<a href="juego.php?idPartida=${partida.idPartida}" class="btn btn-success btn-lg px-4">
🎮 ¡Iniciar Partida!
</a>
</div>
`;
}
const salaHTML = `
<div class="col-12 col-md-10 col-lg-8">
<div class="sala card p-3 shadow-sm mb-4">
<div class="sala-header h4 text-center mb-3">
${escapeHTML(partida.nombrePartida)}
</div>
<div class="sala-body">
<div class="equipos d-flex justify-content-around">
${equiposHTML}
</div>
${accionesSalaHTML}
</div>
</div>
</div>
`;
contenedor.append(salaHTML);
}
// 6. Evento: Unirse a un Equipo
$(document).on("click", ".btn-unirse-equipo", function () {
const boton = $(this);
const idEquipo = boton.data("id-equipo");
const idPartida = boton.data("id-partida");
boton.prop("disabled", true).text("Uniéndose...");
$.ajax({
url: "controladores/ControladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: {
orden: "registrarUsuarioEnEquipo",
idEquipo: idEquipo,
},
success: function (respuesta) {
if (respuesta.error) {
alert(respuesta.error);
boton.prop("disabled", false).text("Unirse");
return;
}
usuarioYaEstaEnEquipo = true;
$("#contenedorCrearSala").hide();
$("#contenedorSalas").empty();
cargarSalaUsuario(idPartida);
},
error: function (xhr, status, error) {
console.error("Error al unirse al equipo:", error);
alert("No se ha podido unir al equipo.");
boton.prop("disabled", false).text("Unirse");
},
});
});
// 7. Evento: Abandonar Sala
// Guardamos temporalmente el botón presionado
let botonAbandonarReferencia = null;
// A. Al hacer clic en el botón "Abandonar sala" de la tarjeta, abrimos el modal
$(document).on("click", ".btn-abandonar-sala", function () {
botonAbandonarReferencia = $(this);
const modal = new bootstrap.Modal(document.getElementById('modalAbandonarSala'));
modal.show();
});
// B. Al hacer clic en "Sí, salir" dentro del modal Kahoot
$(document).on("click", "#btnConfirmarAbandonar", function () {
const modalEl = document.getElementById('modalAbandonarSala');
const modalInstance = bootstrap.Modal.getInstance(modalEl);
const btnConfirmar = $(this);
btnConfirmar.prop("disabled", true).text("Saliendo...");
$.ajax({
url: "controladores/ControladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: { orden: "salirDeSala" },
success: function (respuesta) {
btnConfirmar.prop("disabled", false).text("Sí, salir");
if (modalInstance) {
modalInstance.hide();
}
if (respuesta.error) {
alert(respuesta.error);
return;
}
// Restablecemos la interfaz a la lista completa de salas
usuarioYaEstaEnEquipo = false;
$("#contenedorCrearSala").show();
cargarSalas();
},
error: function (xhr, status, error) {
console.error("Error al salir de la sala:", error);
alert("No se pudo salir de la sala.");
btnConfirmar.prop("disabled", false).text("Sí, salir");
if (modalInstance) {
modalInstance.hide();
}
}
});
});
// 8. Evento: Crear Sala
$("#btnCrearSala").on("click", function () {
const nombreSala = $("#nombreSala").val().trim();
const nombreEquipo1 = $("#nombreEquipo1").val().trim();
const nombreEquipo2 = $("#nombreEquipo2").val().trim();
let valido = true;
$(".mensaje-error-sala").remove();
$(".input-kahoot").removeClass("is-invalid");
if (nombreSala === "" || nombreSala.length < 3) {
mostrarError(
"#nombreSala",
"El nombre de la sala debe tener al menos 3 caracteres.",
);
valido = false;
}
if (nombreEquipo1 === "" || nombreEquipo1.length < 2) {
mostrarError(
"#nombreEquipo1",
"El nombre del equipo debe tener al menos 2 caracteres.",
);
valido = false;
}
if (nombreEquipo2 === "" || nombreEquipo2.length < 2) {
mostrarError(
"#nombreEquipo2",
"El nombre del equipo debe tener al menos 2 caracteres.",
);
valido = false;
}
if (
nombreEquipo1 !== "" &&
nombreEquipo2 !== "" &&
nombreEquipo1.toLowerCase() === nombreEquipo2.toLowerCase()
) {
mostrarError(
"#nombreEquipo2",
"Los dos equipos deben tener nombres diferentes.",
);
valido = false;
}
if (!valido) return;
const boton = $("#btnCrearSala");
boton.prop("disabled", true).text("Creando sala...");
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "crear",
nombrePartida: nombreSala,
nombreEquipo1: nombreEquipo1,
nombreEquipo2: nombreEquipo2,
},
success: function (respuesta) {
if (respuesta.error) {
alert(respuesta.error);
boton.prop("disabled", false).text("Crear sala");
return;
}
if (respuesta.exito) {
$("#modalCrearSala").modal("hide");
location.reload();
}
},
error: function (xhr, status, error) {
console.error("Error al crear la sala:", error);
alert("No se ha podido crear la sala.");
boton.prop("disabled", false).text("Crear sala");
},
});
});
// Auxiliares
function escapeHTML(texto) {
return $("<div>")
.text(texto ?? "")
.html();
}
function mostrarError(selector, mensaje) {
const input = $(selector);
input.addClass("is-invalid");
input.after(
`<div class="mensaje-error-sala text-danger mt-1 small">${mensaje}</div>`,
);
}
$(document).on("input", ".input-kahoot", function () {
$(this).removeClass("is-invalid");
$(this).next(".mensaje-error-sala").remove();
});
+216
View File
@@ -0,0 +1,216 @@
$(document).ready(function () {
// Comprobar la sesión activa al cargar la página
comprobarEstadoSesion();
// Evento Click: Login
$('#botonAceptarLogin').on('click', function () {
ejecutarLogin();
});
// Permitir Submit con tecla Enter en el formulario de Login
$('#formLogin').on('submit', function (e) {
e.preventDefault();
ejecutarLogin();
});
// Evento Click: Registro
$('#botonAceptarRegistro').on('click', function () {
ejecutarRegistro();
});
// Permitir Submit con tecla Enter en el formulario de Registro
$('#formRegistro').on('submit', function (e) {
e.preventDefault();
ejecutarRegistro();
});
});
/**
* Comprueba con el servidor si existe una sesión PHP activa.
*/
function comprobarEstadoSesion() {
$.ajax({
url: 'controladores/controladorUsuario.php',
type: 'POST',
dataType: 'json',
data: { orden: 'comprobarSesion' },
success: function (respuesta) {
if (respuesta.activa) {
renderizarCabeceraConSesion(respuesta.usuario);
// Si existe el contenedor del botón Jugar en index, lo mostramos
$('#colBotonJugar').removeClass('d-none');
} else {
renderizarCabeceraSinSesion();
$('#colBotonJugar').addClass('d-none');
}
},
error: function () {
renderizarCabeceraSinSesion();
}
});
}
/**
* Petición AJAX para iniciar sesión
*/
function ejecutarLogin() {
let email = $('#loginEmail').val().trim();
let contrasena = $('#loginPassword').val().trim();
$('#errorLogin').text('');
if (email === '' || contrasena === '') {
$('#errorLogin').text('Por favor, rellena todos los campos.');
return;
}
$.ajax({
url: 'controladores/controladorUsuario.php',
type: 'POST',
dataType: 'json',
data: {
orden: 'comprobarUsuario',
email: email,
contrasena: contrasena
},
success: function (respuesta) {
if (respuesta.error) {
$('#errorLogin').text(respuesta.error);
} else if (respuesta.exito) {
$('#modalLogin').modal('hide');
$('#formLogin')[0].reset();
renderizarCabeceraConSesion({
idUsuario: respuesta.idUsuario,
nombreUsuario: respuesta.nombreUsuario,
avatar: respuesta.avatar
});
$('#colBotonJugar').removeClass('d-none');
}
},
error: function () {
$('#errorLogin').text('Error al conectar con el servidor.');
}
});
}
/**
* Petición AJAX para registrar un usuario
*/
function ejecutarRegistro() {
let nombre = $('#regNombre').val().trim();
let email = $('#regEmail').val().trim();
let pass = $('#regPassword').val().trim();
let passConfirm = $('#regPasswordConfirm').val().trim();
$('#errorRegistro').text('');
if (nombre === '' || email === '' || pass === '') {
$('#errorRegistro').text('Todos los campos son obligatorios.');
return;
}
if (pass !== passConfirm) {
$('#errorRegistro').text('Las contraseñas no coinciden.');
return;
}
$.ajax({
url: 'controladores/controladorUsuario.php',
type: 'POST',
dataType: 'json',
data: {
orden: 'registrarUsuario',
nombreUsuario: nombre,
email: email,
contrasena: pass
},
success: function (respuesta) {
if (respuesta.error) {
$('#errorRegistro').text(respuesta.error);
} else {
$('#modalRegistro').modal('hide');
$('#formRegistro')[0].reset();
// Autologin
$('#loginEmail').val(email);
$('#loginPassword').val(pass);
ejecutarLogin();
}
},
error: function () {
$('#errorRegistro').text('Error al procesar el registro.');
}
});
}
/**
* Petición AJAX para cerrar la sesión
*/
function cerrarSesion() {
$.ajax({
url: 'controladores/controladorUsuario.php',
type: 'POST',
dataType: 'json',
data: { orden: 'cerrarSesion' },
success: function () {
renderizarCabeceraSinSesion();
$('#colBotonJugar').addClass('d-none');
if (window.location.pathname.includes('perfil.php') || window.location.pathname.includes('buscadorSala.php')) {
window.location.href = 'index.php';
}
}
});
}
/**
* Renderiza la cabecera cuando HAY sesión iniciada (Menú Perfil + Avatar)
*/
function renderizarCabeceraConSesion(usuario) {
let avatarImg = usuario.avatar ? usuario.avatar : 'img/avatars/defaultProfile.jpeg';
let html = `
<div class="dropdown">
<button class="btn btn-outline-light dropdown-toggle d-flex align-items-center gap-2 rounded-pill px-3 py-1 fw-bold" type="button" id="userMenu" data-bs-toggle="dropdown" aria-expanded="false">
<img src="${avatarImg}" alt="Avatar" class="rounded-circle border" style="width: 32px; height: 32px; object-fit: cover;">
<span>${escapeHtml(usuario.nombreUsuario)}</span>
</button>
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2" aria-labelledby="userMenu">
<li>
<a class="dropdown-item py-2 fw-semibold" href="perfil.php">
<i class="fa-solid fa-user me-2 text-primary"></i>Mi Perfil
</a>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<button class="dropdown-item py-2 fw-semibold text-danger" onclick="cerrarSesion()">
<i class="fa-solid fa-right-from-bracket me-2"></i>Cerrar Sesión
</button>
</li>
</ul>
</div>
`;
$('#contenedorUsuarioCabecera').html(html);
}
/**
* Renderiza los botones originales:
* - "Iniciar Sesión" (Rojo -> btn-danger)
* - "Registrarse" (Verde -> btn-success)
*/
function renderizarCabeceraSinSesion() {
let html = `
<button class="btn btn-danger rounded-pill px-4 fw-bold shadow-sm" data-bs-toggle="modal" data-bs-target="#modalLogin">
<i class="fa-solid fa-right-to-bracket me-1"></i> Iniciar sesión
</button>
<button class="btn btn-success rounded-pill px-4 fw-bold shadow-sm" data-bs-toggle="modal" data-bs-target="#modalRegistro">
<i class="fa-solid fa-user-plus me-1"></i> Registrarse
</button>
`;
$('#contenedorUsuarioCabecera').html(html);
}
function escapeHtml(texto) {
return $('<div>').text(texto).html();
}
+95
View File
@@ -0,0 +1,95 @@
$(document).ready(function () {
cargarRanking();
});
function cargarRanking() {
$.ajax({
url: 'controladores/controladorUsuario.php',
type: 'POST',
data: { orden: 'obtenerRanking' },
dataType: 'json',
success: function (response) {
if (response.exito && response.ranking.length > 0) {
renderizarTablaRanking(response.ranking);
} else {
$('#ranking-container').html(`
<div class="alert alert-info my-3">
<i class="fa-solid fa-info-circle me-2"></i>Aún no hay partidas registradas para mostrar el ranking.
</div>
`);
}
},
error: function () {
$('#ranking-container').html(`
<div class="alert alert-danger my-3">
<i class="fa-solid fa-exclamation-triangle me-2"></i>Error al cargar la clasificación.
</div>
`);
}
});
}
function renderizarTablaRanking(jugadores) {
let html = `
<div class="table-responsive">
<table class="table table-striped table-hover align-middle mb-0 text-center">
<thead class="table-dark">
<tr>
<th scope="col" style="width: 10%;">#</th>
<th scope="col" class="text-start" style="width: 35%;">Jugador</th>
<th scope="col" style="width: 15%;"><i class="fa-solid fa-trophy text-warning me-1"></i> Vic</th>
<th scope="col" style="width: 15%;"><i class="fa-solid fa-xmark text-danger me-1"></i> Der</th>
<th scope="col" style="width: 15%;"><i class="fa-solid fa-bullseye text-success me-1"></i> Aciertos</th>
<th scope="col" style="width: 10%;"><i class="fa-solid fa-percent text-info me-1"></i> % Vic</th>
</tr>
</thead>
<tbody>
`;
jugadores.forEach((jugador, index) => {
let posicion = index + 1;
let medalla = '';
// Medallas para el Top 3
if (posicion === 1) {
medalla = '<i class="fa-solid fa-medal text-warning fa-lg" title="1º Puesto"></i>';
} else if (posicion === 2) {
medalla = '<i class="fa-solid fa-medal text-secondary fa-lg" title="2º Puesto"></i>';
} else if (posicion === 3) {
medalla = '<i class="fa-solid fa-medal text-brown fa-lg" style="color: #cd7f32;" title="3º Puesto"></i>';
} else {
medalla = `<span class="fw-bold text-muted">${posicion}</span>`;
}
let avatarImg = jugador.avatar ? jugador.avatar : 'img/avatars/defaultProfile.jpeg';
html += `
<tr>
<td class="fw-bold fs-5">${medalla}</td>
<td class="text-start fw-bold">
<img src="${avatarImg}" alt="Avatar" class="rounded-circle me-2 border" style="width: 32px; height: 32px; object-fit: cover;">
${escapeHtml(jugador.nombreUsuario)}
</td>
<td><span class="badge bg-success rounded-pill px-3 py-2 fs-6">${jugador.victorias}</span></td>
<td><span class="badge bg-danger rounded-pill px-3 py-2 fs-6">${jugador.derrotas}</span></td>
<td class="fw-bold text-primary fs-6">${jugador.aciertos}</td>
<td>
<span class="badge bg-info text-dark rounded-pill px-2 py-1">${jugador.porcentajeVictoria}%</span>
</td>
</tr>
`;
});
html += `
</tbody>
</table>
</div>
`;
$('#ranking-container').removeClass('text-center p-4 ranking-placeholder').html(html);
}
function escapeHtml(texto) {
return $('<div>').text(texto).html();
}
+219 -40
View File
@@ -1,74 +1,253 @@
// =========================
// MOSTRAR ESTADISTICAS
// =========================
$.ajax({
method: "POST",
url: "controladores/controladorUsuario.php",
data: {
orden: "mostrarEstadisticas",
},
}).done(function (respuesta) {
console.log(respuesta);
respuesta = JSON.parse(respuesta);
if (respuesta.error) {
console.log(respuesta.error);
} else {
$("#victorias").text(respuesta.victorias);
$("#derrotas").text(respuesta.derrotas);
$("#aciertos").text(respuesta.aciertos);
}
});
// =========================
// CAMBIAR NOMBRE
// =========================
function cambiarNombre() {
let nuevoNombre = $("#nuevoNombre").val().trim();
const input = document.getElementById("nuevoNombre");
const nombre = document.getElementById("nombre");
$.ajax({
method: "POST",
url: "controladores/controladorUsuario.php",
data: {
nombreUsuario: nuevoNombre,
orden: "cambiarNombre",
},
}).done(function (respuesta) {
console.log(respuesta);
respuesta = JSON.parse(respuesta);
if (respuesta.error) {
console.log(respuesta.error);
} else {
// Actualizamos el nombre mostrado en la página
$("#nombre").text(respuesta.nombreUsuario);
const nuevoNombre = input.value.trim();
if (nuevoNombre !== "") {
nombre.textContent = nuevoNombre;
input.value = "";
// Limpiamos el input
$("#nuevoNombre").val("");
}
});
}
// =========================
// BORRAR NOMBRE
// =========================
function borrarNombre() {
document.getElementById("nuevoNombre").value = "";
}
// =========================
// ABRIR SELECTOR DE IMAGEN
// =========================
function seleccionarFoto() {
document.getElementById("inputFoto").click();
}
// =========================
// CAMBIAR FOTO
// =========================
document.getElementById("inputFoto").addEventListener(
"change",
function(event) {
function seleccionarFoto() {
$("#inputFoto").click();
}
const archivo = event.target.files[0];
$("#inputFoto").change(function () {
let archivo = this.files[0];
if (archivo) {
if (!archivo) {
return;
}
// Comprobamos que sea una imagen
if (!archivo.type.startsWith("image/")) {
alert("El archivo seleccionado no es una imagen.");
alert("Por favor, selecciona una imagen.");
$("#inputFoto").val("");
return;
}
let datos = new FormData();
// Creamos una URL temporal
const imagenURL = URL.createObjectURL(archivo);
datos.append("avatar", archivo);
datos.append("orden", "cambiarAvatar");
// Cambiamos la foto
document.getElementById("fotoPerfil").src = imagenURL;
}
}
$.ajax({
method: "POST",
url: "controladores/controladorUsuario.php",
data: datos,
processData: false,
contentType: false,
}).done(function (respuesta) {
console.log(respuesta);
respuesta = JSON.parse(respuesta);
if (respuesta.error) {
alert(respuesta.error);
} else {
// Actualizamos la imagen sin recargar la página
$("#fotoPerfil").attr(
"src",
respuesta.avatar + "?t=" + new Date().getTime(),
);
}
});
});
// =========================
// RECOGER CATEGORIAS
// ====
$("#modalCrearPregunta").on("show.bs.modal", function () {
const selectCategoria = $("#idCategoria");
// Limpiamos las categorías anteriores
selectCategoria.empty();
// Opción inicial
selectCategoria.append('<option value="">Selecciona una categoría</option>');
$.ajax({
url: "controladores/controladorCategoria.php",
type: "POST",
dataType: "json",
data: {
orden: "listarCategorias",
},
success: function (respuesta) {
console.log("Categorías:", respuesta);
if (respuesta.error) {
alert(respuesta.error);
return;
}
$.each(respuesta, function (index, categoria) {
selectCategoria.append(
$("<option>", {
value: categoria.idCategoria,
text: categoria.nombreCategoria,
}),
);
});
},
error: function (xhr, status, error) {
console.error("Error al cargar las categorías:", error);
console.error("Respuesta del servidor:", xhr.responseText);
alert("No se han podido cargar las categorías.");
},
});
});
// =========================
// CREAR PREGUNTA
// ====
$("#formCrearPregunta").on("submit", function (e) {
e.preventDefault();
const boton = $("#btnCrearPregunta");
const pregunta = $("#pregunta").val().trim();
const respuestaCorrecta = $("#respuestaCorrecta").val().trim();
const respuestaIncorrecta1 = $("#respuestaIncorrecta1").val().trim();
const respuestaIncorrecta2 = $("#respuestaIncorrecta2").val().trim();
const respuestaIncorrecta3 = $("#respuestaIncorrecta3").val().trim();
// Comprobamos que no haya campos vacíos
if (
pregunta === "" ||
respuestaCorrecta === "" ||
respuestaIncorrecta1 === "" ||
respuestaIncorrecta2 === "" ||
respuestaIncorrecta3 === ""
) {
alert("Todos los campos son obligatorios.");
return;
}
boton.prop("disabled", true);
boton.text("Creando pregunta...");
$.ajax({
url: "controladores/controladorPregunta.php",
type: "POST",
dataType: "json",
data: {
orden: "crearPregunta",
idCategoria: $("#idCategoria").val(),
nombrePregunta: pregunta,
respuestaCorrecta: respuestaCorrecta,
respuestaIncorrecta1: respuestaIncorrecta1,
respuestaIncorrecta2: respuestaIncorrecta2,
respuestaIncorrecta3: respuestaIncorrecta3,
},
success: function (respuesta) {
console.log("Respuesta del servidor:", respuesta);
if (respuesta.error) {
alert(respuesta.error);
boton.prop("disabled", false);
boton.text("Crear pregunta");
return;
}
if (respuesta.exito) {
console.log("Pregunta creada:", respuesta.idPregunta);
// Cerramos el modal
$("#modalCrearPregunta").modal("hide");
// Limpiamos el formulario
$("#formCrearPregunta")[0].reset();
// Volvemos a activar el botón
boton.prop("disabled", false);
boton.text("Crear pregunta");
// Si tienes que actualizar la lista de preguntas:
// cargarPreguntas();
}
},
error: function (xhr, status, error) {
console.error("Error al crear la pregunta:", error);
console.error("Respuesta del servidor:", xhr.responseText);
alert("No se ha podido crear la pregunta.");
boton.prop("disabled", false);
boton.text("Crear pregunta");
},
});
});
+1
View File
@@ -6,6 +6,7 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
<title>Proyecto Trivial</title>
<link rel="stylesheet" href="css/juego.css">
<link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg">
</head>
<body>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

@@ -64,7 +64,7 @@ CREATE TABLE `equipo` (
`idEquipo` int(11) NOT NULL AUTO_INCREMENT,
`nombreEquipo` varchar(50) NOT NULL,
PRIMARY KEY (`idEquipo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -73,6 +73,11 @@ CREATE TABLE `equipo` (
LOCK TABLES `equipo` WRITE;
/*!40000 ALTER TABLE `equipo` DISABLE KEYS */;
INSERT INTO `equipo` VALUES
(1,'Los Trivialistas'),
(2,'Los Cerebritos'),
(3,'Los Sabios'),
(4,'Los Exploradores');
/*!40000 ALTER TABLE `equipo` ENABLE KEYS */;
UNLOCK TABLES;
@@ -92,7 +97,7 @@ CREATE TABLE `equipoxpartida` (
KEY `FK idPartida tabla partida` (`idPartida`),
CONSTRAINT `FK idEquipo tabla equipo` FOREIGN KEY (`idEquipo`) REFERENCES `equipo` (`idEquipo`),
CONSTRAINT `FK idPartida tabla partida` FOREIGN KEY (`idPartida`) REFERENCES `partida` (`idPartida`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -101,6 +106,13 @@ CREATE TABLE `equipoxpartida` (
LOCK TABLES `equipoxpartida` WRITE;
/*!40000 ALTER TABLE `equipoxpartida` DISABLE KEYS */;
INSERT INTO `equipoxpartida` VALUES
(1,1,1),
(2,1,2),
(3,2,2),
(4,2,3),
(5,3,3),
(6,3,4);
/*!40000 ALTER TABLE `equipoxpartida` ENABLE KEYS */;
UNLOCK TABLES;
@@ -120,7 +132,7 @@ CREATE TABLE `equipoxusuario` (
KEY `idEquipo` (`idEquipo`),
CONSTRAINT `equipoxusuario_ibfk_1` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`),
CONSTRAINT `equipoxusuario_ibfk_2` FOREIGN KEY (`idEquipo`) REFERENCES `equipo` (`idEquipo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -129,6 +141,17 @@ CREATE TABLE `equipoxusuario` (
LOCK TABLES `equipoxusuario` WRITE;
/*!40000 ALTER TABLE `equipoxusuario` DISABLE KEYS */;
INSERT INTO `equipoxusuario` VALUES
(1,1,1),
(2,2,1),
(3,3,1),
(4,4,2),
(5,5,2),
(6,6,2),
(7,7,3),
(8,8,3),
(9,9,4),
(10,10,4);
/*!40000 ALTER TABLE `equipoxusuario` ENABLE KEYS */;
UNLOCK TABLES;
@@ -143,10 +166,13 @@ CREATE TABLE `partida` (
`idPartida` int(11) NOT NULL AUTO_INCREMENT,
`nombrePartida` varchar(100) NOT NULL,
`idUsuario` int(11) NOT NULL,
`fechaCreacion` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`fechaInicio` DATETIME NULL,
`fechaFin` DATETIME NULL,
PRIMARY KEY (`idPartida`),
KEY `FK idUsuario tabla usuario` (`idUsuario`),
CONSTRAINT `FK idUsuario tabla usuario` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -155,6 +181,10 @@ CREATE TABLE `partida` (
LOCK TABLES `partida` WRITE;
/*!40000 ALTER TABLE `partida` DISABLE KEYS */;
INSERT INTO `partida` (idPartida, nombrePartida, idUsuario, fechaInicio, fechaFin) VALUES
(1,'Partida de prueba 1',1, NULL, NULL),
(2,'Partida de prueba 2',4, NULL, NULL),
(3,'Partida de prueba 3',9, NULL, NULL);
/*!40000 ALTER TABLE `partida` ENABLE KEYS */;
UNLOCK TABLES;
@@ -174,7 +204,7 @@ CREATE TABLE `partidaxpregunta` (
KEY `idPregunta` (`idPregunta`),
CONSTRAINT `partidaxpregunta_ibfk_1` FOREIGN KEY (`idPartida`) REFERENCES `partida` (`idPartida`),
CONSTRAINT `partidaxpregunta_ibfk_2` FOREIGN KEY (`idPregunta`) REFERENCES `pregunta` (`idPregunta`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -183,6 +213,37 @@ CREATE TABLE `partidaxpregunta` (
LOCK TABLES `partidaxpregunta` WRITE;
/*!40000 ALTER TABLE `partidaxpregunta` DISABLE KEYS */;
INSERT INTO `partidaxpregunta` VALUES
(1,1,2140),
(2,1,2141),
(3,1,2142),
(4,1,2143),
(5,1,2144),
(6,1,2145),
(7,1,2146),
(8,1,2147),
(9,1,2148),
(10,1,2149),
(11,2,2150),
(12,2,2151),
(13,2,2152),
(14,2,2153),
(15,2,2154),
(16,2,2155),
(17,2,2156),
(18,2,2157),
(19,2,2158),
(20,2,2159),
(21,3,2160),
(22,3,2161),
(23,3,2162),
(24,3,2163),
(25,3,2164),
(26,3,2165),
(27,3,2166),
(28,3,2167),
(29,3,2168),
(30,3,2169);
/*!40000 ALTER TABLE `partidaxpregunta` ENABLE KEYS */;
UNLOCK TABLES;
@@ -2303,4 +2364,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*M!100616 SET NOTE_VERBOSITY=@OLD_NOTE_VERBOSITY */;
-- Dump completed on 2026-09-25 9:54:43
-- Dump completed on 2026-09-25 10:00:41
+60 -187
View File
@@ -1,157 +1,121 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Redirección si el usuario no ha iniciado sesión
if (!isset($_SESSION['idUsuario'])) {
header('Location: login.php');
exit();
}
$nombreUsuario = htmlspecialchars($_SESSION['nombreUsuario'] ?? 'Usuario');
$avatarUsuario = htmlspecialchars($_SESSION['avatar'] ?? 'img/avatars/defaultProfile.jpeg');
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg">
<title>Perfil</title>
<!-- Bootstrap -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<!-- Google Font: Fredoka -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap"
rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Tu CSS -->
<link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="css/perfil.css">
<script src="js/jquery-4.0.0.min.js"></script>
</head>
<body>
<?php
include_once 'cabecera.php';
?>
<?php include_once 'cabecera.php'; ?>
<div class="perfil-container">
<div class="perfil-card">
<!-- ========================= -->
<!-- CABECERA -->
<!-- ========================= -->
<div class="perfil-header">
<i class="bi bi-person-circle"></i>
Mi perfil
</div>
<div class="perfil-content">
<div class="row align-items-center g-5">
<!-- ========================= -->
<!-- PERFIL -->
<!-- ========================= -->
<div class="col-md-6 text-center">
<!-- Nombre -->
<h1 id="nombre" class="nombre">
tuNombre
<?= $nombreUsuario ?>
</h1>
<!-- ========================= -->
<!-- FOTO DE PERFIL -->
<!-- ========================= -->
<div class="foto-container">
<img
id="fotoPerfil"
src="https://i.pravatar.cc/300?img=47"
<img id="fotoPerfil"
src="<?= $avatarUsuario ?>"
alt="Foto de perfil"
class="avatar rounded-circle">
<!-- Botón lápiz -->
<button
type="button"
<button type="button"
class="btn-foto"
onclick="seleccionarFoto()"
title="Cambiar foto de perfil"
aria-label="Cambiar foto de perfil">
<i class="bi bi-pencil-fill"></i>
</button>
<!-- Input oculto -->
<input
type="file"
<input type="file"
id="inputFoto"
accept="image/*"
hidden>
</div>
<!-- ========================= -->
<!-- CAMBIAR NOMBRE -->
<!-- ========================= -->
<div class="formulario-nombre">
<label
for="nuevoNombre"
class="form-label">
<label for="nuevoNombre" class="form-label">
Cambia tu nombre
</label>
<input
type="text"
<input type="text"
id="nuevoNombre"
class="form-control mb-3"
placeholder="Escribe tu nuevo nombre">
<div class="d-flex justify-content-center gap-2">
<button
type="button"
<button type="button"
class="btn-perfil-cambiar"
onclick="cambiarNombre()">
<i class="bi bi-check-lg"></i>
Cambiar nombre
</button>
<button
type="button"
<button type="button"
class="btn-perfil-borrar"
onclick="borrarNombre()">
<i class="bi bi-x-lg"></i>
Borrar
</button>
</div>
@@ -160,11 +124,7 @@
</div>
<!-- ========================= -->
<!-- ESTADÍSTICAS -->
<!-- ========================= -->
<div class="col-md-6">
<div class="estadisticas">
@@ -174,60 +134,33 @@
Estadísticas
</h2>
<div class="estadistica estadistica-victorias">
<i class="bi bi-trophy-fill"></i>
&nbsp; Victorias:
<strong>
0
</strong>
<strong id="victorias">0</strong>
</div>
<div class="estadistica estadistica-derrotas">
<i class="bi bi-x-circle-fill"></i>
&nbsp; Derrotas:
<strong>
0
</strong>
<strong id="derrotas">0</strong>
</div>
<div class="estadistica estadistica-aciertos">
<i class="bi bi-bullseye"></i>
&nbsp; Aciertos:
<strong>
0
</strong>
<strong id="aciertos">0</strong>
</div>
<!-- ========================= -->
<!-- CREAR PREGUNTA -->
<!-- ========================= -->
<div class="text-center mt-4">
<button
type="button"
<button type="button"
class="btn btn-play-kahoot"
data-bs-toggle="modal"
data-bs-target="#modalCrearPregunta">
<i class="bi bi-plus-circle-fill"></i>
Crear pregunta
</button>
</div>
</div>
@@ -243,12 +176,8 @@
</div>
<!-- ================================================= -->
<!-- MODAL CREAR PREGUNTA -->
<!-- ================================================= -->
<div
class="modal fade"
<div class="modal fade"
id="modalCrearPregunta"
tabindex="-1"
aria-labelledby="modalCrearPreguntaLabel"
@@ -258,157 +187,107 @@
<div class="modal-content modal-kahoot">
<!-- CABECERA DEL MODAL -->
<div class="modal-header modal-kahoot-header">
<h5
class="modal-title"
id="modalCrearPreguntaLabel">
<h5 class="modal-title" id="modalCrearPreguntaLabel">
<i class="bi bi-question-circle-fill me-2"></i>
Crear pregunta
</h5>
<button
type="button"
<button type="button"
class="btn-close btn-close-white"
data-bs-dismiss="modal"
aria-label="Cerrar">
</button>
</div>
<!-- CUERPO DEL MODAL -->
<div class="modal-body p-4">
<form id="formCrearPregunta">
<!-- PREGUNTA -->
<div class="mb-4">
<label
for="pregunta"
class="form-label fw-semibold">
<label for="pregunta" class="form-label fw-semibold">
<i class="bi bi-question-lg me-1"></i>
Pregunta
</label>
<textarea
id="pregunta"
<textarea id="pregunta"
name="pregunta"
class="form-control input-kahoot"
rows="3"
placeholder="Escribe aquí la pregunta..."
required></textarea>
</div>
<!-- CATEGORÍA -->
<div class="mb-4">
<label for="idCategoria" class="form-label fw-semibold">
<i class="bi bi-folder-fill me-1"></i>
Categoría
</label>
<select id="idCategoria"
name="idCategoria"
class="form-select input-kahoot"
required>
<option value="">Selecciona una categoría</option>
</select>
</div>
<!-- RESPUESTA CORRECTA -->
<div class="mb-3">
<label
for="respuestaCorrecta"
class="form-label fw-semibold text-success">
<label for="respuestaCorrecta" class="form-label fw-semibold text-success">
<i class="bi bi-check-circle-fill me-1"></i>
Respuesta correcta
</label>
<input
type="text"
<input type="text"
id="respuestaCorrecta"
name="respuestaCorrecta"
class="form-control input-kahoot"
placeholder="Escribe la respuesta correcta..."
required>
</div>
<!-- RESPUESTAS INCORRECTAS -->
<div class="mb-3">
<label
class="form-label fw-semibold text-danger">
<label class="form-label fw-semibold text-danger">
<i class="bi bi-x-circle-fill me-1"></i>
Respuestas incorrectas
</label>
<input
type="text"
<input type="text"
id="respuestaIncorrecta1"
name="respuestaIncorrecta1"
class="form-control input-kahoot mb-2"
placeholder="Respuesta incorrecta 1"
required>
<input
type="text"
<input type="text"
id="respuestaIncorrecta2"
name="respuestaIncorrecta2"
class="form-control input-kahoot mb-2"
placeholder="Respuesta incorrecta 2"
required>
<input
type="text"
<input type="text"
id="respuestaIncorrecta3"
name="respuestaIncorrecta3"
class="form-control input-kahoot"
placeholder="Respuesta incorrecta 3"
required>
</div>
</form>
</div>
<!-- PIE DEL MODAL -->
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="bi bi-x-lg me-1"></i>
Cancelar
</button>
<button
type="submit"
form="formCrearPregunta"
class="btn btn-kahoot-login">
<button type="submit" form="formCrearPregunta" class="btn btn-kahoot-login" id="btnCrearPregunta">
<i class="bi bi-check-lg me-1"></i>
Crear pregunta
</button>
</div>
</div>
@@ -417,16 +296,10 @@
</div>
<!-- Bootstrap JS -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Tu JavaScript -->
<script src="js/perfil.js"></script>
</body>
+2
View File
@@ -7,6 +7,8 @@
<title>Trivial - Resultado final</title>
<link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg">
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet">