Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013SfRSvDd335NPYEbBrDFGE
133 lines
6.9 KiB
JavaScript
133 lines
6.9 KiB
JavaScript
/* Página de entrada (27-oct-2026).
|
||
- Si ya hay sesión, salta directo a donde ibas (nginx manda aquí con #/ruta/original).
|
||
- Entrar: POST /api/entrar → el servidor pone la cookie de sesión; el mensaje dice qué pasó.
|
||
- Avisos públicos del sitio (incidencias marcadas «publica») y reporte sin sesión (POST /api/incidencias/publica). */
|
||
(function () {
|
||
var $ = function (id) { return document.getElementById(id); };
|
||
|
||
function destino() {
|
||
// Solo rutas de ESTE sitio: se arma la URL completa y se exige el mismo origen (un «/\t/otro.com» o «/\\otro.com»
|
||
// se vuelve «//otro.com» en el navegador: comparar el origen lo cierra). Nunca regresa a la entrada.
|
||
var h = '';
|
||
try { h = decodeURIComponent((location.hash || '').slice(1)); } catch (e) { h = ''; }
|
||
if (!h || h.charAt(0) !== '/') return '/';
|
||
try {
|
||
var u = new URL(h, location.origin);
|
||
if (u.origin !== location.origin || /^\/entrar\.html/.test(u.pathname)) return '/';
|
||
return u.href; // absoluta y del mismo origen (un «/.//otro.com» relativo sería otro sitio)
|
||
} catch (e) { return '/'; }
|
||
}
|
||
function ir() { location.replace(destino()); }
|
||
function mensaje(el, html, bien) { el.className = 'en-msg ' + (bien ? 'ok' : 'err'); el.innerHTML = html; }
|
||
function esc(s) { var d = document.createElement('div'); d.textContent = s == null ? '' : String(s); return d.innerHTML; }
|
||
|
||
// ¿ya hay sesión?
|
||
fetch('/api/sesion', { cache: 'no-store', credentials: 'same-origin' })
|
||
.then(function (r) { return r.ok ? r.json() : null; })
|
||
.then(function (j) { if (j && j.sesion) ir(); })
|
||
.catch(function () {});
|
||
|
||
// usuario recordado (solo el nombre, nunca la contraseña)
|
||
try { var u0 = localStorage.getItem('hbox.usuario'); if (u0) { $('usuario').value = u0; } } catch (e) {}
|
||
($('usuario').value ? $('password') : $('usuario')).focus();
|
||
|
||
$('ver').addEventListener('click', function () {
|
||
var p = $('password'), mostrar = p.type === 'password';
|
||
p.type = mostrar ? 'text' : 'password';
|
||
this.textContent = mostrar ? 'Ocultar' : 'Ver';
|
||
this.setAttribute('aria-pressed', mostrar ? 'true' : 'false');
|
||
this.setAttribute('aria-label', mostrar ? 'Ocultar la contraseña' : 'Mostrar la contraseña');
|
||
});
|
||
function revisarMayus(ev) {
|
||
if (ev.getModifierState) $('mayus').hidden = !ev.getModifierState('CapsLock');
|
||
}
|
||
$('password').addEventListener('keydown', revisarMayus);
|
||
$('password').addEventListener('keyup', revisarMayus);
|
||
|
||
$('fEntrar').addEventListener('submit', function (ev) {
|
||
ev.preventDefault();
|
||
var b = $('bEntrar'), msg = $('msg');
|
||
var usuario = $('usuario').value.trim(), password = $('password').value;
|
||
if (!usuario || !password) { mensaje(msg, 'Escribe tu usuario y tu contraseña.', false); return; }
|
||
b.disabled = true; b.textContent = 'Entrando…';
|
||
fetch('/api/entrar', {
|
||
method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ usuario: usuario, password: password, recordar: $('recordar').checked })
|
||
}).then(function (r) {
|
||
return r.json().catch(function () { return { ok: false, error: 'El servidor no respondió bien (HTTP ' + r.status + ').' }; });
|
||
}).then(function (j) {
|
||
if (j && j.ok) {
|
||
try { localStorage.setItem('hbox.usuario', usuario); } catch (e) {}
|
||
mensaje(msg, '<b>Listo, ' + esc(j.user) + '.</b> Abriendo el sitio…', true);
|
||
ir();
|
||
return;
|
||
}
|
||
var t = esc((j && j.error) || 'No se pudo entrar.');
|
||
if (j && j.codigo === 'contrasena') {
|
||
$('password').value = ''; $('password').focus();
|
||
} else if (j && j.codigo === 'usuario') {
|
||
$('usuario').focus();
|
||
}
|
||
if (j && (j.codigo === 'bloqueado' || j.codigo === 'contrasena')) {
|
||
t += ' <a href="#" id="abrirAyuda">Reportar el problema</a>.';
|
||
}
|
||
mensaje(msg, t, false);
|
||
var a = $('abrirAyuda');
|
||
if (a) a.addEventListener('click', function (e) { e.preventDefault(); abrirAyuda(); });
|
||
}).catch(function () {
|
||
mensaje(msg, 'No pude contactar al servidor. Revisa tu conexión e intenta otra vez; si sigue, repórtalo abajo.', false);
|
||
}).then(function () { b.disabled = false; b.textContent = 'Entrar'; });
|
||
});
|
||
|
||
function abrirAyuda() {
|
||
var d = $('ayuda'); d.open = true;
|
||
if (!$('rNombre').value) $('rNombre').value = $('usuario').value.trim();
|
||
d.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
setTimeout(function () { $('rDesc').focus(); }, 300);
|
||
}
|
||
$('ayuda').addEventListener('toggle', function () {
|
||
if (this.open && !$('rNombre').value) $('rNombre').value = $('usuario').value.trim();
|
||
});
|
||
|
||
$('fReporte').addEventListener('submit', function (ev) {
|
||
ev.preventDefault();
|
||
var b = $('bReporte'), msg = $('msgR');
|
||
var tipo = (document.querySelector('input[name="rTipo"]:checked') || {}).value || 'acceso';
|
||
var cuerpo = { nombre: $('rNombre').value.trim(), contacto: $('rContacto').value.trim(), descripcion: $('rDesc').value.trim(),
|
||
tipo: tipo, sitio_web: $('rTrampa').value, pantalla: screen.width + '×' + screen.height };
|
||
if (cuerpo.descripcion.length < 5) { mensaje(msg, 'Cuéntanos qué pasa (aunque sea una línea).', false); return; }
|
||
if (!cuerpo.nombre && !cuerpo.contacto) { mensaje(msg, 'Dinos quién eres o cómo contactarte.', false); return; }
|
||
b.disabled = true; b.textContent = 'Enviando…';
|
||
fetch('/api/incidencias/publica', {
|
||
method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(cuerpo)
|
||
}).then(function (r) { return r.json().catch(function () { return { ok: false, error: 'HTTP ' + r.status }; }); })
|
||
.then(function (j) {
|
||
if (j && j.ok) {
|
||
mensaje(msg, '<b>Recibido: ' + esc(j.id) + '.</b> Se revisa todos los días; si dejaste cómo contactarte, te buscamos. '
|
||
+ 'Guarda el folio por si preguntas.', true);
|
||
$('rDesc').value = '';
|
||
} else {
|
||
mensaje(msg, esc((j && j.error) || 'No se pudo enviar.'), false);
|
||
}
|
||
})
|
||
.catch(function () { mensaje(msg, 'No pude contactar al servidor. Avísale a Leo o a Gibran por mensaje.', false); })
|
||
.then(function () { b.disabled = false; b.textContent = 'Enviar reporte'; });
|
||
});
|
||
|
||
// avisos públicos
|
||
fetch('/api/incidencias/publicas', { cache: 'no-store', credentials: 'same-origin' })
|
||
.then(function (r) { return r.ok ? r.json() : null; })
|
||
.then(function (j) {
|
||
if (!j || !j.ok || !j.avisos || !j.avisos.length) return;
|
||
var ul = $('avisosLista');
|
||
j.avisos.forEach(function (a) {
|
||
var li = document.createElement('li');
|
||
li.innerHTML = '<span class="en-pill' + (a.resuelta ? ' ok' : '') + '">' + (a.resuelta ? 'Resuelto' : 'En atención') + '</span>'
|
||
+ '<span>' + esc(a.titulo) + '</span> <small>' + esc(a.actualizado) + '</small>';
|
||
ul.appendChild(li);
|
||
});
|
||
$('avisos').hidden = false;
|
||
})
|
||
.catch(function () {});
|
||
})();
|