index.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. import React from 'react';
  2. import { Typography, Button } from '@material-ui/core';
  3. import TextField from '@material-ui/core/TextField';
  4. import { makeStyles } from '@material-ui/core/styles';
  5. import './message.scss';
  6. import { useState, useEffect } from "react";
  7. import Avatar from '@material-ui/core/Avatar';
  8. import { useDispatch, useSelector, connect } from "react-redux";
  9. import Card from '@material-ui/core/Card';
  10. import CardActionArea from '@material-ui/core/CardActionArea';
  11. import { defaultAvatar, origUrl } from '../../App.js';
  12. import ImageList from '@material-ui/core/ImageList';
  13. import MenuOpenIcon from '@material-ui/icons/MenuOpen';
  14. import HighlightOffIcon from '@material-ui/icons/HighlightOff';
  15. import { actionMyUserMessage, actionForMeMessage, actionAdMessage } from '../../actions';
  16. const useStyles = makeStyles((theme) => ({
  17. messageList: {
  18. width: "50%",
  19. maxWidth: "70%",
  20. backgroundColor: '#ccd7e3',
  21. display: 'flex',
  22. flexDirection: 'column-reverse',
  23. },
  24. messageListClose: {
  25. width: "90%",
  26. backgroundColor: '#ccd7e3',
  27. display: 'flex',
  28. flexDirection: 'column-reverse',
  29. },
  30. userList: {
  31. width: "30%",
  32. marginRight: "5px",
  33. minWidth: "max-content",
  34. backgroundColor: '#ccd7e3'
  35. },
  36. userListButton: {
  37. minWidth: "max-content",
  38. backgroundColor: '#ccd7e3',
  39. height: '498px',
  40. cursor: 'pointer'
  41. },
  42. MessageInput: {
  43. margin: '10px'
  44. },
  45. user: {
  46. display: 'flex',
  47. height: '60px',
  48. backgroundColor: '#88a0b9',
  49. margin: '10px',
  50. alignItems: 'center',
  51. padding: '5px'
  52. },
  53. avatar: {
  54. marginRight: '5px'
  55. },
  56. messageCard: {
  57. maxWidth: '80%',
  58. margin: '10px 10px 0px 10px',
  59. width: 'max-content',
  60. padding: '4px',
  61. height: 'max-content'
  62. },
  63. myUserColor: {
  64. backgroundColor: "#848bd8",
  65. maxWidth: '80%',
  66. margin: '10px 10px 0px 10px',
  67. marginRight: '-6px',
  68. marginLeft: '-5px',
  69. width: 'max-content',
  70. padding: '4px',
  71. },
  72. imageList: {
  73. width: 'auto',
  74. height: '402px',
  75. display: 'block',
  76. overflowY: 'scroll'
  77. },
  78. imageListUsers: {
  79. width: 'auto',
  80. height: '502px',
  81. display: 'block',
  82. overflowY: 'scroll'
  83. },
  84. userColor: {
  85. backgroundColor: "#50905f",
  86. maxWidth: '80%',
  87. maxHeight: '21px',
  88. margin: '10px 10px 0px 10px',
  89. marginRight: '-6px',
  90. width: 'max-content',
  91. padding: '4px',
  92. },
  93. UserDiv: {
  94. display: 'flex',
  95. },
  96. myUserDiv: {
  97. display: 'flex',
  98. flexDirection: 'row-reverse',
  99. marginRight: '15px',
  100. },
  101. time: {
  102. float: "right",
  103. fontSize: "80%",
  104. marginLeft: "12px",
  105. }
  106. }));
  107. function timeConverter(UNIX_timestamp) {
  108. const time = new Date(UNIX_timestamp);
  109. const months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
  110. const month = months[time.getMonth()];
  111. const date = time.getDate();
  112. const hour = time.getHours();
  113. const min = time.getMinutes();
  114. const newTime = date + '.' + month + ' ' + hour + ':' + min;
  115. return newTime;
  116. }
  117. function MyMessage({ user, message, time }) {
  118. const login = useSelector(state => state.auth?.payload?.sub?.login)
  119. const classes = useStyles();
  120. return (<>
  121. <div className={login === user ? classes.myUserDiv : classes.UserDiv}>
  122. <Card className={login === user ? classes.myUserColor : classes.userColor}>{user} </Card>
  123. <Card className={classes.messageCard}>{message} </Card>
  124. </div>
  125. <div className={login === user ? classes.myUserDiv : classes.UserDiv}>
  126. <Typography className={classes.time} gutterBottom >
  127. {timeConverter(+time)}
  128. </Typography></div></>
  129. )
  130. }
  131. const Users = ({ myOnclick, user }) => {
  132. const classes = useStyles();
  133. return (
  134. <CardActionArea onClick={() => myOnclick(user._id)}>
  135. <Card className={classes.user}>
  136. <Avatar className={classes.avatar} src={user.avatar ? origUrl + user.avatar.url : defaultAvatar} alt="Remy Sharp" />
  137. <p >{user.login} </p>
  138. </Card>
  139. </CardActionArea>
  140. )
  141. }
  142. const Spoiler = ({ open, children }) => {
  143. return <>
  144. <div>{open && children}</div>
  145. </>
  146. }
  147. const Message = ({ loadData, dataMyUser, myMessage = [], forMeMessage = [], forMeStatus, myMessageStatus }) => {
  148. const classes = useStyles();
  149. const dispatch = useDispatch();
  150. const id = useSelector(state => state.auth?.payload?.sub?.id)
  151. const [time, setTime] = useState(true);
  152. const [users, setUsers] = useState([]);
  153. const [send, setSend] = useState(false);
  154. const [message, setMessage] = useState('');
  155. const [iduser, setIduser] = useState("");
  156. const [messageArr, setMessageArr] = useState([]);
  157. const [allmessage, setAllMessage] = useState([]);
  158. useEffect(() => {
  159. if (forMeStatus === 'FULFILLED' && myMessageStatus === 'FULFILLED') {
  160. if (forMeMessage.length > 0 || myMessage.length > 0) {
  161. let allmessages = []
  162. if (forMeMessage.length > 0) {
  163. allmessages = [...forMeMessage]
  164. }
  165. if (myMessage.length > 0) {
  166. allmessages = [...myMessage]
  167. }
  168. if (forMeMessage.length > 0 && myMessage.length > 0) {
  169. allmessages = [...forMeMessage, ...myMessage]
  170. }
  171. if (allmessages.length > 0) {
  172. let usersList = allmessages.map((el) => {
  173. if (el.to) {
  174. return { login: el.to.login, _id: el.to._id, avatar: el.to.avatar }
  175. }
  176. return { login: el.owner.login, _id: el.owner._id, avatar: el.owner.avatar }
  177. })
  178. usersList = usersList.reduce((a, b) => {
  179. if (!a.find(v => v._id == b._id)) {
  180. a.push(b);
  181. }
  182. return a;
  183. }, []);
  184. setUsers(usersList)
  185. }
  186. }
  187. }
  188. }, [forMeMessage, myMessage])
  189. useEffect(() => {
  190. loadData(id)
  191. }, [send])
  192. useEffect(() => {
  193. const element = document.getElementById('list');
  194. element.scrollTop = element.scrollHeight;
  195. }, [messageArr])
  196. const onclickSend = () => {
  197. if (message) {
  198. dispatch(actionAdMessage({ text: message, to: { _id: iduser } }))
  199. setSend(!send)
  200. setMessage('')
  201. }
  202. }
  203. const enterHandler = (event) => {
  204. if (event.key === 'Enter') {
  205. if (message) {
  206. dispatch(actionAdMessage({ text: message, to: { _id: iduser } }))
  207. setSend(!send)
  208. setMessage('')
  209. }
  210. }
  211. }
  212. const upDate = () => {
  213. let usersMessage = []
  214. forMeMessage.map((el) => {
  215. if (el.owner._id === iduser) {
  216. usersMessage.push(el)
  217. }
  218. })
  219. myMessage.map((el) => {
  220. if (el.to._id === iduser) {
  221. usersMessage.push(el)
  222. }
  223. })
  224. const sort = usersMessage.sort((a, b) => a.createdAt - b.createdAt)
  225. setMessageArr(sort)
  226. setAllMessage([...forMeMessage, ...myMessage])
  227. }
  228. useEffect(() => {
  229. setTimeout(() => {
  230. dataMyUser(id)
  231. setTime(!time);
  232. }, 3000)
  233. }, [time])
  234. const onclickUser = (id) => {
  235. setIduser(id)
  236. let usersMessage = []
  237. forMeMessage.map((el) => {
  238. if (el.owner._id === id) {
  239. usersMessage.push(el)
  240. }
  241. })
  242. myMessage.map((el) => {
  243. if (el.to._id === id) {
  244. usersMessage.push(el)
  245. }
  246. })
  247. const sort = usersMessage.sort((a, b) => a.createdAt - b.createdAt)
  248. setMessageArr(sort)
  249. }
  250. if (allmessage.length < forMeMessage.length + myMessage.length) {
  251. upDate()
  252. }
  253. const [open, setOpen] = useState(true);
  254. const onclickOpen = () => {
  255. setOpen(!open)
  256. }
  257. return (
  258. <main className='mainMessage'>
  259. <Card onClick={onclickOpen} className={classes.userListButton} >{open ? <HighlightOffIcon /> : <MenuOpenIcon />}</Card>
  260. <Spoiler open={open}>
  261. <Card className={classes.userList}>
  262. <ImageList rowHeight={180} className={classes.imageListUsers}>
  263. {users.map((el) => <Users myOnclick={onclickUser} user={el} />)}
  264. </ImageList>
  265. </Card>
  266. </Spoiler>
  267. <Card className={open ? classes.messageList : classes.messageListClose}>
  268. <div className='divButtonText'>
  269. <Button onClick={onclickSend} size="small" color="primary">SEND</Button>
  270. <TextField
  271. onKeyPress={enterHandler}
  272. value={message}
  273. onChange={(e) => setMessage(e.target.value)}
  274. className={classes.MessageInput}
  275. id="standard-basic"
  276. label="Message" />
  277. <ImageList id='list' rowHeight={180} className={classes.imageList}>
  278. {messageArr.map((el) => <MyMessage user={el.owner.login} message={el.text} time={el.createdAt} />)}
  279. </ImageList>
  280. </div>
  281. </Card>
  282. </main>
  283. );
  284. }
  285. const Messages = connect(state => ({
  286. myMessage: state.promise?.allMeMessage?.payload,
  287. forMeMessage: state.promise?.allForMeMessage?.payload?.incomings || [],
  288. forMeStatus: state.promise?.allForMeMessage?.status || [],
  289. myMessageStatus: state.promise?.allMeMessage?.status || []
  290. }), {
  291. loadData: actionMyUserMessage,
  292. dataMyUser: actionForMeMessage
  293. })(Message)
  294. export default Messages