recursos-catolicos/frontend/js/auth.js

298 lines
12 KiB
JavaScript

// ================================
// UTILIDADES DE AUTENTICACIÓN
// ================================
/** Devuelve el token JWT o null si no hay sesión. */
function getToken() {
return localStorage.getItem("token");
}
/** Devuelve el objeto usuario guardado en sesión, o null. */
function getUsuario() {
const u = localStorage.getItem("usuario");
return u ? JSON.parse(u) : null;
}
/**
* Verifica que el usuario esté autenticado.
* Si no lo está, redirige a login.html y devuelve null.
*/
function verificarAuth() {
if (!getToken()) {
window.location.href = "login.html";
return null;
}
return getUsuario();
}
/** Cierra la sesión y recarga la página actual (o va a index si es protegida). */
function cerrarSesion() {
localStorage.removeItem("token");
localStorage.removeItem("usuario");
const paginasProtegidas = ["intenciones.html", "diario-oracion.html"];
const actual = location.pathname.split("/").pop();
if (paginasProtegidas.includes(actual)) {
window.location.href = "index.html";
} else {
location.reload();
}
}
/**
* Muestra el nombre del usuario y el botón de cerrar sesión en el header.
* Sin sesión: muestra botones que abren el modal de auth.
*/
function mostrarSesionEnHeader() {
const usuario = getUsuario();
const contenedor = document.getElementById("header-sesion");
if (!contenedor) return;
if (usuario) {
contenedor.innerHTML = `
<span class="header-usuario">👤 ${usuario.nombre}</span>
<button class="btn-cerrar-sesion" onclick="cerrarSesion()">Salir</button>
`;
} else {
contenedor.innerHTML = `
<button class="btn-registro" onclick="abrirModalAuth('registro')">Registrarse</button>
<button class="btn-sesion" onclick="abrirModalAuth('login')">Iniciar sesión</button>
`;
}
}
// ================================
// MODAL DE AUTENTICACIÓN
// ================================
/** Resuelve la base de la API aunque api-config.js no esté cargado en la página. */
function _apiBase() {
if (typeof API_BASE !== "undefined") return API_BASE;
return (location.hostname === "localhost" ||
location.hostname === "127.0.0.1" ||
location.hostname === "")
? "http://localhost:8080"
: "https://recursos-catolicos.es:8080";
}
/** Crea e inserta el modal en el DOM la primera vez que se abre. */
function _inyectarModalAuth() {
if (document.getElementById("modal-auth")) return;
const el = document.createElement("div");
el.id = "modal-auth";
el.className = "modal-auth-overlay";
el.setAttribute("role", "dialog");
el.setAttribute("aria-modal", "true");
el.setAttribute("aria-label", "Iniciar sesión o registrarse");
el.innerHTML = `
<div class="modal-auth-caja">
<button class="modal-auth-cerrar" id="modal-auth-cerrar" aria-label="Cerrar">&times;</button>
<div class="modal-auth-tabs" role="tablist">
<button class="modal-auth-tab activa" data-tab="login" role="tab">Iniciar sesión</button>
<button class="modal-auth-tab" data-tab="registro" role="tab">Registrarse</button>
</div>
<!-- Panel: Login -->
<div class="modal-auth-panel" id="modal-panel-login" role="tabpanel">
<p class="modal-auth-bienvenida">Bienvenido de nuevo 🙏</p>
<input type="email" id="modal-email" placeholder="correo@example.com" autocomplete="email">
<input type="password" id="modal-password" placeholder="Contraseña" autocomplete="current-password">
<button class="modal-auth-btn" id="modal-btn-login">Entrar</button>
<p id="modal-login-msg" class="modal-auth-msg" aria-live="polite"></p>
<p class="modal-auth-pie">¿Olvidaste tu contraseña? <a href="login.html">Más opciones</a></p>
</div>
<!-- Panel: Registro -->
<div class="modal-auth-panel" id="modal-panel-registro" role="tabpanel" style="display:none;">
<p class="modal-auth-bienvenida">Crea tu espacio personal ✝</p>
<input type="text" id="modal-nombre" placeholder="Tu nombre" autocomplete="name">
<input type="email" id="modal-email-reg" placeholder="correo@example.com" autocomplete="email">
<input type="password" id="modal-password-reg" placeholder="Mínimo 8 caracteres" autocomplete="new-password">
<button class="modal-auth-btn" id="modal-btn-registro">Registrarme</button>
<p id="modal-registro-msg" class="modal-auth-msg" aria-live="polite"></p>
<p class="modal-auth-pie">¿Quieres más opciones? <a href="register.html">Registro completo</a></p>
</div>
</div>
`;
document.body.appendChild(el);
// — Cerrar —
document.getElementById("modal-auth-cerrar").addEventListener("click", cerrarModalAuth);
el.addEventListener("click", e => { if (e.target === el) cerrarModalAuth(); });
document.addEventListener("keydown", _modalKeyHandler);
// — Pestañas —
el.querySelectorAll(".modal-auth-tab").forEach(tab => {
tab.addEventListener("click", () => {
el.querySelectorAll(".modal-auth-tab").forEach(t => t.classList.remove("activa"));
tab.classList.add("activa");
document.getElementById("modal-panel-login").style.display = tab.dataset.tab === "login" ? "block" : "none";
document.getElementById("modal-panel-registro").style.display = tab.dataset.tab === "registro" ? "block" : "none";
_focoModal(tab.dataset.tab);
});
});
// — Enter para enviar —
["modal-email", "modal-password"].forEach(id =>
document.getElementById(id).addEventListener("keydown", e => { if (e.key === "Enter") _loginModal(); })
);
["modal-nombre", "modal-email-reg", "modal-password-reg"].forEach(id =>
document.getElementById(id).addEventListener("keydown", e => { if (e.key === "Enter") _registroModal(); })
);
document.getElementById("modal-btn-login").addEventListener("click", _loginModal);
document.getElementById("modal-btn-registro").addEventListener("click", _registroModal);
}
function _modalKeyHandler(e) {
if (e.key === "Escape") cerrarModalAuth();
}
function _focoModal(tab) {
setTimeout(() => {
const id = tab === "login" ? "modal-email" : "modal-nombre";
document.getElementById(id)?.focus();
}, 80);
}
/** Abre el modal en la pestaña indicada ('login' | 'registro'). */
function abrirModalAuth(tab = "login") {
_inyectarModalAuth();
const modal = document.getElementById("modal-auth");
// Limpiar mensajes y campos al abrir
["modal-login-msg", "modal-registro-msg"].forEach(id => {
const el = document.getElementById(id);
if (el) { el.textContent = ""; el.className = "modal-auth-msg"; }
});
modal.querySelectorAll(".modal-auth-tab").forEach(t => t.classList.remove("activa"));
modal.querySelector(`[data-tab="${tab}"]`).classList.add("activa");
document.getElementById("modal-panel-login").style.display = tab === "login" ? "block" : "none";
document.getElementById("modal-panel-registro").style.display = tab === "registro" ? "block" : "none";
modal.classList.add("activo");
document.body.classList.add("modal-abierto");
_focoModal(tab);
}
/** Cierra el modal. */
function cerrarModalAuth() {
const modal = document.getElementById("modal-auth");
if (!modal) return;
modal.classList.remove("activo");
document.body.classList.remove("modal-abierto");
}
/** Lógica de inicio de sesión desde el modal. */
async function _loginModal() {
const email = document.getElementById("modal-email").value.trim();
const password = document.getElementById("modal-password").value.trim();
const msg = document.getElementById("modal-login-msg");
const btn = document.getElementById("modal-btn-login");
msg.textContent = "";
msg.className = "modal-auth-msg";
if (!email || !password) {
msg.textContent = "Completa todos los campos.";
msg.classList.add("error");
return;
}
btn.disabled = true;
btn.textContent = "Entrando…";
try {
const res = await fetch(`${_apiBase()}/auth/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password })
});
if (res.ok) {
const data = await res.json();
localStorage.setItem("token", data.token);
localStorage.setItem("usuario", JSON.stringify(data.usuario));
msg.textContent = `¡Bienvenido, ${data.usuario.nombre}! ✝`;
msg.classList.add("success");
setTimeout(() => location.reload(), 900);
} else {
msg.textContent = "Email o contraseña incorrectos.";
msg.classList.add("error");
btn.disabled = false;
btn.textContent = "Entrar";
}
} catch (e) {
msg.textContent = "No se pudo conectar con el servidor.";
msg.classList.add("error");
btn.disabled = false;
btn.textContent = "Entrar";
}
}
/** Lógica de registro desde el modal (individual; registro completo en register.html). */
async function _registroModal() {
const nombre = document.getElementById("modal-nombre").value.trim();
const email = document.getElementById("modal-email-reg").value.trim();
const password = document.getElementById("modal-password-reg").value.trim();
const msg = document.getElementById("modal-registro-msg");
const btn = document.getElementById("modal-btn-registro");
msg.textContent = "";
msg.className = "modal-auth-msg";
if (!nombre || !email || !password) {
msg.textContent = "Completa todos los campos.";
msg.classList.add("error");
return;
}
if (password.length < 8) {
msg.textContent = "La contraseña debe tener al menos 8 caracteres.";
msg.classList.add("error");
return;
}
btn.disabled = true;
btn.textContent = "Registrando…";
try {
const res = await fetch(`${_apiBase()}/auth/register`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ nombre, email, password, tipoUsuario: "individual" })
});
if (res.ok) {
msg.textContent = "¡Cuenta creada! Iniciando sesión…";
msg.classList.add("success");
// Auto-login tras el registro
const loginRes = await fetch(`${_apiBase()}/auth/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password })
});
if (loginRes.ok) {
const data = await loginRes.json();
localStorage.setItem("token", data.token);
localStorage.setItem("usuario", JSON.stringify(data.usuario));
}
setTimeout(() => location.reload(), 900);
} else {
const error = await res.text();
msg.textContent = error || "No se pudo crear la cuenta.";
msg.classList.add("error");
btn.disabled = false;
btn.textContent = "Registrarme";
}
} catch (e) {
msg.textContent = "No se pudo conectar con el servidor.";
msg.classList.add("error");
btn.disabled = false;
btn.textContent = "Registrarme";
}
}