Difuntos e intenciones personales

This commit is contained in:
Tatiana Villa 2026-04-28 13:11:45 +02:00
parent cf4c09abf4
commit b2ca38f0af
5 changed files with 130 additions and 45 deletions

View File

@ -261,6 +261,45 @@
border-color: var(--color-acento);
}
/* NAVEGADOR DE MES */
.nav-mes {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin: 1rem 0 0.8rem;
}
.nombre-mes {
font-size: 1rem;
font-weight: 600;
min-width: 120px;
text-align: center;
color: var(--color-texto);
text-transform: capitalize;
}
.btn-mes {
background: none;
border: 1px solid var(--color-acento, #c8a96e);
color: var(--color-acento, #c8a96e);
border-radius: 50%;
width: 2rem;
height: 2rem;
font-size: 1.4rem;
line-height: 1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s;
}
.btn-mes:hover {
background: var(--color-acento, #c8a96e);
color: #fff;
}
/* LISTA DE DIFUNTOS */
.lista-difuntos {
list-style: none;

View File

@ -17,7 +17,7 @@
},
{
"nombre": "Visi Correas González",
"nacimiento": "XXXX-11-14",
"nacimiento": "1900-11-14",
"fallecimiento": "2024-02-04",
"nota": ""
},
@ -83,8 +83,8 @@
},
{
"nombre": "Mauricio Sánchez",
"nacimiento": "XXXX-09-22",
"fallecimiento": "XXXX-08-20",
"nacimiento": "1900-09-22",
"fallecimiento": "1900-08-20",
"nota": ""
},
{

View File

@ -39,6 +39,11 @@
</div>
<button id="btn-guardar-difunto" class="boton">Añadir</button>
</div>
<div id="nav-mes-difuntos" class="nav-mes">
<button id="btn-mes-prev" class="btn-mes" title="Mes anterior">&#8249;</button>
<span id="nombre-mes-difuntos" class="nombre-mes">Abril</span>
<button id="btn-mes-next" class="btn-mes" title="Mes siguiente">&#8250;</button>
</div>
<ul id="lista-difuntos" class="lista-difuntos"></ul>
<p id="sin-difuntos" class="texto-suave" style="display:none; margin-top:1rem;">Aún no has añadido ningún difunto.</p>
</div>

View File

@ -141,77 +141,89 @@ async function recordatorioDifuntos() {
if (!seccion) return;
const hoy = new Date();
const mmdd = String(hoy.getMonth() + 1).padStart(2, "0") + "-" + String(hoy.getDate()).padStart(2, "0");
const mesActual = hoy.getMonth() + 1; // 1-12
const mmdd = String(mesActual).padStart(2, "0") + "-" + String(hoy.getDate()).padStart(2, "0");
const nombreMes = hoy.toLocaleDateString('es-ES', { month: 'long' });
// 1. Lista compartida desde difuntos.json (normalizar fallecimiento -> defuncion)
let difuntosJSON = [];
try {
const res = await fetch('data/difuntos.json');
if (res.ok) {
const data = await res.json();
difuntosJSON = data.map(d => ({
nombre: d.nombre,
nacimiento: d.nacimiento,
defuncion: d.fallecimiento,
nota: d.nota || ""
}));
}
} catch (e) { /* sin conexion */ }
// 2. Difuntos personales desde localStorage
// 1. Difuntos personales desde la API (usuario logueado) o localStorage
const usuarioGuardado = typeof getUsuario === 'function' ? getUsuario() : null;
const clave = usuarioGuardado
? `difuntos_personales_${usuarioGuardado.id}`
: "difuntos_personales_anonimo";
const difuntosLocal = JSON.parse(localStorage.getItem(clave) || "[]");
let todosDifuntos = [];
// 3. Combinar (locales primero, sin duplicados por nombre)
const nombresSeen = new Set();
const todos = [...difuntosLocal, ...difuntosJSON].filter(d => {
if (!d.nombre || nombresSeen.has(d.nombre)) return false;
nombresSeen.add(d.nombre);
return true;
if (usuarioGuardado) {
try {
const res = await fetch(`${API_BASE}/difuntos/personales`, {
headers: { 'Authorization': 'Bearer ' + (localStorage.getItem('token') || '') }
});
if (res.ok) {
todosDifuntos = await res.json();
// La API devuelve 'defuncion', igual que localStorage
}
} catch (e) { /* sin conexión */ }
}
// Fallback localStorage si no hay API o no hay usuario
if (todosDifuntos.length === 0) {
const clave = usuarioGuardado
? `difuntos_personales_${usuarioGuardado.id}`
: "difuntos_personales_anonimo";
todosDifuntos = JSON.parse(localStorage.getItem(clave) || "[]");
}
if (todosDifuntos.length === 0) return;
// 2. Filtrar los que tienen aniversario o cumpleaños en el mes actual
const delMes = todosDifuntos.filter(d => {
const nacMes = d.nacimiento && !d.nacimiento.includes('XXXX')
? parseInt(d.nacimiento.split('-')[1]) : null;
const defMes = d.defuncion && !d.defuncion.includes('XXXX')
? parseInt(d.defuncion.split('-')[1]) : null;
return nacMes === mesActual || defMes === mesActual;
});
if (todos.length === 0) return;
if (delMes.length === 0) return;
// 4. Detectar aniversarios de hoy
// 3. Detectar aniversarios de hoy (dentro de los del mes)
const recordatorios = [];
todos.forEach(d => {
delMes.forEach(d => {
if (d.nacimiento && !d.nacimiento.includes('XXXX')) {
const partes = d.nacimiento.split("-");
if (partes.length === 3 && partes[1] + "-" + partes[2] === mmdd) {
const anios = hoy.getFullYear() - parseInt(partes[0]);
recordatorios.push("\uD83C\uDF82 Hoy habr\u00eda sido el cumplea\u00F1os de <strong>" + d.nombre + "</strong> &mdash; " + anios + " a\u00F1os");
recordatorios.push("🎂 Hoy habría sido el cumpleaños de <strong>" + d.nombre + "</strong> &mdash; " + anios + " años");
}
}
if (d.defuncion && !d.defuncion.includes('XXXX')) {
const partes = d.defuncion.split("-");
if (partes.length === 3 && partes[1] + "-" + partes[2] === mmdd) {
const anios = hoy.getFullYear() - parseInt(partes[0]);
recordatorios.push("\uD83D\uDD6F Hoy es el " + anios + ".\u00BA aniversario del fallecimiento de <strong>" + d.nombre + "</strong>");
recordatorios.push("🕯 Hoy es el " + anios + ".º aniversario del fallecimiento de <strong>" + d.nombre + "</strong>");
}
}
});
// 5. Construir HTML
// 4. Construir HTML
seccion.style.display = "block";
let html = '<h3>\uD83D\uDD6F En el recuerdo</h3>';
let html = `<h3>🕯 En el recuerdo — ${nombreMes.charAt(0).toUpperCase() + nombreMes.slice(1)}</h3>`;
if (recordatorios.length > 0) {
html += recordatorios.map(r => `<p>${r}</p>`).join("");
html += '<p class="recordatorio-oracion"><em>"D\u00E1les, Se\u00F1or, el descanso eterno y brille para ellos la luz perpetua."</em></p>';
html += '<p class="recordatorio-oracion"><em>"Dales, Señor, el descanso eterno y brille para ellos la luz perpetua."</em></p>';
html += '<hr style="border-color:rgba(255,255,255,0.15);margin:0.8rem 0;">';
}
html += '<ul class="lista-difuntos-index">';
todos.forEach(d => {
let anioStr = "";
if (d.defuncion && !d.defuncion.includes('XXXX')) {
const anio = parseInt(d.defuncion.split('-')[0]);
if (anio > 1000) anioStr = ' <span class="anio-difunto">(\u2020 ' + anio + ')</span>';
delMes.forEach(d => {
let fechaStr = "";
if (d.nacimiento && !d.nacimiento.includes('XXXX')) {
const dia = parseInt(d.nacimiento.split('-')[2]);
fechaStr += ` <span class="anio-difunto">(🎂 ${dia})</span>`;
}
html += '<li>\uD83D\uDD4A ' + d.nombre + anioStr + '</li>';
if (d.defuncion && !d.defuncion.includes('XXXX')) {
const dia = parseInt(d.defuncion.split('-')[2]);
const anio = parseInt(d.defuncion.split('-')[0]);
fechaStr += ` <span class="anio-difunto">(✝ ${dia}${anio > 1000 ? ' · ' + anio : ''})</span>`;
}
html += '<li>🕊 ' + d.nombre + fechaStr + '</li>';
});
html += '</ul>';

View File

@ -209,6 +209,10 @@ function crearHexagono(intencion) {
// 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 {
@ -309,12 +313,27 @@ async function eliminarDifunto(id) {
async function cargarDifuntos() {
const lista = document.getElementById("lista-difuntos");
const sinDifuntos = document.getElementById("sin-difuntos");
const difuntos = _difuntosCache || await _apiGetDifuntos();
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";
@ -349,6 +368,16 @@ async function cargarDifuntos() {
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 ────────────────────────────────────────────────────