intenciones de oracion, login y registro. Intentando que hable con backend

This commit is contained in:
Tatiana Villa Ema 2026-01-21 19:28:04 +01:00
parent d7c2e2de4a
commit 67e4b2b5c7
12 changed files with 470 additions and 91 deletions

View File

@ -1,60 +1,112 @@
:root {
--blanco-lino: #FAF7F2;
--color-text: #3A3A3A;
--color-naranja: #F4C76E;
--color-naranja2: #E8A23A;
--arena: #E8DCC2;
--color-primary-dark: #2F3A56;
--color-text-light: #FDFBF7;
}
/* CONTENEDOR */
.contenedor-intenciones {
max-width: 600px;
margin: 2rem auto;
max-width: 900px;
margin: auto;
padding: 2rem;
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.05);
text-align: center;
}
/* FORMULARIO */
.formulario-intencion {
display: flex;
gap: 10px;
gap: 1rem;
justify-content: center;
margin-bottom: 2rem;
}
.formulario-intencion input {
flex: 1;
padding: 12px;
border: 1px solid var(--arena);
padding: 0.7rem;
width: 60%;
border-radius: 8px;
font-family: 'Nunito', sans-serif;
border: 1px solid #ccc;
}
.lista-personalizada {
list-style: none;
padding: 0;
}
.item-intencion {
/* MURO DE HEXÁGONOS */
.muro-hexagonos {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
border-bottom: 1px solid var(--color-secundario);
transition: background 0.3s;
flex-wrap: wrap;
justify-content: center;
gap: 25px;
}
.item-intencion:hover {
background-color: #fdfaf5;
}
.btn-borrar {
background: none;
border: none;
color: #cc0000;
/* HEXÁGONO */
.hexagono {
width: 120px;
height: 70px;
background: #ffffffaa;
position: relative;
cursor: pointer;
font-weight: bold;
padding: 5px 10px;
}
transition: transform .2s;
display: flex;
justify-content: center;
align-items: center;
border-radius: 6px;
}
.hexagono:hover {
transform: scale(1.07);
}
.hexagono:before,
.hexagono:after {
content: "";
position: absolute;
width: 0;
border-left: 60px solid transparent;
border-right: 60px solid transparent;
}
.hexagono:before {
bottom: 100%;
border-bottom: 35px solid #ffffffaa;
}
.hexagono:after {
top: 100%;
border-top: 35px solid #ffffffaa;
}
/* ICONO DENTRO DEL HEXÁGONO */
.icono-intencion {
width: 40px;
height: 40px;
opacity: 0.9;
}
/* MODAL */
.modal {
display: none;
position: fixed;
inset: 0;
background: #00000088;
justify-content: center;
align-items: center;
}
.modal.visible {
display: flex;
}
.modal-contenido {
background: white;
padding: 2rem;
border-radius: 12px;
text-align: center;
max-width: 300px;
}
.cerrar {
float: right;
font-size: 1.5rem;
cursor: pointer;
}
.icono-modal {
width: 60px;
margin-bottom: 1rem;
}
.texto-modal {
font-size: 1.1rem;
margin-top: 1rem;
}

69
css/login.css Normal file
View File

@ -0,0 +1,69 @@
body {
font-family: Arial, sans-serif;
background: #f4f4f9;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
}
.container {
background: white;
padding: 30px;
border-radius: 10px;
width: 90%;
max-width: 400px;
margin-top: 120px;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
}
h2 {
text-align: center;
margin-bottom: 20px;
color: #333;
}
label {
font-weight: bold;
display: block;
margin-top: 15px;
}
input {
width: 100%;
padding: 10px;
margin-top: 5px;
border-radius: 5px;
border: 1px solid #ccc;
}
button {
width: 100%;
margin-top: 20px;
padding: 12px;
background: #2196F3;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
}
button:hover {
background: #1976D2;
}
.msg {
margin-top: 15px;
text-align: center;
font-size: 14px;
}
.success {
color: green;
}
.error {
color: red;
}

76
css/register.css Normal file
View File

@ -0,0 +1,76 @@
/* Fuentes importadas corregidas */
@import url('https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,600;1,400&family=Nunito:wght@400;600&display=swap');
:root {
/* Paleta refinada */
--color-primario: #2F3A56; /* Azul noche espiritual */
--color-hover: #24314A; /* Azul noche más oscuro */
--color-secundario: #EAF2FA; /* Azul muy suave */
--color-fondo: #FAF7F2; /* Crema papel antiguo */
--color-texto: #2b2b2b;
--color-acento: #E8A23A; /* Dorado litúrgico */
--blanco-puro: #FFFFFF;
--sombra: rgba(47, 58, 86, 0.15);
}
body {
font-family: 'Nunito', sans-serif;
background: var(--color-fondo);
margin: 0;
padding: 0;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background: white;
padding: 30px;
border-radius: 10px;
width: 90%;
max-width: 400px;
box-shadow: 0 4px 10px rgba(0,0,0,0.5);
margin-left: auto;
margin-right: auto;
margin-top: 1.25rem;
}
label {
font-weight: bold;
display: block;
margin-top: 15px;
}
input {
width: 100%;
padding: 10px;
margin-top: 5px;
border-radius: 5px;
border: 1px solid #ccc;
}
button {
width: 100%;
margin-top: 20px;
padding: 12px;
background: var(--color-primario);
color: var(--blanco-puro);
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
}
button:hover {
background: var(--color-hover);
}
.msg {
margin-top: 15px;
text-align: center;
font-size: 14px;
}
.success {
color: var(--color-acento);
}
.error {
color: red;
}

BIN
img/iconos/cruz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
img/iconos/flor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

BIN
img/iconos/vela.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -9,21 +9,32 @@
<link rel="stylesheet" href="css/intenciones.css">
</head>
<body>
<div id="header-container"></div>
<div class="contenedor-intenciones">
<h3>🙏 Mis Intenciones Personales</h3>
<p class="texto-suave">Estas intenciones se guardan solo en tu dispositivo.</p>
<div id="header-container"></div>
<div class="contenedor-intenciones">
<h3>🙏 Intenciones de Oración</h3>
<p class="texto-suave">Cada intención se guarda solo en tu dispositivo.</p>
<div class="formulario-intencion">
<input type="text" id="nueva-intencion" placeholder="Escribe tu petición aquí...">
<button id="btn-guardar" class="boton">Añadir Intención</button>
<input type="text" id="nueva-intencion" placeholder="Escribe tu intención...">
<button id="btn-guardar" class="boton">Añadir</button>
</div>
<ul id="lista-intenciones" class="lista-personalizada">
</ul>
<div id="muro-intenciones" class="muro-hexagonos"></div>
</div>
<!-- MODAL -->
<div id="modal-intencion" class="modal">
<div class="modal-contenido">
<span id="cerrar-modal" class="cerrar">&times;</span>
<img id="icono-modal" class="icono-modal" src="">
<p id="texto-modal" class="texto-modal"></p>
</div>
</div>
<script src="js/header.js"></script>
<script src="js/intenciones.js"></script>
</body>
</html>
</html>

View File

@ -1,41 +1,61 @@
document.addEventListener('DOMContentLoaded', () => {
const input = document.getElementById('nueva-intencion');
const btnGuardar = document.getElementById('btn-guardar');
const lista = document.getElementById('lista-intenciones');
// Cargar intenciones desde localStorage
let intenciones = JSON.parse(localStorage.getItem("intenciones")) || [];
// 1. Cargar intenciones guardadas al iniciar
let intenciones = JSON.parse(localStorage.getItem('misIntenciones')) || [];
renderizarIntenciones();
const muro = document.getElementById("muro-intenciones");
const input = document.getElementById("nueva-intencion");
const btn = document.getElementById("btn-guardar");
// 2. Función para guardar
btnGuardar.addEventListener('click', () => {
const texto = input.value.trim();
if (texto) {
intenciones.push({ id: Date.now(), texto: texto });
localStorage.setItem('misIntenciones', JSON.stringify(intenciones));
input.value = '';
renderizarIntenciones();
}
});
// Iconos disponibles
const iconos = ["vela.png", "flor.png", "cruz.png"];
// 3. Función para mostrar en pantalla
function renderizarIntenciones() {
lista.innerHTML = '';
intenciones.forEach(intencion => {
const li = document.createElement('li');
li.className = 'item-intencion';
li.innerHTML = `
<span>${intencion.texto}</span>
<button class="btn-borrar" onclick="eliminarIntencion(${intencion.id})"></button>
`;
lista.appendChild(li);
});
}
// Crear un hexágono
function crearHexagono(intencion, icono) {
const hex = document.createElement("div");
hex.className = "hexagono";
hex.dataset.intencion = intencion;
hex.dataset.icono = icono;
// 4. Función para eliminar (la hacemos global para que el onclick funcione)
window.eliminarIntencion = (id) => {
intenciones = intenciones.filter(i => i.id !== id);
localStorage.setItem('misIntenciones', JSON.stringify(intenciones));
renderizarIntenciones();
};
});
hex.innerHTML = `<img src="img/iconos/${icono}" class="icono-intencion">`;
muro.appendChild(hex);
}
// Guardar intención
btn.addEventListener("click", () => {
const texto = input.value.trim();
if (texto === "") return;
const icono = iconos[Math.floor(Math.random() * iconos.length)];
intenciones.push({ texto, icono });
localStorage.setItem("intenciones", JSON.stringify(intenciones));
crearHexagono(texto, icono);
input.value = "";
});
// Mostrar intenciones guardadas
intenciones.forEach(i => crearHexagono(i.texto, i.icono));
// MODAL
const modal = document.getElementById("modal-intencion");
const cerrar = document.getElementById("cerrar-modal");
const textoModal = document.getElementById("texto-modal");
const iconoModal = document.getElementById("icono-modal");
// Abrir modal al tocar un hexágono
document.addEventListener("click", e => {
const hex = e.target.closest(".hexagono");
if (!hex) return;
textoModal.textContent = hex.dataset.intencion;
iconoModal.src = "img/iconos/" + hex.dataset.icono;
modal.classList.add("visible");
});
// Cerrar modal
cerrar.onclick = () => modal.classList.remove("visible");
modal.onclick = e => {
if (e.target === modal) modal.classList.remove("visible");
};

46
js/login.js Normal file
View File

@ -0,0 +1,46 @@
async function login() {
const email = document.getElementById("email").value.trim();
const password = document.getElementById("password").value.trim();
const msg = document.getElementById("mensaje");
msg.textContent = "";
msg.className = "msg";
if (!email || !password) {
msg.textContent = "Por favor, completa todos los campos.";
msg.classList.add("error");
return;
}
try {
const response = await fetch("http://aplicacionesdevanguardia.es:8080/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password })
});
if (response.ok) {
const data = await response.json();
// Guardar token
localStorage.setItem("token", data.token);
msg.textContent = "Inicio de sesión correcto.";
msg.classList.add("success");
// Redirigir a la página privada
setTimeout(() => {
window.location.href = "intenciones.html";
}, 1000);
} else {
const error = await response.text();
msg.textContent = "Error: " + error;
msg.classList.add("error");
}
} catch (e) {
msg.textContent = "No se pudo conectar con el servidor.";
msg.classList.add("error");
}
}

