index.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import { useState, useEffect,useMemo } from 'react';
  2. import { useDispatch, useSelector } from 'react-redux';
  3. import Tab from '@mui/material/Tab';
  4. import Tabs from '@mui/material/Tabs';
  5. import Box from '@mui/material/Box';
  6. import { makeStyles } from '@material-ui/core'
  7. import { styled } from '@mui/material/styles';
  8. import ChatListRecent from './ChatListRecent'
  9. import FilesList from './FilesList';
  10. import MediaList from './MediaList';
  11. import TextList from './TextList';
  12. import AudioList from './AudioList'
  13. import VideoList from './VideoList';
  14. import { asyncGetAllMessages } from '../../../../redux/allMessages/operations';
  15. import { asyncGetChats } from '../../../../redux/chats/operations';
  16. import { getStateMemo } from '../../../../redux/chats/selector';
  17. import { getAllMessagesMemo } from '../../../../redux/allMessages/selector';
  18. import { getState } from '../../../../redux/control/selector';
  19. import { sortByRecent,filterBy,filteredMessages,handleSort,timeStampFilter,refreshAppTime } from '../../../../helpers';
  20. import { asyncStartChatById } from '../../../../redux/chat/operations';
  21. import { getPinnedMessagesMemo } from '../../../../redux/pinnedMessages/selector';
  22. import { actionLeftIsOpen,actionRightIsOpen,actionOpenPinned } from '../../../../redux/control/action';
  23. import { TMessage } from '../../../../typescript/redux/messages/types';
  24. const useStyles = makeStyles({
  25. container: {
  26. height: '5vh',
  27. display: "flex",
  28. alignContent: "end",
  29. alignItems: "end",
  30. width:'100%',
  31. borderBottom: 'solid 2px #dddddd',
  32. },
  33. })
  34. interface StyledTabsProps {
  35. children?: React.ReactNode;
  36. value: number;
  37. onChange: (event: React.SyntheticEvent, newValue: number) => void;
  38. }
  39. const StyledTabs = styled((props: StyledTabsProps) => (
  40. <Tabs
  41. {...props}
  42. TabIndicatorProps={{ children: <span className="MuiTabs-indicatorSpan" /> }}
  43. />
  44. ))({
  45. '& .MuiTabs-flexContainer': {
  46. display: "flex",
  47. width: '100%',
  48. padding:'0px 10px',
  49. justifyContent: "space-between"
  50. },
  51. '& .MuiTabs-indicator': {
  52. height: 0,
  53. backgroundColor: 'transparent',
  54. borderBottom: '3px solid #1976d2',
  55. borderLeft: '3px solid transparent',
  56. borderRight: '3px solid transparent',
  57. },
  58. });
  59. const StyledTab = styled((props:{label: string}) => <Tab disableRipple {...props} />)({
  60. fontSize: '1rem',
  61. fontWeight: 550,
  62. textTransform: 'none',
  63. minWidth: 'auto',
  64. },
  65. );
  66. interface ISearchLists {
  67. value: string,
  68. setValue: React.Dispatch<string>
  69. sort: boolean,
  70. date: any,
  71. setDate: React.Dispatch<any>,
  72. setDisabled: React.Dispatch<boolean>,
  73. chatDivRef: any | null
  74. }
  75. const SearchLists = ({ value,setValue,sort,date,setDate,setDisabled,chatDivRef}: ISearchLists) => {
  76. const classes = useStyles()
  77. const dispatch = useDispatch()
  78. const { chats, total } = useSelector(getStateMemo)
  79. const messagesMemo = useSelector(getAllMessagesMemo)
  80. const pinnedMessagesMemo = useSelector(getPinnedMessagesMemo)
  81. const { leftIsOpen,rightIsOpen,openPinned } = useSelector(getState)
  82. const [isActive, setIsActive] = useState<number>(0)
  83. const handleIsActive = (_e:any,newValue: number): void => {
  84. setIsActive(newValue)
  85. value && setValue('')
  86. date&&setDate('')
  87. }
  88. const handleListItemClick = (companionId: string) => {
  89. rightIsOpen && dispatch(actionRightIsOpen(''))
  90. openPinned&&dispatch(actionOpenPinned(false))
  91. dispatch(asyncStartChatById(companionId))
  92. }
  93. const scrollTo = (nodeRef: any,id:string) => {
  94. const childNodes = nodeRef.current.childNodes[0].childNodes
  95. let toScrollNode = [...childNodes].find((el: any) => el.id === id)
  96. if (toScrollNode) {
  97. toScrollNode = [...toScrollNode.childNodes].slice(-1)[0]
  98. toScrollNode.style.backgroundColor = 'rgba(70, 70, 70, 0.4)'
  99. toScrollNode.style.boxShadow = '0px 0px 6px 0px #ffffff'
  100. toScrollNode.scrollIntoView({ behavior: 'smooth' })
  101. setTimeout(() => {
  102. toScrollNode.style.backgroundColor = 'unset'
  103. toScrollNode.style.boxShadow = 'unset'
  104. }, 2000)
  105. }
  106. }
  107. const handleScrollToTheMessage = (_id: string, companionId: string) => {
  108. if (openPinned && !pinnedMessagesMemo.some((el) => (el._id === _id && el.companionId === companionId))) {
  109. dispatch(actionOpenPinned(false))
  110. }
  111. if (chatDivRef.current && chatDivRef.current.id === companionId) {
  112. scrollTo(chatDivRef,_id)
  113. } else if (chatDivRef.current && chatDivRef.current.id !== companionId) {
  114. rightIsOpen&&dispatch(actionRightIsOpen(''))
  115. dispatch(asyncStartChatById(companionId))
  116. setTimeout(() => {
  117. if(chatDivRef.current) scrollTo(chatDivRef,_id)
  118. }, 3000)
  119. } else if (!chatDivRef.current) {
  120. rightIsOpen&&dispatch(actionRightIsOpen(''))
  121. dispatch(asyncStartChatById(companionId))
  122. setTimeout(() => {
  123. if(chatDivRef.current) scrollTo(chatDivRef,_id)
  124. }, 3000)
  125. }
  126. }
  127. useEffect(() => {
  128. setDate('')
  129. }, [setDate])
  130. useEffect(() => {
  131. if (isActive === 0) {
  132. dispatch(actionLeftIsOpen('searchChats'))
  133. } else {
  134. dispatch(actionLeftIsOpen('searchAllMessages'))
  135. }
  136. }, [isActive,dispatch])
  137. useEffect(() => {
  138. if (isActive === 0) setDisabled(total === '0'?true:false)
  139. }, [isActive,total,setDisabled])
  140. useEffect(() => {
  141. const handleReset = () => {
  142. if (leftIsOpen === 'searchChats') {
  143. dispatch(asyncGetChats())
  144. } else if (leftIsOpen === 'searchAllMessages') {
  145. dispatch(asyncGetAllMessages())
  146. }
  147. }
  148. handleReset()
  149. const idInterval = setInterval(handleReset, refreshAppTime);
  150. return () => clearInterval(idInterval);
  151. }, [leftIsOpen,dispatch]);
  152. const filteredAndSortedChats = useMemo(() => {
  153. return sortByRecent(chats,sort).filter((el) => {
  154. const credentials = el.name + ' ' + el.lastName
  155. if (!date) {
  156. return credentials.toLowerCase().includes(value.toLowerCase())
  157. } else if (credentials.toLowerCase().includes(value.toLowerCase())
  158. &&timeStampFilter(date) === timeStampFilter(el.lastMessageCreatedAt ?
  159. el.lastMessageCreatedAt : el.createdAt)) {
  160. return el
  161. } else return undefined
  162. })
  163. }, [chats, date, value, sort])
  164. const filteredAndSortedMessages = useMemo(() => {
  165. const filtered = messagesMemo.filter((el:TMessage) => filterBy[isActive === 0?0:isActive-1].includes(el.type))
  166. if(isActive > 0) setDisabled(filtered.length > 0?false:true)
  167. return filteredMessages(handleSort('createdAt', filtered, sort), date, value)
  168. }, [messagesMemo, date, isActive, sort, value,setDisabled])
  169. return (
  170. <>
  171. <Box className={classes.container}>
  172. <StyledTabs sx={{width:'100%'}} onChange={handleIsActive} value={isActive} aria-label="wrapped label tabs example">
  173. <StyledTab label='Chats' />
  174. <StyledTab label='Files' />
  175. <StyledTab label='Media' />
  176. <StyledTab label='Text' />
  177. <StyledTab label='Audio' />
  178. <StyledTab label='Video' />
  179. </StyledTabs>
  180. </Box>
  181. {isActive === 0 && <ChatListRecent value={value} date={date}
  182. filteredAndSortedChats={filteredAndSortedChats} handleListItemClick={handleListItemClick} />}
  183. {isActive === 1 && <FilesList filteredAndSortedMessages={filteredAndSortedMessages} value={value} date={date} handleScrollToTheMessage={handleScrollToTheMessage}/>}
  184. {isActive === 2 && <MediaList filteredAndSortedMessages={filteredAndSortedMessages} value={value} date={date} handleScrollToTheMessage={handleScrollToTheMessage}/>}
  185. {isActive === 3 && <TextList filteredAndSortedMessages={filteredAndSortedMessages} value={value} date={date} handleScrollToTheMessage={handleScrollToTheMessage}/>}
  186. {isActive === 4 && <AudioList filteredAndSortedMessages={filteredAndSortedMessages} value={value} date={date} handleScrollToTheMessage={handleScrollToTheMessage}/>}
  187. {isActive === 5 && <VideoList filteredAndSortedMessages={filteredAndSortedMessages} value={value} date={date} handleScrollToTheMessage={handleScrollToTheMessage}/>}
  188. </>
  189. )
  190. }
  191. export default SearchLists