// ================================ // INTENCIONES DE ORACIÓN // Ámbitos: personal / parroquia / grupo // Requiere: api-config.js, auth.js // ================================ const iconos = ["vela.png", "flor.png", "cruz.png"]; let ambitoActual = "personal"; let grupoActualId = null; let usuario = null; // ── INICIALIZACIÓN ────────────────────────────────────────── function init() { usuario = verificarAuth(); if (!usuario) return; // verificarAuth ya redirige a login si no hay sesión migrarDifuntosAnonimos(); configurarPestanas(); configurarSelectorGrupo(); cargarIntenciones(); document.getElementById("btn-guardar").addEventListener("click", guardarIntencion); document.getElementById("nueva-intencion").addEventListener("keydown", e => { if (e.key === "Enter") guardarIntencion(); }); document.getElementById("btn-guardar-difunto").addEventListener("click", agregarDifunto); document.getElementById("difunto-nombre").addEventListener("keydown", e => { if (e.key === "Enter") agregarDifunto(); }); } // ── PESTAÑAS ──────────────────────────────────────────────── function configurarPestanas() { // Mostrar pestaña de parroquia si el usuario pertenece a una if (usuario.parroquia) { const tabParroquia = document.getElementById("tab-parroquia"); tabParroquia.style.display = ""; tabParroquia.textContent = `⛪ ${usuario.parroquia.nombre}`; } // Mostrar pestaña de comunidad si el usuario tiene grupos if (usuario.grupos && usuario.grupos.length > 0) { document.getElementById("tab-grupo").style.display = ""; } document.querySelectorAll(".pestana").forEach(btn => { btn.addEventListener("click", () => { document.querySelectorAll(".pestana").forEach(b => b.classList.remove("activa")); btn.classList.add("activa"); ambitoActual = btn.dataset.ambito; const esDifuntos = ambitoActual === "difuntos"; document.getElementById("panel-difuntos").style.display = esDifuntos ? "block" : "none"; document.getElementById("formulario-intencion").style.display = esDifuntos ? "none" : "flex"; document.getElementById("muro-intenciones").style.display = esDifuntos ? "none" : "flex"; document.getElementById("sin-intenciones").style.display = "none"; if (esDifuntos) { cargarDifuntos(); } else { actualizarSelectorGrupo(); cargarIntenciones(); } }); }); } // ── SELECTOR DE GRUPO ─────────────────────────────────────── function configurarSelectorGrupo() { if (!usuario.grupos || usuario.grupos.length === 0) return; const select = document.getElementById("select-grupo"); usuario.grupos.forEach(g => { const option = document.createElement("option"); option.value = g.id; option.textContent = g.nombre; select.appendChild(option); }); grupoActualId = usuario.grupos[0].id; select.addEventListener("change", () => { grupoActualId = parseInt(select.value); cargarIntenciones(); }); } function actualizarSelectorGrupo() { const selector = document.getElementById("selector-grupo"); selector.style.display = ambitoActual === "grupo" ? "block" : "none"; } // La clave del fallback de intenciones también es por usuario function keyIntenciones() { return `intenciones_${usuario ? usuario.id : "anonimo"}`; } // ── CARGA DE INTENCIONES ───────────────────────────────────── async function cargarIntenciones() { const muro = document.getElementById("muro-intenciones"); const sinIntenciones = document.getElementById("sin-intenciones"); muro.innerHTML = ""; let endpoint; if (ambitoActual === "personal") { endpoint = "/intenciones/personales"; } else if (ambitoActual === "parroquia") { endpoint = `/intenciones/parroquia/${usuario.parroquia.id}`; } else { if (!grupoActualId) return; endpoint = `/intenciones/grupo/${grupoActualId}`; } try { const response = await apiCall(endpoint); if (!response || !response.ok) { sinIntenciones.style.display = "block"; return; } const intenciones = await response.json(); if (intenciones.length === 0) { sinIntenciones.style.display = "block"; return; } sinIntenciones.style.display = "none"; intenciones.forEach(i => crearHexagono(i)); } catch (e) { // Si no hay conexión, mostrar las intenciones personales del localStorage como fallback if (ambitoActual === "personal") { const local = JSON.parse(localStorage.getItem(keyIntenciones()) || localStorage.getItem("intenciones") || "[]"); if (local.length === 0) { sinIntenciones.style.display = "block"; } else { local.forEach(i => crearHexagono({ texto: i.texto, icono: i.icono, esPropia: true })); } } else { sinIntenciones.style.display = "block"; } } } // ── GUARDAR INTENCIÓN ──────────────────────────────────────── async function guardarIntencion() { const input = document.getElementById("nueva-intencion"); const texto = input.value.trim(); if (!texto) return; const icono = iconos[Math.floor(Math.random() * iconos.length)]; const body = { texto, icono, ambito: ambitoActual }; if (ambitoActual === "parroquia") body.parroquiaId = usuario.parroquia.id; if (ambitoActual === "grupo") body.grupoId = grupoActualId; try { const response = await apiCall("/intenciones", { method: "POST", body: JSON.stringify(body) }); if (response && response.ok) { const nueva = await response.json(); crearHexagono({ ...nueva, esPropia: true }); document.getElementById("sin-intenciones").style.display = "none"; } } catch (e) { // Fallback local solo para intenciones personales if (ambitoActual === "personal") { const local = JSON.parse(localStorage.getItem(keyIntenciones()) || "[]"); local.push({ texto, icono }); localStorage.setItem(keyIntenciones(), JSON.stringify(local)); crearHexagono({ texto, icono, esPropia: true, id: null }); document.getElementById("sin-intenciones").style.display = "none"; } } input.value = ""; } // ── HEXÁGONO ───────────────────────────────────────────────── function crearHexagono(intencion) { const muro = document.getElementById("muro-intenciones"); const hex = document.createElement("div"); hex.className = "hexagono"; hex.dataset.texto = intencion.texto; hex.dataset.icono = intencion.icono || iconos[0]; hex.dataset.autor = intencion.autorNombre || ""; hex.dataset.id = intencion.id || ""; hex.dataset.esPropia = intencion.esPropia || (intencion.usuarioId === usuario?.id) ? "true" : "false"; hex.innerHTML = `icono intención`; muro.appendChild(hex); } // ── DIFUNTOS ───────────────────────────────────────────────── // Caché en memoria para evitar peticiones redundantes let _difuntosCache = null; let _mesDifuntos = new Date().getMonth(); // 0-11, mes visible actualmente const MESES_ES = ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre']; async function _apiGetDifuntos() { try { const res = await apiCall('/difuntos/personales'); if (!res || !res.ok) throw new Error('Error al cargar difuntos'); const data = await res.json(); _difuntosCache = data; // Sincronizar localStorage como caché offline localStorage.setItem(keyDifuntos(), JSON.stringify(data)); return data; } catch (e) { // Fallback a localStorage si no hay conexión return JSON.parse(localStorage.getItem(keyDifuntos()) || '[]'); } } // La clave incluye el id del usuario para que cada cuenta tenga sus propios difuntos function keyDifuntos() { return `difuntos_personales_${usuario ? usuario.id : 'anonimo'}`; } // Migra los difuntos guardados anónimamente al usuario actual via API async function migrarDifuntosAnonimos() { const claveAnonima = 'difuntos_personales_anonimo'; const anonimos = JSON.parse(localStorage.getItem(claveAnonima) || '[]'); if (anonimos.length === 0) return; let migrados = 0; for (const d of anonimos) { try { const res = await apiCall('/difuntos/personales', { method: 'POST', body: JSON.stringify({ nombre: d.nombre, nacimiento: d.nacimiento || null, defuncion: d.defuncion || null }) }); if (res && res.ok) migrados++; } catch (e) { /* si falla uno, continuar con el siguiente */ } } if (migrados > 0) { localStorage.removeItem(claveAnonima); _difuntosCache = null; } } async function agregarDifunto() { const nombre = document.getElementById("difunto-nombre").value.trim(); if (!nombre) return; const nacimiento = document.getElementById("difunto-nacimiento").value || null; const defuncion = document.getElementById("difunto-defuncion").value || null; try { const res = await apiCall('/difuntos/personales', { method: 'POST', body: JSON.stringify({ nombre, nacimiento, defuncion }) }); if (res && res.ok) { _difuntosCache = null; // invalidar caché } else { // Guardar local si falla const difuntos = JSON.parse(localStorage.getItem(keyDifuntos()) || '[]'); difuntos.push({ id: Date.now().toString(), nombre, nacimiento, defuncion }); localStorage.setItem(keyDifuntos(), JSON.stringify(difuntos)); } } catch (e) { const difuntos = JSON.parse(localStorage.getItem(keyDifuntos()) || '[]'); difuntos.push({ id: Date.now().toString(), nombre, nacimiento, defuncion }); localStorage.setItem(keyDifuntos(), JSON.stringify(difuntos)); } document.getElementById("difunto-nombre").value = ""; document.getElementById("difunto-nacimiento").value = ""; document.getElementById("difunto-defuncion").value = ""; cargarDifuntos(); } async function eliminarDifunto(id) { try { const res = await apiCall(`/difuntos/personales/${id}`, { method: 'DELETE' }); if (res && (res.ok || res.status === 204)) { _difuntosCache = null; // Sincronizar localStorage const local = JSON.parse(localStorage.getItem(keyDifuntos()) || '[]'); localStorage.setItem(keyDifuntos(), JSON.stringify(local.filter(d => String(d.id) !== String(id)))); return; } } catch (e) { /* sin conexión: eliminar solo local */ } // Fallback: solo localStorage const difuntos = JSON.parse(localStorage.getItem(keyDifuntos()) || '[]').filter(d => String(d.id) !== String(id)); localStorage.setItem(keyDifuntos(), JSON.stringify(difuntos)); } async function cargarDifuntos() { const lista = document.getElementById("lista-difuntos"); const sinDifuntos = document.getElementById("sin-difuntos"); const todos = _difuntosCache || await _apiGetDifuntos(); // Actualizar navegador de mes const navMes = document.getElementById("nav-mes-difuntos"); if (navMes) { document.getElementById("nombre-mes-difuntos").textContent = MESES_ES[_mesDifuntos]; } // Filtrar por mes seleccionado const mesNum = _mesDifuntos + 1; // 1-12 const difuntos = todos.filter(d => { const nacMes = d.nacimiento ? parseInt(d.nacimiento.split('-')[1]) : null; const defMes = d.defuncion ? parseInt(d.defuncion.split('-')[1]) : null; return nacMes === mesNum || defMes === mesNum; }); lista.innerHTML = ""; if (difuntos.length === 0) { sinDifuntos.style.display = "block"; sinDifuntos.textContent = `No hay difuntos con fechas en ${MESES_ES[_mesDifuntos]}.`; return; } sinDifuntos.style.display = "none"; difuntos.forEach(d => { const li = document.createElement("li"); li.className = "item-difunto"; const etiquetas = []; if (d.nacimiento) { const f = new Date(d.nacimiento + "T12:00:00"); etiquetas.push(`🎂 ${f.toLocaleDateString("es-ES", { day: "numeric", month: "long", year: "numeric" })}`); } if (d.defuncion) { const f = new Date(d.defuncion + "T12:00:00"); etiquetas.push(`✝ ${f.toLocaleDateString("es-ES", { day: "numeric", month: "long", year: "numeric" })}`); } li.innerHTML = `
🕯 ${d.nombre} ${etiquetas.join("")}
`; lista.appendChild(li); }); lista.querySelectorAll(".btn-eliminar-difunto").forEach(btn => { btn.addEventListener("click", async () => { await eliminarDifunto(btn.dataset.id); cargarDifuntos(); }); }); // Botones de navegación de mes (se reasignan cada vez para evitar duplicados) const btnPrev = document.getElementById("btn-mes-prev"); const btnNext = document.getElementById("btn-mes-next"); if (btnPrev) { btnPrev.onclick = () => { _mesDifuntos = (_mesDifuntos + 11) % 12; cargarDifuntos(); }; } if (btnNext) { btnNext.onclick = () => { _mesDifuntos = (_mesDifuntos + 1) % 12; cargarDifuntos(); }; } } // ── 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"); const autorModal = document.getElementById("autor-modal"); const btnBorrar = document.getElementById("btn-borrar-modal"); let intencionActivaId = null; document.addEventListener("click", e => { const hex = e.target.closest(".hexagono"); if (!hex) return; textoModal.textContent = hex.dataset.texto; iconoModal.src = "img/iconos/" + hex.dataset.icono; autorModal.textContent = hex.dataset.autor ? `— ${hex.dataset.autor}` : ""; intencionActivaId = hex.dataset.id || null; // Solo mostrar botón borrar si es la propia intención btnBorrar.style.display = hex.dataset.esPropia === "true" ? "inline-block" : "none"; modal.classList.add("visible"); }); cerrar.onclick = () => modal.classList.remove("visible"); modal.onclick = e => { if (e.target === modal) modal.classList.remove("visible"); }; btnBorrar.onclick = async () => { if (!intencionActivaId) return; try { const response = await apiCall(`/intenciones/${intencionActivaId}`, { method: "DELETE" }); if (response && response.ok) { modal.classList.remove("visible"); cargarIntenciones(); } } catch (e) { // Fallback local const local = JSON.parse(localStorage.getItem(keyIntenciones()) || "[]"); const idx = local.findIndex(i => i.texto === textoModal.textContent); if (idx !== -1) { local.splice(idx, 1); localStorage.setItem(keyIntenciones(), JSON.stringify(local)); } modal.classList.remove("visible"); cargarIntenciones(); } }; // ── ARRANQUE (se llama desde header.js tras cargar el header) ── // header.js invoca las funciones de inicialización tras insertar el header. // Para intenciones, usamos DOMContentLoaded como punto de entrada seguro. document.addEventListener("DOMContentLoaded", init);