quiniela-sembradores-frontend/app/login/page.tsx

219 lines
8.1 KiB
TypeScript

'use client';
import React, {ChangeEvent, useState} from 'react';
import Link from 'next/link';
import {useRouter, useSearchParams} from 'next/navigation';
import {Alert, Box, Button, Paper, Stack, TextField, Typography} from '@mui/material';
import GoogleIcon from '@mui/icons-material/Google';
import AppleIcon from '@mui/icons-material/Apple';
import {ApiError} from '@/lib/api/client';
import {useAuth} from "@/src/auth/AuthProvider";
import {GuestGuard} from "@/src/auth/GuestGuard";
type LoginValues = {
email: string;
password: string;
};
const Page: React.FC = () => {
const router = useRouter();
const searchParams = useSearchParams();
const next = searchParams.get('next') || '/';
const {login} = useAuth()
const [values, setValues] = useState<LoginValues>({
email: '',
password: '',
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [serverError, setServerError] = useState('');
const handleChange =
(field: keyof LoginValues) => (event: ChangeEvent<HTMLInputElement>) => {
setValues((current) => ({
...current,
[field]: event.target.value,
}));
};
const handleSubmit = async (event: React.SubmitEvent<HTMLFormElement>) => {
event.preventDefault();
setServerError('');
setIsSubmitting(true);
try {
await login(values)
router.replace(next);
router.refresh()
} catch (error: unknown) {
if (error instanceof ApiError) {
setServerError(error.message);
} else {
setServerError('No fue posible iniciar sesión')
}
} finally {
setIsSubmitting(false)
}
};
const handleGoogleLogin = () => {
// TODO: wire up Google auth here
console.log('Continuar con Google');
};
const handleAppleLogin = () => {
// TODO: wire up Apple auth here
console.log('Continuar con Apple');
};
return (
<GuestGuard>
<Box
sx={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'grey.100',
p: 3,
}}
>
<Paper
elevation={4}
sx={{
width: '100%',
maxWidth: 360,
borderRadius: 4,
px: 3,
py: 4,
textAlign: 'center',
}}
>
<Typography variant="h4" fontWeight={700} gutterBottom>
Bienvenido
</Typography>
<Typography variant="body1" color="text.secondary" sx={{mb: 3}}>
Regístrate o inicia sesión con tu cuenta preferida
</Typography>
<Box component="form" onSubmit={handleSubmit}>
<Stack spacing={2}>
{serverError ? <Alert severity="error">{serverError}</Alert> : null}
<TextField
label="Correo electrónico"
name="email"
type="email"
autoComplete="email"
value={values.email}
onChange={handleChange('email')}
required
fullWidth
/>
<TextField
label="Contraseña"
name="password"
type="password"
autoComplete="current-password"
value={values.password}
onChange={handleChange('password')}
required
fullWidth
/>
<Button
type="submit"
variant="contained"
size="large"
fullWidth
disabled={isSubmitting}
sx={{
py: 1.5,
borderRadius: 2.5,
textTransform: 'none',
fontSize: 16,
fontWeight: 700,
}}
>
{isSubmitting ? 'Iniciando sesión...' : 'Iniciar sesión'}
</Button>
<Typography variant="body2" color="text.secondary">
¿No tienes cuenta?{' '}
<Box
component={Link}
href="/register"
sx={{
color: 'primary.main',
textDecoration: 'none',
fontWeight: 600,
}}
>
Regístrate
</Box>
</Typography>
<Typography variant="body2" color="text.secondary">
---------- o -----------
</Typography>
</Stack>
</Box>
<Stack spacing={1.5} sx={{mt: 2}}>
<Button
type="button"
variant="outlined"
size="large"
fullWidth
onClick={handleGoogleLogin}
sx={{
py: 1.5,
borderRadius: 2.5,
textTransform: 'none',
fontSize: 16,
fontWeight: 600,
justifyContent: 'center',
}}
>
<Box display='flex' flexDirection='row' sx={{justifyContent: 'center'}}>
<GoogleIcon sx={{mr: 1}}/>
<Typography>Continuar con Google</Typography>
</Box>
</Button>
<Button
type="button"
variant="contained"
size="large"
fullWidth
onClick={handleAppleLogin}
sx={{
py: 1.5,
borderRadius: 2.5,
textTransform: 'none',
fontSize: 16,
fontWeight: 600,
bgcolor: '#111827',
'&:hover': {
bgcolor: '#000000',
},
justifyItems: 'center',
}}
>
<Box display='flex' flexDirection='row' sx={{justifyContent: 'center'}}>
<AppleIcon sx={{mr: 1}}/>
<Typography>Continuar con Apple</Typography>
</Box>
</Button>
</Stack>
</Paper>
</Box>
</GuestGuard>
);
};
export default Page;