index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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 { useFormik } from "formik";
  7. import * as Yup from "yup";
  8. import { UIContext } from "../../UIContext";
  9. import { MdVisibility, MdVisibilityOff } from "react-icons/md";
  10. import { ProfileImageEditor } from "../../common/ProfileImageEditor";
  11. const CProfileImageEditor = connect((state) => ({ avatar: state.promise?.aboutMe?.payload?.avatar || null }), {
  12. onFileDrop: (acceptedFiles) => actionUpdateAvatar(acceptedFiles[0]),
  13. })(ProfileImageEditor);
  14. const profileSchema = Yup.object().shape({
  15. name: Yup.string(),
  16. username: Yup.string().min(3, "Too Short!").max(15, "Too Long!").required("Required"),
  17. password: Yup.string().min(3, "Too Short!").max(15, "Too Long!"),
  18. nick: Yup.string(),
  19. });
  20. export const ProfileForm = ({ profile = {}, promiseStatus, onProfileSave, serverErrors = [] } = {}) => {
  21. const [editMod, setEditMod] = useState(false);
  22. const [showPassword, setShowPassword] = useState(false);
  23. const { setAlert } = useContext(UIContext);
  24. const [promiseTimeOut, setPromiseTimeOut] = useState(null);
  25. const formik = useFormik({
  26. initialValues: {
  27. username: "",
  28. password: "",
  29. name: "",
  30. nick: "",
  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. profile._id && formik.setFieldValue("_id", profile?._id || "");
  47. formik.setFieldValue("username", profile?.username || "");
  48. formik.setFieldValue("nick", profile?.nick || "");
  49. formik.setFieldValue("name", profile?.name || "");
  50. }, [profile]);
  51. useEffect(() => {
  52. if (promiseStatus === "FULFILLED") {
  53. formik.setSubmitting(false);
  54. promiseTimeOut && clearTimeout(promiseTimeOut);
  55. setPromiseTimeOut(null);
  56. setAlert({
  57. show: true,
  58. severity: "success",
  59. message: "Готово",
  60. });
  61. setEditMod(false);
  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={`Після зміни username потрібно перезайти в аккаунт!!! \n ${
  99. formik.touched.username ? formik.errors.username || "" : ""
  100. }`}
  101. />
  102. ) : (
  103. formik.values.username
  104. )}
  105. </TableCell>
  106. </TableRow>
  107. <TableRow>
  108. <TableCell>Nick</TableCell>
  109. <TableCell>
  110. {editMod ? (
  111. <TextField
  112. size="small"
  113. id="nick"
  114. name="nick"
  115. variant="standard"
  116. label="Nick"
  117. error={formik.touched.nick && Boolean(formik.errors.nick)}
  118. value={formik.values.nick}
  119. onBlur={formik.handleBlur}
  120. onChange={formik.handleChange}
  121. helperText={formik.touched.nick && formik.errors.nick}
  122. />
  123. ) : (
  124. formik.values.nick
  125. )}
  126. </TableCell>
  127. </TableRow>
  128. <TableRow>
  129. <TableCell>Name</TableCell>
  130. <TableCell>
  131. {editMod ? (
  132. <TextField
  133. size="small"
  134. id="name"
  135. name="name"
  136. variant="standard"
  137. label="Name"
  138. error={formik.touched.name && Boolean(formik.errors.name)}
  139. value={formik.values.name}
  140. onBlur={formik.handleBlur}
  141. onChange={formik.handleChange}
  142. helperText={formik.touched.name && formik.errors.name}
  143. />
  144. ) : (
  145. formik.values.name
  146. )}
  147. </TableCell>
  148. </TableRow>
  149. <TableRow>
  150. <TableCell>Password</TableCell>
  151. <TableCell>
  152. {editMod ? (
  153. <TextField
  154. size="small"
  155. id="password"
  156. name="password"
  157. variant="standard"
  158. label="Password"
  159. type={showPassword ? "text" : "password"}
  160. error={formik.touched.password && Boolean(formik.errors.password)}
  161. value={formik.values.password}
  162. onBlur={formik.handleBlur}
  163. onChange={formik.handleChange}
  164. helperText={formik.touched.password && formik.errors.password}
  165. InputProps={{
  166. endAdornment: (
  167. <IconButton onClick={() => setShowPassword((prev) => !prev)} edge="end">
  168. {showPassword ? <MdVisibilityOff /> : <MdVisibility />}
  169. </IconButton>
  170. ),
  171. }}
  172. />
  173. ) : (
  174. "****************"
  175. )}
  176. </TableCell>
  177. </TableRow>
  178. <TableRow>
  179. <TableCell></TableCell>
  180. <TableCell>
  181. {editMod ? (
  182. <Box display="flex" justifyContent="flex-end">
  183. <Button variant="text" color="error" onClick={() => setEditMod(false)}>
  184. Скасувати
  185. </Button>
  186. <Button
  187. variant="text"
  188. color="primary"
  189. type="submit"
  190. disabled={formik.isSubmitting || !formik.isValid}
  191. >
  192. Зберегти
  193. </Button>
  194. </Box>
  195. ) : (
  196. <Box display="flex" justifyContent="flex-end">
  197. <Button onClick={() => setEditMod(true)}>Редагувати</Button>
  198. </Box>
  199. )}
  200. </TableCell>
  201. </TableRow>
  202. </TableBody>
  203. </Table>
  204. </Grid>
  205. </Grid>
  206. </Box>
  207. );
  208. };
  209. export const CProfileForm = connect(
  210. (state) => ({
  211. profile: state.promise?.aboutMe?.payload || {},
  212. promiseStatus: state.promise.userUpsert?.status || null,
  213. serverErrors: state.promise?.userUpsert?.error || [],
  214. }),
  215. {
  216. onProfileSave: (profile = {}) => actionUserUpdate(profile),
  217. }
  218. )(ProfileForm);