diff --git a/cabecera.php b/cabecera.php index cea321a..c909e9c 100644 --- a/cabecera.php +++ b/cabecera.php @@ -16,11 +16,8 @@ $username = $isLoggedIn ? $_SESSION['nombreUsuario'] : ''; - - @@ -152,154 +149,4 @@ $username = $isLoggedIn ? $_SESSION['nombreUsuario'] : ''; - \ No newline at end of file + \ No newline at end of file diff --git a/clases/ClaseUsuario.php b/clases/ClaseUsuario.php index 410a252..a180469 100644 --- a/clases/ClaseUsuario.php +++ b/clases/ClaseUsuario.php @@ -1,7 +1,8 @@ idUsuario = $idUsuario; @@ -34,33 +35,85 @@ class Usuario { $this->derrotas = $derrotas; } - 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 getIdUsuario(): ?int + { + return $this->idUsuario; + } - public function getContrasena(): string { return $this->contrasena; } - public function setContrasena(string $contrasena): void { $this->contrasena = $contrasena; } + public function getNombreUsuario(): string + { + return $this->nombreUsuario; + } + public function setNombreUsuario(string $nombreUsuario): void + { + $this->nombreUsuario = $nombreUsuario; + } - public function getEmail(): string { return $this->email; } - public function setEmail(string $email): void { $this->email = $email; } + public function getContrasena(): string + { + return $this->contrasena; + } + public function setContrasena(string $contrasena): void + { + $this->contrasena = $contrasena; + } - public function getAvatar(): ?string { return $this->avatar; } - public function setAvatar(?string $avatar): void { $this->avatar = $avatar; } + public function getEmail(): string + { + return $this->email; + } + public function setEmail(string $email): void + { + $this->email = $email; + } - public function getCookie(): ?string { return $this->cookie; } - public function setCookie(?string $cookie): void { $this->cookie = $cookie; } + public function getAvatar(): ?string + { + return $this->avatar; + } + public function setAvatar(?string $avatar): void + { + $this->avatar = $avatar; + } - public function getAciertos(): int { return $this->aciertos; } - public function setAciertos(int $aciertos): void { $this->aciertos = $aciertos; } + public function getCookie(): ?string + { + return $this->cookie; + } + public function setCookie(?string $cookie): void + { + $this->cookie = $cookie; + } - public function getVictorias(): int { return $this->victorias; } - public function setVictorias(int $victorias): void { $this->victorias = $victorias; } + public function getAciertos(): int + { + return $this->aciertos; + } + public function setAciertos(int $aciertos): void + { + $this->aciertos = $aciertos; + } - public function getDerrotas(): int { return $this->derrotas; } - public function setDerrotas(int $derrotas): void { $this->derrotas = $derrotas; } + public function getVictorias(): int + { + return $this->victorias; + } + public function setVictorias(int $victorias): void + { + $this->victorias = $victorias; + } - public function registrar() { + public function getDerrotas(): int + { + return $this->derrotas; + } + public function setDerrotas(int $derrotas): void + { + $this->derrotas = $derrotas; + } + + public function registrar() + { $conexion = conexionBD(); if (is_array($conexion)) { @@ -71,7 +124,7 @@ class Usuario { $sql = "INSERT INTO usuario (nombreUsuario, contrasena, email, avatar, cookie, aciertos, victorias, derrotas) VALUES (:nombre, :pass, :email, :avatar, :cookie, :aciertos, :victorias, :derrotas)"; $stmt = $conexion->prepare($sql); - + $passHash = password_hash($this->contrasena, PASSWORD_BCRYPT); $stmt->execute([ @@ -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)) { @@ -111,27 +164,26 @@ class Usuario { $sql = "SELECT * FROM usuario WHERE idUsuario = :id"; $stmt = $conexion->prepare($sql); $stmt->execute([':id' => $id]); - + $datos = $stmt->fetch(PDO::FETCH_ASSOC); if ($datos) { return new Usuario( - $datos['nombreUsuario'], - $datos['contrasena'], - $datos['email'], - $datos['avatar'], - $datos['cookie'], - (int)$datos['aciertos'], - (int)$datos['victorias'], - (int)$datos['derrotas'], + $datos['nombreUsuario'], + $datos['contrasena'], + $datos['email'], + $datos['avatar'], + $datos['cookie'], + (int)$datos['aciertos'], + (int)$datos['victorias'], + (int)$datos['derrotas'], (int)$datos['idUsuario'] ); } - + 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,123 @@ 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() + ]; + } + } } diff --git a/controladores/ControladorUsuario.php b/controladores/ControladorUsuario.php index a61322b..cfc5206 100644 --- a/controladores/ControladorUsuario.php +++ b/controladores/ControladorUsuario.php @@ -35,7 +35,8 @@ switch ($_POST['orden']) { $usuario = new Usuario( $nombreUsuario, $contrasena, - $email + $email, + 'img/avatars/defaultProfile.jpeg' ); $resultado = $usuario->registrar(); @@ -97,7 +98,6 @@ switch ($_POST['orden']) { 'derrotas' => $usuario->getDerrotas(), 'aciertos' => $usuario->getAciertos() ]); - } else { echo json_encode($usuario); @@ -105,6 +105,120 @@ switch ($_POST['orden']) { 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; } diff --git a/img/avatars/defaultProfile.jpeg b/img/avatars/defaultProfile.jpeg new file mode 100644 index 0000000..b0107ec Binary files /dev/null and b/img/avatars/defaultProfile.jpeg differ diff --git a/js/cabecera.js b/js/cabecera.js new file mode 100644 index 0000000..7ba5510 --- /dev/null +++ b/js/cabecera.js @@ -0,0 +1,133 @@ +// 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 + window.location.href = 'index.php'; + + } + }); // Fin función ajax +}); // Fin función click diff --git a/js/perfil.js b/js/perfil.js index edfca78..64f9353 100644 --- a/js/perfil.js +++ b/js/perfil.js @@ -1,42 +1,59 @@ +// ========================= +// 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(); - + document.getElementById("nuevoNombre").value = ""; } @@ -44,31 +61,48 @@ function seleccionarFoto() { // 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/")) { + // 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; - } + return; + } + let datos = new FormData(); - // Creamos una URL temporal - const imagenURL = URL.createObjectURL(archivo); - - - // Cambiamos la foto - document.getElementById("fotoPerfil").src = imagenURL; - - } + datos.append("avatar", archivo); + datos.append("orden", "cambiarAvatar"); + $.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(), + ); } -); + }); +}); diff --git a/perfil.php b/perfil.php index a313d77..9782ddf 100644 --- a/perfil.php +++ b/perfil.php @@ -80,7 +80,7 @@ @@ -418,33 +418,6 @@ - -