36
js/register.js Normal file
View File

@ -0,0 +1,36 @@
async function registrar() {
const nombre = document.getElementById("nombre").value.trim();
const email = document.getElementById("email").value.trim();
const password = document.getElementById("password").value.trim();
const msg = document.getElementById("mensaje");
msg.textContent = "";
msg.className = "msg";
if (!nombre || !email || !password) {
msg.textContent = "Por favor, completa todos los campos.";
msg.classList.add("error");
return;
}
try {
const response = await fetch("http://aplicacionesdevanguardia.es:8080/auth/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ nombre, email, password })
});
if (response.ok) {
msg.textContent = "Cuenta creada correctamente.";
msg.classList.add("success");
} else {
const error = await response.text();
msg.textContent = "Error: " + error;
msg.classList.add("error");
}
} catch (e) {
msg.textContent = "No se pudo conectar con el servidor.";
msg.classList.add("error");
}
}

33
login.html Normal file
View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Iniciar sesión</title>
<link rel="icon" type="image/x-icon" href="img/favicon.png">
<link rel="stylesheet" href="css/estilos.css">
<link rel="stylesheet" href="css/login.css">
</head>
<body>
<div id="header-container"></div>
<div class="container">
<h2>Iniciar sesión</h2>
<label>Email</label>
<input type="email" id="email" placeholder="correo@example.com">
<label>Contraseña</label>
<input type="password" id="password" placeholder="••••••••">
<button onclick="login()">Entrar</button>
<div id="mensaje" class="msg"></div>
</div>
<script src="js/header.js"></script>
<script src="js/login.js"></script>
</body>
</html>

36
register.html Normal file
View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Crear cuenta</title>
<link rel="icon" type="image/x-icon" href="img/favicon.png">
<link rel="stylesheet" href="css/estilos.css">
<link rel="stylesheet" href="css/register.css">
</head>
<body>
<div id="header-container"></div>
<div class="container">
<h2>Crear cuenta</h2>
<label>Nombre</label>
<input type="text" id="nombre" placeholder="Tu nombre">
<label>Email</label>
<input type="email" id="email" placeholder="correo@example.com">
<label>Contraseña</label>
<input type="password" id="password" placeholder="••••••••">
<button onclick="registrar()">Registrarme</button>
<div id="mensaje" class="msg"></div>
</div>
<script src="js/header.js"></script>
<script src="js/register.js"></script>
</body>
</html>