'use client'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { useAuthStore } from '@/lib/auth/client/useAuthStore'; import { apiClient } from '@/lib/utils/api-client'; import { logInfo, logError } from '@/lib/logger/client-logger'; type LoginStep = 'credentials' | 'twoFactor'; export default function LoginForm() { const [step, setStep] = useState('credentials'); const [userName, setUserName] = useState(''); const [password, setPassword] = useState(''); const [softToken, setSoftToken] = useState(''); const [error, setError] = useState(''); const [userNameError, setUserNameError] = useState(''); const [passwordError, setPasswordError] = useState(''); const [tokenError, setTokenError] = useState(''); const [isLoading, setIsLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); const [showDeactivateToken, setShowDeactivateToken] = useState(false); const router = useRouter(); const { setUser, setRequires2FA, setLoading } = useAuthStore(); useEffect(() => { if (userName.length > 12) { setUserName(userName.substring(0, 12)); } }, [userName]); const validateUserName = (value: string): string => { if (!value || value.trim() === '') { return 'Este campo es obligatorio'; } if (value.length < 6) { return 'Debe ser mayor o igual a seis caracteres'; } return ''; }; const validatePassword = (value: string): string => value?.trim() ? '' : 'Este campo es obligatorio'; const validateToken = (value: string): string => value?.trim() ? '' : 'Este campo es obligatorio'; const handleUserNameChange = (e: React.ChangeEvent) => { const value = e.target.value; setUserName(value); setUserNameError(validateUserName(value)); setError(''); }; const handlePasswordChange = (e: React.ChangeEvent) => { const value = e.target.value; setPassword(value); setPasswordError(validatePassword(value)); setError(''); }; const handleTokenChange = (e: React.ChangeEvent) => { const value = e.target.value; setSoftToken(value); setTokenError(validateToken(value)); setError(''); }; const handleCredentialsSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(''); const userNameErr = validateUserName(userName); const passwordErr = validatePassword(password); setUserNameError(userNameErr); setPasswordError(passwordErr); if (userNameErr || passwordErr) { return; } setIsLoading(true); setLoading(true); try { const response = await apiClient.post('/api/auth/login', { userName, password }); if (response.error) { throw new Error(response.error); } if (response.requires2FA) { setRequires2FA(true, userName); setStep('twoFactor'); setShowDeactivateToken(true); } else { setUser(response.user); logInfo('Login exitoso de credenciales', { userId: response.user.id }); router.push('/dashboard'); router.refresh(); } } catch (err: any) { logError('Error en credenciales de login', { error: err.message }); setError(err.message || 'Error desconocido.'); } finally { setIsLoading(false); setLoading(false); } }; const handleTwoFactorSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(''); const tokenErr = validateToken(softToken); setTokenError(tokenErr); if (tokenErr) { return; } setIsLoading(true); setLoading(true); try { const response = await apiClient.post('/api/auth/login', { userName, password, softToken }); if (response.error) { throw new Error(response.error); } setUser(response.user); logInfo('Login exitoso con 2FA completado', { userId: response.user.id }); router.push('/dashboard'); router.refresh(); } catch (err: any) { logError('Fallo de validacion de token 2FA', { error: err.message }); setError(err.message || 'Código de autenticación inválido.'); } finally { setIsLoading(false); setLoading(false); } }; const isCredentialsButtonDisabled = !userName || !password || isLoading || !!userNameError || !!passwordError; const isTokenButtonDisabled = !softToken || isLoading || !!tokenError; return (
{error && (
{error}
)} {step === 'credentials' ? ( <>
{userNameError && ( )}
{passwordError && ( )}
) : ( <>

Autenticación de dos factores (2FA)

Ingresa el código numérico de 6 dígitos de tu aplicación móvil Soft Token.

{tokenError && ( )}
{showDeactivateToken && (

¿No tienes acceso a tu móvil? Ingresa en Autogestión.

)}
)}
); }