index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import { Box, Button, Grid, IconButton, Paper, Table, TableBody, TableCell, TableRow, TextField } from "@mui/material";
  2. import { useContext, useEffect, useState } from "react";
  3. import { connect } from "react-redux";
  4. import { actionUpdateAvatar } from "../../../actions/actionUpdateAvatar";
  5. import { actionUserUpdate } from "../../../actions/actionUserUpdate";
  6. import { DropZone } from "../../common/DropZone";
  7. import { useFormik } from "formik";
  8. import * as Yup from "yup";
  9. import { UIContext } from "../../UIContext";
  10. import { MdVisibility, MdVisibilityOff } from "react-icons/md";
  11. import { ProfileImageEditor } from "../../common/ProfileImageEditor";
  12. const CProfileImageEditor = connect((state) => ({ avatar: state.promise?.aboutMe?.payload?.avatar || null }), {
  13. onFileDrop: (acceptedFiles) => actionUpdateAvatar(acceptedFiles[0]),
  14. })(ProfileImageEditor);
  15. const profileSchema = Yup.object().shape({
  16. name: Yup.string(),
  17. username: Yup.string().min(3, "Too Short!").max(15, "Too Long!").required("Required"),
  18. password: Yup.string().min(3, "Too Short!").max(15, "Too Long!"),
  19. nick: Yup.string(),
  20. });
  21. export const ProfileForm = ({ profile = {}, promiseStatus, onProfileSave, serverErrors = [] } = {}) => {
  22. const [editMod, setEditMod] = useState(false);
  23. const [showPassword, setShowPassword] = useState(false);
  24. const { setAlert } = useContext(UIContext);
  25. const [promiseTimeOut, setPromiseTimeOut] = useState(null);
  26. const formik = useFormik({
  27. initialValues: {
  28. username: "",
  29. password: "",
  30. repeatPassword: "",
  31. },
  32. validationSchema: profileSchema,
  33. validateOnChange: true,
  34. onSubmit: () => {
  35. onProfileSave(formik.values);
  36. setPromiseTimeOut(setTimeout(() => formik.setSubmitting(false), 3000));
  37. },
  38. });
  39. useEffect(() => {
  40. return () => {
  41. promiseTimeOut && clearTimeout(promiseTimeOut);
  42. setPromiseTimeOut(null);
  43. };
  44. }, []);
  45. useEffect(() => {
  46. formik.setValues(profile);
  47. return () => {
  48. promiseTimeOut && clearTimeout(promiseTimeOut);
  49. setPromiseTimeOut(null);
  50. };
  51. }, [profile]);
  52. useEffect(() => {
  53. if (promiseStatus === "FULFILLED") {
  54. formik.setSubmitting(false);
  55. promiseTimeOut && clearTimeout(promiseTimeOut);
  56. setPromiseTimeOut(null);
  57. setAlert({
  58. show: true,
  59. severity: "success",
  60. message: "Готово",
  61. });
  62. }
  63. if (promiseStatus === "REJECTED") {
  64. const errorMessage = (serverErrors ? [].concat(serverErrors) : []).reduce((prev, curr) => prev + "\n" + curr.message, "");
  65. formik.setSubmitting(false);
  66. promiseTimeOut && clearTimeout(promiseTimeOut);
  67. setPromiseTimeOut(null);
  68. setAlert({
  69. show: true,
  70. severity: "error",
  71. message: errorMessage,
  72. });
  73. }
  74. }, [promiseStatus]);
  75. return (
  76. <Box component="form" className="ProfileForm" onSubmit={formik.handleSubmit}>
  77. <Grid container spacing={3}>
  78. <Grid xs={4} item>
  79. <CProfileImageEditor />
  80. </Grid>
  81. <Grid xs={8} item>
  82. <Table>
  83. <TableBody>
  84. <TableRow>
  85. <TableCell>Username</TableCell>
  86. <TableCell>
  87. {editMod ? (
  88. <TextField
  89. size="small"
  90. id="username"
  91. name="username"
  92. variant="standard"
  93. label="Username"
  94. error={formik.touched.username && Boolean(formik.errors.username)}
  95. value={formik.values.username}
  96. onBlur={formik.handleBlur}
  97. onChange={formik.handleChange}
  98. helperText={formik.touched.username && formik.errors.username}
  99. />
  100. ) : (
  101. formik.values.username
  102. )}
  103. </TableCell>
  104. </TableRow>
  105. <TableRow>
  106. <TableCell>Nick</TableCell>
  107. <TableCell>
  108. {editMod ? (
  109. <TextField
  110. size="small"
  111. id="nick"
  112. name="nick"
  113. variant="standard"
  114. label="Nick"
  115. error={formik.touched.nick && Boolean(formik.errors.nick)}
  116. value={formik.values.nick}
  117. onBlur={formik.handleBlur}
  118. onChange={formik.handleChange}
  119. helperText={formik.touched.nick && formik.errors.nick}
  120. />
  121. ) : (
  122. formik.values.nick
  123. )}
  124. </TableCell>
  125. </TableRow>
  126. <TableRow>
  127. <TableCell>Name</TableCell>
  128. <TableCell>
  129. {editMod ? (
  130. <TextField
  131. size="small"
  132. id="name"
  133. name="name"
  134. variant="standard"
  135. label="Name"
  136. error={formik.touched.name && Boolean(formik.errors.name)}
  137. value={formik.values.name}
  138. onBlur={formik.handleBlur}
  139. onChange={formik.handleChange}
  140. helperText={formik.touched.name && formik.errors.name}
  141. />
  142. ) : (
  143. formik.values.name
  144. )}
  145. </TableCell>
  146. </TableRow>
  147. <TableRow>
  148. <TableCell>Password</TableCell>
  149. <TableCell>
  150. {editMod ? (
  151. <TextField
  152. size="small"
  153. id="password"
  154. name="password"
  155. variant="standard"
  156. label="Password"
  157. type={showPassword ? "text" : "password"}
  158. error={formik.touched.password && Boolean(formik.errors.password)}
  159. value={formik.values.password}
  160. onBlur={formik.handleBlur}
  161. onChange={formik.handleChange}
  162. helperText={formik.touched.password && formik.errors.password}
  163. InputProps={{
  164. endAdornment: (
  165. <IconButton onClick={() => setShowPassword((prev) => !prev)} edge="end">
  166. {showPassword ? <MdVisibilityOff /> : <MdVisibility />}
  167. </IconButton>
  168. ),
  169. }}
  170. />
  171. ) : (
  172. "****************"
  173. )}
  174. </TableCell>
  175. </TableRow>
  176. <TableRow>
  177. <TableCell></TableCell>
  178. <TableCell>
  179. {editMod ? (
  180. <Box display="flex" justifyContent="flex-end">
  181. <Button variant="text" color="error" onClick={() => setEditMod(false)}>
  182. Скасувати
  183. </Button>
  184. <Button
  185. variant="text"
  186. color="primary"
  187. type="submit"
  188. disabled={formik.isSubmitting || !formik.isValid}
  189. >
  190. Зберегти
  191. </Button>
  192. </Box>
  193. ) : (
  194. <Box display="flex" justifyContent="flex-end">
  195. <Button onClick={() => setEditMod(true)}>Редагувати</Button>
  196. </Box>
  197. )}
  198. </TableCell>
  199. </TableRow>
  200. </TableBody>
  201. </Table>
  202. </Grid>
  203. </Grid>
  204. </Box>
  205. );
  206. };
  207. export const CProfileForm = connect(
  208. (state) => ({
  209. profile: state.promise?.aboutMe?.payload,
  210. promiseStatus: state.promise.userUpsert?.status || null,
  211. serverErrors: state.promise?.userUpsert?.error || [],
  212. }),
  213. {
  214. onProfileSave: (profile = {}) => actionUserUpdate(profile),
  215. }
  216. )(ProfileForm);