// ============================================================ // Login screen // ============================================================ const Login = ({ onLogin, authStatus = 'unauthenticated', onRetry }) => { const [selected, setSelected] = useState(null); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); const isLocalDemo = window.persistenceAdapter.mode === 'local_demo' && window.APP_CONFIG.AUTH.ALLOW_LOCAL_DEMO; const listaUsuarios = isLocalDemo ? window.persistenceAdapter.getLocalDemoUsers() : []; const safeErrorMessage = (loginError) => { if (loginError?.status === 401) return 'Usuario o contraseña incorrectos.'; if (loginError?.status === 403) return 'La cuenta se encuentra inactiva. Contacta al administrador.'; if (loginError?.status === 422) return 'Revisa los datos de acceso e inténtalo de nuevo.'; if (loginError?.status === 0) return 'No fue posible conectar con el servidor. Verifica que Apache y MySQL estén activos.'; return 'No fue posible iniciar sesión. Inténtalo nuevamente.'; }; const handleLogin = async (e) => { e && e.preventDefault(); if (authStatus !== 'unauthenticated' || isSubmitting) return; if (isLocalDemo && !selected) { setError('Selecciona un usuario'); return; } if (!isLocalDemo && !username.trim()) { setError('Ingresa tu usuario'); return; } if (!password) { setError('Ingresa tu contraseña'); return; } setIsSubmitting(true); setError(''); try { const user = await window.persistenceAdapter.login( isLocalDemo ? selected.id : username.trim(), password ); onLogin(user); } catch (loginError) { setPassword(''); setError(safeErrorMessage(loginError)); } finally { setIsSubmitting(false); } }; return (
Fondo Editorial · Proyecto 2026
Sistema de Control de Digitalización de Libros
Control de producción por proceso, asignación FIFO, registro de productividad y seguimiento de metas para la digitalización de fondos bibliográficos.
409
Libros meta
70,000
Imágenes meta
12 Sep
Deadline 2026
Iniciar sesión
{isLocalDemo ? 'Selecciona tu usuario para continuar' : 'Ingresa tus credenciales para continuar'}
{isLocalDemo ? (
{listaUsuarios.map(u => (
{ setSelected(u); setError(''); }} >
{u.nombre.split(' ')[0]}
{u.roles.includes('supervisor') ? 'Supervisor' : u.roles.length > 2 ? 'Multi-rol' : APP_DATA.ROLES[u.roles[0]].label.split(' ')[0]}
))}
) : (
{ setUsername(e.target.value); setError(''); }} autoComplete="username" autoFocus disabled={authStatus !== 'unauthenticated' || isSubmitting} />
)}
{ setPassword(e.target.value); setError(''); }} autoComplete="current-password" autoFocus={isLocalDemo} disabled={authStatus !== 'unauthenticated' || isSubmitting} /> {isLocalDemo &&
Demo: usa cualquier texto
}
{authStatus === 'initializing' && (
Verificando sesión…
)} {authStatus === 'unavailable' && (
El servicio de autenticación no está disponible.
)} {error &&
{error}
} {authStatus === 'unavailable' && ( )} {isLocalDemo && (
Perfiles disponibles:
Supervisor Oscar, Ramón · Digitalización Vivi, Oscar, José, Arturo, Ana · Edición Katy, Pao, Fernanda, Oscar, José, Arturo, Ana · CC/Conversión Ana
)}
); }; Object.assign(window, { Login });