erp-core-frontend-web/src/pages/auth/LoginPage.tsx

117 lines
3.5 KiB
TypeScript

import { useState } from 'react';
import { Link, useNavigate, useLocation } from 'react-router-dom';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Mail, Lock, Eye, EyeOff } from 'lucide-react';
import { AuthLayout } from '@app/layouts/AuthLayout';
import { Button } from '@components/atoms/Button';
import { FormField } from '@components/molecules/FormField';
import { Alert } from '@components/molecules/Alert';
import { useAuthStore } from '@stores/useAuthStore';
const loginSchema = z.object({
email: z.string().email('Email inválido'),
password: z.string().min(1, 'La contraseña es requerida'),
});
type LoginFormData = z.infer<typeof loginSchema>;
export default function LoginPage() {
const navigate = useNavigate();
const location = useLocation();
const { login, isLoading, error, clearError } = useAuthStore();
const [showPassword, setShowPassword] = useState(false);
const from = (location.state as { from?: Location })?.from?.pathname || '/dashboard';
const {
register,
handleSubmit,
formState: { errors },
} = useForm<LoginFormData>({
resolver: zodResolver(loginSchema),
});
const onSubmit = async (data: LoginFormData) => {
try {
await login(data);
navigate(from, { replace: true });
} catch {
// Error is handled in the store
}
};
return (
<AuthLayout
title="Iniciar sesión"
subtitle="Ingresa tus credenciales para acceder a tu cuenta"
>
{error && (
<Alert variant="danger" onClose={clearError} className="mb-4">
{error}
</Alert>
)}
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
<FormField
label="Email"
type="email"
placeholder="tu@email.com"
error={errors.email?.message}
leftIcon={<Mail className="h-5 w-5" />}
{...register('email')}
/>
<FormField
label="Contraseña"
type={showPassword ? 'text' : 'password'}
placeholder="••••••••"
error={errors.password?.message}
leftIcon={<Lock className="h-5 w-5" />}
rightIcon={
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="text-gray-400 hover:text-gray-600"
>
{showPassword ? <EyeOff className="h-5 w-5" /> : <Eye className="h-5 w-5" />}
</button>
}
{...register('password')}
/>
<div className="flex items-center justify-between">
<label className="flex items-center">
<input
type="checkbox"
className="h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-500"
/>
<span className="ml-2 text-sm text-gray-600">Recordarme</span>
</label>
<Link
to="/forgot-password"
className="text-sm font-medium text-primary-600 hover:text-primary-500"
>
¿Olvidaste tu contraseña?
</Link>
</div>
<Button type="submit" fullWidth isLoading={isLoading}>
Iniciar sesión
</Button>
</form>
<p className="mt-6 text-center text-sm text-gray-600">
¿No tienes cuenta?{' '}
<Link
to="/register"
className="font-medium text-primary-600 hover:text-primary-500"
>
Regístrate aquí
</Link>
</p>
</AuthLayout>
);
}