// Login overlay for BControl v0.5 function LoginOverlay({ onLogin, successBanner }) { 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(''); const [fbStatus, setFbStatus] = React.useState(null); // null | 'loading' | 'error' const [fbErr, setFbErr] = React.useState(''); async function signInWithGoogle() { setFbStatus('loading'); setFbErr(''); try { const provider = new firebase.auth.GoogleAuthProvider(); const result = await window.fbAuth.signInWithPopup(provider); const idToken = await result.user.getIdToken(); const res = await fetch('/auth/firebase-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id_token: idToken }), }); if (!res.ok) { const data = await res.json().catch(() => ({})); setFbStatus('error'); setFbErr(data.detail || 'Acceso denegado.'); return; } const meRes = await fetch('/auth/me'); const user = await meRes.json(); setFbStatus(null); onLogin(user); } catch (err) { setFbStatus('error'); setFbErr(err.message || 'Error al iniciar sesión con Google.'); } } 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}
{/* Firebase sign-in */} {fbStatus === 'error' && (
{fbErr}
)}
o con usuario y contraseña
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
)} {successBanner && (
{successBanner}
)}
CARLOS INCENDIO SPA SANTIAGO · CHILE · 2026
); } window.LoginOverlay = LoginOverlay;