219 lines
8.1 KiB
TypeScript
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;
|