// Login overlay for BControl v0.5 function LoginOverlay({ onLogin }) { const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const [status, setStatus] = React.useState(null); // null | 'loading' | 'error' | 'success' const [errMsg, setErrMsg] = React.useState(''); async function submit(e) { e?.preventDefault?.(); if (!username || !password) { setStatus('error'); setErrMsg('Ingrese usuario y contraseña.'); return; } setStatus('loading'); setErrMsg(''); try { const res = await fetch('/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); if (!res.ok) { setStatus('error'); setErrMsg('Usuario o contraseña incorrectos.'); return; } const meRes = await fetch('/auth/me'); if (!meRes.ok) { setStatus('error'); setErrMsg('Error al obtener sesión.'); return; } const user = await meRes.json(); setStatus('success'); setTimeout(() => onLogin(user), 350); } catch (err) { setStatus('error'); setErrMsg('Error de conexión con el servidor.'); } } return (
{/* Brand strip */}
BControl
{APP_TITLE} · {APP_VERSION}
Ingrese sus credenciales para acceder al monitor de eventos.
setUsername(e.target.value)} placeholder="usuario" style={{ flex:1, border:'none', background:'transparent', fontSize:14, color:BC.ink }}/>
setPassword(e.target.value)} placeholder="••••••••" style={{ flex:1, border:'none', background:'transparent', fontSize:14, color:BC.ink }}/>
{status === 'error' && (
{errMsg}
)} {status === 'success' && (
Conexión exitosa
)}
CARLOS INCENDIO SPA SANTIAGO · CHILE · 2026
); } window.LoginOverlay = LoginOverlay;