You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import {
  2. Box,
  3. Button,
  4. Container,
  5. Grid,
  6. IconButton,
  7. InputAdornment,
  8. TextField,
  9. Typography,
  10. } from '@mui/material';
  11. import { useFormik } from 'formik';
  12. import { signIn } from 'next-auth/react';
  13. import { useTranslation } from 'next-i18next';
  14. import Link from 'next/link';
  15. import { useRouter } from 'next/router';
  16. import { useState } from 'react';
  17. import {
  18. BASE_PAGE,
  19. FORGOT_PASSWORD_PAGE,
  20. REGISTER_PAGE,
  21. } from '../../../constants/pages';
  22. import { loginSchema } from '../../../schemas/loginSchema';
  23. import ErrorMessageComponent from '../../mui/ErrorMessageComponent';
  24. const LoginForm = () => {
  25. const { t } = useTranslation('forms', 'login');
  26. const [showPassword, setShowPassword] = useState(false);
  27. const handleClickShowPassword = () => setShowPassword(!showPassword);
  28. const handleMouseDownPassword = () => setShowPassword(!showPassword);
  29. const router = useRouter();
  30. const [error, setError] = useState({ hasError: false, errorMessage: '' });
  31. const submitHandler = async (values) => {
  32. const result = await signIn('credentials', {
  33. redirect: false,
  34. username: values.username,
  35. password: values.password,
  36. });
  37. if (!result.error) {
  38. router.replace(BASE_PAGE);
  39. } else {
  40. setError({ hasError: true, errorMessage: result.error });
  41. }
  42. };
  43. const formik = useFormik({
  44. initialValues: {
  45. username: '',
  46. password: '',
  47. },
  48. validationSchema: loginSchema,
  49. onSubmit: submitHandler,
  50. validateOnBlur: true,
  51. enableReinitialize: true,
  52. });
  53. return (
  54. <Container component="main" maxWidth="md">
  55. <Box
  56. sx={{
  57. marginTop: 32,
  58. display: 'flex',
  59. flexDirection: 'column',
  60. alignItems: 'center',
  61. }}
  62. >
  63. <Typography component="h1" variant="h5">
  64. {t('login:Title')}
  65. </Typography>
  66. {error.hasError && <ErrorMessageComponent error={error.errorMessage} />}
  67. <Box
  68. component="form"
  69. onSubmit={formik.handleSubmit}
  70. sx={{ position: 'relative', mt: 1, p: 1 }}
  71. >
  72. <TextField
  73. name="username"
  74. label={t('forms:Username')}
  75. margin="normal"
  76. value={formik.values.username}
  77. onChange={formik.handleChange}
  78. error={formik.touched.username && Boolean(formik.errors.username)}
  79. helperText={formik.touched.username && formik.errors.username}
  80. autoFocus
  81. fullWidth
  82. />
  83. <TextField
  84. name="password"
  85. label={t('forms:Password')}
  86. margin="normal"
  87. type={showPassword ? 'text' : 'password'}
  88. value={formik.values.password}
  89. onChange={formik.handleChange}
  90. error={formik.touched.password && Boolean(formik.errors.password)}
  91. helperText={formik.touched.password && formik.errors.password}
  92. fullWidth
  93. InputProps={{
  94. endAdornment: (
  95. <InputAdornment position="end">
  96. <IconButton
  97. onClick={handleClickShowPassword}
  98. onMouseDown={handleMouseDownPassword}
  99. ></IconButton>
  100. </InputAdornment>
  101. ),
  102. }}
  103. />
  104. <Button
  105. type="submit"
  106. variant="contained"
  107. sx={{ mt: 3, mb: 2 }}
  108. fullWidth
  109. >
  110. {t('login:LoginBtn')}
  111. </Button>
  112. <Grid container>
  113. <Grid
  114. item
  115. xs={12}
  116. md={6}
  117. sx={{ textAlign: { xs: 'center', md: 'left' }, mt: 1 }}
  118. >
  119. <Link href={FORGOT_PASSWORD_PAGE}>
  120. <Typography sx={{ cursor: 'pointer' }}>
  121. {t('login:ForgotPassword')}
  122. </Typography>
  123. </Link>
  124. </Grid>
  125. <Grid
  126. item
  127. xs={12}
  128. md={6}
  129. sx={{
  130. textAlign: {
  131. xs: 'center',
  132. md: 'right',
  133. },
  134. mt: 1,
  135. }}
  136. >
  137. <Link href={REGISTER_PAGE}>
  138. <Typography sx={{ cursor: 'pointer' }}>
  139. {t('login:NoAccount')}
  140. </Typography>
  141. </Link>
  142. </Grid>
  143. </Grid>
  144. </Box>
  145. </Box>
  146. </Container>
  147. );
  148. };
  149. export default LoginForm;