LoginForm.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. let errorMessage = "";
  56. try {
  57. errorMessage = JSON.parse(serverErrors.message)[0].message;
  58. } catch {
  59. errorMessage = (serverErrors ? [].concat(serverErrors) : []).reduce((prev, curr) => prev + "\n" + curr.message, "");
  60. }
  61. formik.setSubmitting(false);
  62. promiseTimeOut && clearTimeout(promiseTimeOut);
  63. setPromiseTimeOut(null);
  64. setAlert({
  65. show: true,
  66. severity: "error",
  67. message: errorMessage,
  68. });
  69. }
  70. }, [promiseStatus]);
  71. return (
  72. <Box
  73. className="LoginForm"
  74. display="flex"
  75. flexDirection="column"
  76. alignItems="center"
  77. component="form"
  78. onSubmit={formik.handleSubmit}
  79. >
  80. <TextField
  81. id="username"
  82. name="username"
  83. variant={inputVariant}
  84. label="Username"
  85. error={formik.touched.username && Boolean(formik.errors.username)}
  86. value={formik.values.username}
  87. onBlur={formik.handleBlur}
  88. onChange={formik.handleChange}
  89. helperText={formik.touched.username && formik.errors.username}
  90. fullWidth
  91. sx={{ mt: 2 }}
  92. />
  93. <TextField
  94. id="password"
  95. name="password"
  96. variant={inputVariant}
  97. label="Password"
  98. type={showPassword ? "text" : "password"}
  99. error={formik.touched.password && Boolean(formik.errors.password)}
  100. value={formik.values.password}
  101. onBlur={formik.handleBlur}
  102. onChange={formik.handleChange}
  103. helperText={formik.touched.password && formik.errors.password}
  104. InputProps={{
  105. endAdornment: (
  106. <IconButton onClick={() => setShowPassword((prev) => !prev)} edge="end">
  107. {showPassword ? <MdVisibilityOff /> : <MdVisibility />}
  108. </IconButton>
  109. ),
  110. }}
  111. fullWidth
  112. sx={{ mt: 2 }}
  113. />
  114. <Stack direction="row" justifyContent="flex-end" sx={{ width: "100%" }}>
  115. <Button
  116. variant={buttonVariant}
  117. color="primary"
  118. type="submit"
  119. disabled={formik.isSubmitting || !formik.isValid}
  120. sx={{ mt: 2, mr: 1 }}
  121. >
  122. Войти
  123. </Button>
  124. {onRegisterButtonClick ? (
  125. <Button variant={buttonVariant} onClick={onRegisterButtonClick} sx={{ mt: 2 }}>
  126. Регистрация
  127. </Button>
  128. ) : (
  129. ""
  130. )}
  131. </Stack>
  132. </Box>
  133. );
  134. };
  135. export const CLoginForm = connect(
  136. (state) => ({ promiseStatus: state.promise?.login?.status || null, serverErrors: state.promise?.login?.error || [] }),
  137. { onLogin: (login, password) => actionLogin(login, password) }
  138. )(LoginForm);