LoginForm.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { actionLogin } from "../../../actions/actionLogin";
  2. import { useState, useEffect, useContext } from "react";
  3. import { connect } from "react-redux";
  4. import { MdVisibility, MdVisibilityOff } from "react-icons/md";
  5. import { Box, Button, IconButton, TextField, Stack } from "@mui/material";
  6. import { useFormik } from "formik";
  7. import * as Yup from "yup";
  8. import { UIContext } from "../../UIContext";
  9. const signInSchema = Yup.object().shape({
  10. username: Yup.string().min(3, "Too Short!").max(15, "Too Long!").required("Required"),
  11. password: Yup.string().min(3, "Too Short!").max(15, "Too Long!").required("Required"),
  12. });
  13. export const LoginForm = ({
  14. onLogin,
  15. onRegisterButtonClick,
  16. promiseStatus,
  17. serverErrors,
  18. inputVariant = "standard",
  19. buttonVariant = "text",
  20. } = {}) => {
  21. const [showPassword, setShowPassword] = useState(false);
  22. const { setAlert } = useContext(UIContext);
  23. const [promiseTimeOut, setPromiseTimeOut] = useState(null);
  24. const formik = useFormik({
  25. initialValues: {
  26. username: "",
  27. password: "",
  28. repeatPassword: "",
  29. },
  30. validationSchema: signInSchema,
  31. validateOnChange: true,
  32. onSubmit: () => {
  33. onLogin(formik.values.username, formik.values.password);
  34. setPromiseTimeOut(setTimeout(() => formik.setSubmitting(false), 3000));
  35. },
  36. });
  37. useEffect(() => {
  38. return () => {
  39. promiseTimeOut && clearTimeout(promiseTimeOut);
  40. setPromiseTimeOut(null);
  41. };
  42. }, []);
  43. useEffect(() => {
  44. if (promiseStatus === "FULFILLED") {
  45. formik.setSubmitting(false);
  46. promiseTimeOut && clearTimeout(promiseTimeOut);
  47. setPromiseTimeOut(null);
  48. setAlert({
  49. show: true,
  50. severity: "success",
  51. message: "Готово",
  52. });
  53. }
  54. if (promiseStatus === "REJECTED") {
  55. const errorMessage = (serverErrors || []).reduce((prev, curr) => prev + "\n" + curr.message, "");
  56. formik.setSubmitting(false);
  57. promiseTimeOut && clearTimeout(promiseTimeOut);
  58. setPromiseTimeOut(null);
  59. setAlert({
  60. show: true,
  61. severity: "error",
  62. message: errorMessage,
  63. });
  64. }
  65. }, [promiseStatus]);
  66. return (
  67. <Box
  68. className="LoginForm"
  69. display="flex"
  70. flexDirection="column"
  71. alignItems="center"
  72. component="form"
  73. onSubmit={formik.handleSubmit}
  74. >
  75. <TextField
  76. id="username"
  77. name="username"
  78. variant={inputVariant}
  79. label="Username"
  80. error={formik.touched.username && Boolean(formik.errors.username)}
  81. value={formik.values.username}
  82. onBlur={formik.handleBlur}
  83. onChange={formik.handleChange}
  84. helperText={formik.touched.username && formik.errors.username}
  85. fullWidth
  86. sx={{ mt: 2 }}
  87. />
  88. <TextField
  89. id="password"
  90. name="password"
  91. variant={inputVariant}
  92. label="Password"
  93. type={showPassword ? "text" : "password"}
  94. error={formik.touched.password && Boolean(formik.errors.password)}
  95. value={formik.values.password}
  96. onBlur={formik.handleBlur}
  97. onChange={formik.handleChange}
  98. helperText={formik.touched.password && formik.errors.password}
  99. InputProps={{
  100. endAdornment: (
  101. <IconButton onClick={() => setShowPassword((prev) => !prev)} edge="end">
  102. {showPassword ? <MdVisibilityOff /> : <MdVisibility />}
  103. </IconButton>
  104. ),
  105. }}
  106. fullWidth
  107. sx={{ mt: 2 }}
  108. />
  109. <Stack direction="row" justifyContent="flex-end" sx={{ width: "100%" }}>
  110. <Button
  111. variant={buttonVariant}
  112. color="primary"
  113. type="submit"
  114. disabled={formik.isSubmitting || !formik.isValid}
  115. sx={{ mt: 2, mr: 1 }}
  116. >
  117. Войти
  118. </Button>
  119. {onRegisterButtonClick ? (
  120. <Button variant={buttonVariant} onClick={onRegisterButtonClick} sx={{ mt: 2 }}>
  121. Регистрация
  122. </Button>
  123. ) : (
  124. ""
  125. )}
  126. </Stack>
  127. </Box>
  128. );
  129. };
  130. export const CLoginForm = connect(
  131. (state) => ({ promiseStatus: state.promise?.login?.status || null, serverErrors: state.promise?.login?.error || [] }),
  132. { onLogin: (login, password) => actionLogin(login, password) }
  133. )(LoginForm);