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.

LoginPageMUI.js 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* eslint-disable */
  2. import React, { useEffect, useState } from "react";
  3. import PropTypes from "prop-types";
  4. import { useFormik } from "formik";
  5. import { useDispatch, useSelector } from "react-redux";
  6. import { NavLink } from "react-router-dom";
  7. import { useTranslation } from "react-i18next";
  8. import {
  9. clearLoginErrors,
  10. fetchUser,
  11. } from "../../store/actions/login/loginActions";
  12. import { selectLoginError } from "../../store/selectors/loginSelectors";
  13. import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages";
  14. import {
  15. Box,
  16. Button,
  17. Container,
  18. Grid,
  19. IconButton,
  20. InputAdornment,
  21. Link,
  22. TextField,
  23. Typography,
  24. } from "@mui/material";
  25. import { Visibility, VisibilityOff } from "@mui/icons-material";
  26. import Backdrop from "../../components/MUI/BackdropComponent";
  27. import ErrorMessage from "../../components/MUI/ErrorMessageComponent";
  28. import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
  29. import {
  30. LOGIN_USER_SCOPE,
  31. } from "../../store/actions/login/loginActionConstants";
  32. import loginValidation from "../../validations/loginValidation";
  33. import loginInitialValues from "../../initialValues/loginInitialValues";
  34. const LoginPage = ({ history }) => {
  35. const dispatch = useDispatch();
  36. const { t } = useTranslation();
  37. const error = useSelector(selectLoginError);
  38. const [showPassword, setShowPassword] = useState(false);
  39. const handleClickShowPassword = () => setShowPassword(!showPassword);
  40. const handleMouseDownPassword = () => setShowPassword(!showPassword);
  41. // Clear login errors when user firstly enters the page
  42. useEffect(() => {
  43. dispatch(clearLoginErrors());
  44. }, []);
  45. const isLoading = useSelector(selectIsLoadingByActionType(LOGIN_USER_SCOPE));
  46. const handleApiResponseSuccess = () => {
  47. history.push({
  48. pathname: HOME_PAGE,
  49. state: {
  50. from: history.location.pathname,
  51. },
  52. });
  53. };
  54. const handleSubmit = (values) => {
  55. const { email, password} = values;
  56. dispatch(clearLoginErrors());
  57. dispatch(
  58. fetchUser({
  59. identifier: email,
  60. password,
  61. handleApiResponseSuccess,
  62. })
  63. );
  64. };
  65. const formik = useFormik({
  66. initialValues: loginInitialValues,
  67. validationSchema: loginValidation,
  68. onSubmit: handleSubmit,
  69. validateOnBlur: true,
  70. enableReinitialize: true,
  71. });
  72. return (
  73. <Container component="main" maxWidth="md">
  74. <Box
  75. sx={{
  76. marginTop: 32,
  77. display: "flex",
  78. flexDirection: "column",
  79. alignItems: "center",
  80. }}
  81. >
  82. <Typography component="h1" variant="h5">
  83. {t("login.logInTitle")}
  84. </Typography>
  85. {error && <ErrorMessage error={error} />}
  86. <Box
  87. component="form"
  88. onSubmit={formik.handleSubmit}
  89. sx={{ position: "relative", mt: 1, p: 1 }}
  90. >
  91. <Backdrop position="absolute" isLoading={isLoading} />
  92. <TextField
  93. name="email"
  94. label={t("common.labelEmail")}
  95. margin="normal"
  96. value={formik.values.email}
  97. onChange={formik.handleChange}
  98. error={formik.touched.email && Boolean(formik.errors.email)}
  99. helperText={formik.touched.email && formik.errors.email}
  100. autoFocus
  101. fullWidth
  102. />
  103. <TextField
  104. name="password"
  105. label={t("common.labelPassword")}
  106. margin="normal"
  107. type={showPassword ? "text" : "password"}
  108. value={formik.values.password}
  109. onChange={formik.handleChange}
  110. error={formik.touched.password && Boolean(formik.errors.password)}
  111. helperText={formik.touched.password && formik.errors.password}
  112. fullWidth
  113. InputProps={{
  114. endAdornment: (
  115. <InputAdornment position="end">
  116. <IconButton
  117. onClick={handleClickShowPassword}
  118. onMouseDown={handleMouseDownPassword}
  119. >
  120. {showPassword ? <Visibility /> : <VisibilityOff />}
  121. </IconButton>
  122. </InputAdornment>
  123. ),
  124. }}
  125. />
  126. <Button
  127. type="submit"
  128. variant="contained"
  129. sx={{ mt: 3, mb: 2 }}
  130. fullWidth
  131. >
  132. {t("login.logIn")}
  133. </Button>
  134. <Grid container>
  135. <Grid
  136. item
  137. xs={12}
  138. md={6}
  139. sx={{ textAlign: { xs: "center", md: "left" } }}
  140. >
  141. <Link
  142. to={FORGOT_PASSWORD_PAGE}
  143. component={NavLink}
  144. variant="body2"
  145. underline="hover"
  146. >
  147. {t("login.forgotYourPassword")}
  148. </Link>
  149. </Grid>
  150. <Grid
  151. item
  152. xs={12}
  153. md={6}
  154. sx={{ textAlign: { xs: "center", md: "right" } }}
  155. >
  156. <Link
  157. to="#"
  158. component={NavLink}
  159. variant="body2"
  160. underline="hover"
  161. >
  162. {t("login.dontHaveAccount")}
  163. </Link>
  164. </Grid>
  165. </Grid>
  166. </Box>
  167. </Box>
  168. </Container>
  169. );
  170. };
  171. LoginPage.propTypes = {
  172. history: PropTypes.shape({
  173. replace: PropTypes.func,
  174. push: PropTypes.func,
  175. location: PropTypes.shape({
  176. pathname: PropTypes.string,
  177. }),
  178. }),
  179. };
  180. export default LoginPage;