picshop/src/components/forms/login.jsx

158 lines
5.5 KiB
React
Raw Normal View History

2024-12-04 15:35:04 +00:00
'use client';
import * as Yup from 'yup';
import { useState } from 'react';
import { useMutation } from 'react-query';
import RouterLink from 'next/link';
import { useSearchParams } from 'next/navigation';
import { useRouter } from 'next-nprogress-bar';
import toast from 'react-hot-toast';
2024-12-05 13:06:19 +00:00
import { lang } from '../lang/kr';
2024-12-04 15:35:04 +00:00
// formik
import { useFormik, Form, FormikProvider } from 'formik';
// cookies
import { createCookies } from 'src/hooks/cookies';
// redux
import { useDispatch } from 'react-redux';
import { setWishlist } from 'src/redux/slices/wishlist';
import { setLogin } from 'src/redux/slices/user';
// api
import * as api from 'src/services';
// mui
import {
Link,
Typography,
Stack,
Checkbox,
TextField,
IconButton,
InputAdornment,
2024-12-05 13:06:19 +00:00
FormControlLabel
2024-12-04 15:35:04 +00:00
} from '@mui/material';
import { LoadingButton } from '@mui/lab';
// icons
import { MdOutlineVisibility, MdLock, MdOutlineVisibilityOff } from 'react-icons/md';
import { IoMdMail } from 'react-icons/io';
export default function LoginForm() {
const { push } = useRouter();
const dispatch = useDispatch();
const searchParam = useSearchParams();
const redirect = searchParam.get('redirect');
const [loading, setloading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const { mutate } = useMutation(api.login, {
onSuccess: async (data) => {
dispatch(setLogin(data.user));
dispatch(setWishlist(data.user.wishlist));
await createCookies('token', data.token);
setloading(false);
2024-12-05 13:06:19 +00:00
toast.success(lang['Logged in successfully!']);
2024-12-04 15:35:04 +00:00
const isAdmin = data.user.role.includes('admin');
const isVendor = data.user.role.includes('vendor');
push(redirect || isAdmin ? '/admin/dashboard' : isVendor ? '/vendor/dashboard' : '/');
},
onError: (err) => {
setloading(false);
toast.error(err.response.data.message);
}
});
const LoginSchema = Yup.object().shape({
2024-12-05 13:06:19 +00:00
email: Yup.string().email(lang['Enter valid email']).required(lang['Email is required']),
password: Yup.string()
.required(lang['Password is required'])
.min(8, lang['Password should be 8 characters or longer'])
2024-12-04 15:35:04 +00:00
});
const formik = useFormik({
initialValues: {
email: '',
password: '',
remember: true
},
validationSchema: LoginSchema,
onSubmit: async (values) => {
const { email, password } = values;
setloading(true);
mutate({ email, password });
}
});
2024-12-05 13:06:19 +00:00
const { errors, touched, values, handleSubmit, getFieldProps } = formik;
2024-12-04 15:35:04 +00:00
return (
<>
<FormikProvider value={formik}>
<Form autoComplete="off" noValidate onSubmit={handleSubmit}>
<Stack spacing={3}>
<Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="email" component={'label'}>
2024-12-05 13:06:19 +00:00
{lang.Email}
2024-12-04 15:35:04 +00:00
</Typography>
<TextField
id="email"
fullWidth
autoComplete="username"
type="email"
{...getFieldProps('email')}
error={Boolean(touched.email && errors.email)}
helperText={touched.email && errors.email}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<IoMdMail size={24} />
</InputAdornment>
)
}}
/>
</Stack>
<Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="password" component={'label'}>
2024-12-05 13:06:19 +00:00
{lang.Password}
2024-12-04 15:35:04 +00:00
</Typography>
<TextField
id="password"
fullWidth
autoComplete="current-password"
type={showPassword ? 'text' : 'password'}
{...getFieldProps('password')}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<MdLock size={24} />
</InputAdornment>
),
endAdornment: (
<InputAdornment position="end">
<IconButton edge="end" onClick={() => setShowPassword((prev) => !prev)}>
{showPassword ? <MdOutlineVisibility size={24} /> : <MdOutlineVisibilityOff size={24} />}
</IconButton>
</InputAdornment>
)
}}
error={Boolean(touched.password && errors.password)}
helperText={touched.password && errors.password}
/>
</Stack>
</Stack>
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ my: 2 }}>
<FormControlLabel
control={<Checkbox {...getFieldProps('remember')} checked={values.remember} />}
2024-12-05 13:06:19 +00:00
label={lang['Remember me']}
2024-12-04 15:35:04 +00:00
/>
<Link component={RouterLink} variant="subtitle2" href="/auth/forget-password">
2024-12-05 13:06:19 +00:00
{lang['Forgot password']}
2024-12-04 15:35:04 +00:00
</Link>
</Stack>
<LoadingButton fullWidth size="large" type="submit" variant="contained" loading={loading}>
2024-12-05 13:06:19 +00:00
{lang.login}
2024-12-04 15:35:04 +00:00
</LoadingButton>
<Typography variant="subtitle2" mt={3} textAlign="center">
<Link href={`/auth/register${redirect ? '?redirect=' + redirect : ''}`} component={RouterLink}>
2024-12-05 13:06:19 +00:00
{lang.Register}
2024-12-04 15:35:04 +00:00
</Link>
</Typography>
</Form>
</FormikProvider>
</>
);
}