Pārlūkot izejas kodu

finished with unpinBar

unknown 2 gadi atpakaļ
vecāks
revīzija
d58beedb31

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
.eslintcache


+ 11 - 0
src/api-data/index.ts

@@ -290,6 +290,16 @@ const pinMessageById = async <T>(id:string,pinned:boolean): Promise<T | undefine
   }
 };
 
+const unpinAllMessagesById = async <T>(pinnedMessages:string[]): Promise<T | undefined> => {
+  try {
+    const { data: { data } } = await axios.patch('/messages/unpin/all/',{pinnedMessages});
+    return data
+  } catch (e) {
+    forbidden(e)
+    return undefined
+  }
+};
+
 const sentMessageById = async <T>(id:string,message:string,caption:string): Promise<T | undefined> => {
   try {
     const { data: { data } } = await axios.post('/messages', { id, message,caption });
@@ -389,6 +399,7 @@ export {
   removeSelectedMessagesById,
   updateMessageById,
   pinMessageById,
+  unpinAllMessagesById,
   sentMessageById,
   sentImgMessageById,
   sentAudioMessageById,

+ 40 - 0
src/components/HomePage/CentralBar/ChatBar/UnpinBar/index.tsx

@@ -0,0 +1,40 @@
+import { makeStyles } from '@material-ui/core'
+import { TPinnedMessages } from '../../../../../typescript/redux/pinnedMessages/types' 
+
+const useStyles = makeStyles({
+  unpinBar: {   
+    backgroundColor: '#ffffff',
+    color:'#2b97fd',
+    display: 'flex',
+    justifyContent: 'center',
+    alignContent: 'center',
+    alignItems: 'center',
+    width: '100%',
+    height: '7vh',
+    position: 'fixed',
+    cursor:'pointer',
+    bottom: '0vh',
+    fontSize:18,
+    '&:hover': {
+      color: '#0084ff',
+    }
+  },    
+})
+
+interface IUnpinBar {
+  pinnedMessagesMemo: TPinnedMessages,
+  handleUnpinAll: () => void,
+}
+
+const UnpinBar = ({pinnedMessagesMemo,handleUnpinAll}:IUnpinBar) => {
+  const classes = useStyles()   
+
+  return (
+      <div onClick={handleUnpinAll}  className={classes.unpinBar}>
+        {`UNPIN ALL ${pinnedMessagesMemo.length} MESSAGES`}
+      </div>
+    )
+}
+
+export default UnpinBar
+

+ 20 - 11
src/components/HomePage/CentralBar/ChatBar/index.tsx

@@ -4,6 +4,7 @@ import { useSelector,useDispatch } from "react-redux";
 
 import ArrowBack from "./ArrowBack";
 import SendMessage from "./SendMessage";
+import UnpinBar from "./UnpinBar";
 import MessageLeftText from './Messages/MessageLeftText'
 import MessageLeftImage from './Messages/MessageLeftImage'
 import MessageLeftAudio from './Messages/MessageLeftAudio'
@@ -24,6 +25,7 @@ import { actionScrollChat } from '../../../../redux/control/action'
 import { asyncGetMessagesById } from '../../../../redux/messages/operations'
 import { asyncGetChatById } from "../../../../redux/chat/operations";
 import { seenChat } from "../../../../api-data";
+import { TPinnedMessages } from "../../../../typescript/redux/pinnedMessages/types";
 import { timeStampFilter,prodAwsS3,refreshAppTime } from "../../../../helpers";
 const debounce = require('lodash.debounce');
 
@@ -75,14 +77,17 @@ const useStyles = makeStyles({
 });
 
 interface IChatBar {
-  divRef: any | null,
+  chatDivRef: any | null,
   selectedArr: string[] | [],
   setSelectedArr: React.Dispatch<React.SetStateAction<string[] | []>>,
   isSomeSelected: boolean,
   setIsSomeSelected: React.Dispatch<React.SetStateAction<boolean>>,
+  openPinned: boolean,
+  pinnedMessagesMemo: TPinnedMessages,
+  handleUnpinAll: () => void
 }
 
-const ChatBar = ({divRef,selectedArr,setSelectedArr,isSomeSelected,setIsSomeSelected}:IChatBar) => {
+const ChatBar = ({chatDivRef,selectedArr,setSelectedArr,isSomeSelected,setIsSomeSelected,openPinned,pinnedMessagesMemo,handleUnpinAll}:IChatBar) => {
   const classes = useStyles();
   const dispatch = useDispatch()
   const messages = useSelector(getMessagesMemo)
@@ -100,11 +105,11 @@ const ChatBar = ({divRef,selectedArr,setSelectedArr,isSomeSelected,setIsSomeSele
      else setSelectedArr([...selectedArr,_id])
   }
   const handleScrollTo = useCallback(() => {
-     divRef.current&&divRef.current.scrollTo({
-     top: divRef.current.scrollHeight,
+     chatDivRef.current&&chatDivRef.current.scrollTo({
+     top: chatDivRef.current.scrollHeight,
      behavior: 'smooth'
      })
-  },[divRef])
+  },[chatDivRef])
 
   const handleScroll = useCallback(({ target:{scrollHeight,scrollTop,clientHeight}}: any) => {
     const different = scrollHeight - Math.floor(scrollTop)
@@ -138,22 +143,25 @@ const ChatBar = ({divRef,selectedArr,setSelectedArr,isSomeSelected,setIsSomeSele
 
   useEffect(() => {
     const handleReset = () => {
-      if (divRef.current) {
-         const { scrollHeight, clientHeight } = divRef.current
+      if (chatDivRef.current) {
+         const { scrollHeight, clientHeight } = chatDivRef.current
          if (total !== seen && scrollHeight === clientHeight) seenChat(companionId)
        }
     }
     const idInterval = setInterval(handleReset, refreshAppTime);
     return () => clearInterval(idInterval);
-  }, [total, seen, divRef,companionId]);
+  }, [total, seen, chatDivRef, companionId]);
+  
+  const renderArr = !openPinned?messages:pinnedMessagesMemo
+  
 
   return (
     <div className={classes.container} >
       <ArrowBack isArrow={isArrow} isNew={isNew} handleScrollTo={handleScrollTo}/>
-      <div id={companionId} ref={divRef} onScroll={debouncedHandleScroll}
+      <div id={companionId} ref={chatDivRef} onScroll={debouncedHandleScroll}
         className={messages.length > 0 ? classes.messagesScroll : classes.messagesEmpty}>
         <div className={classes.messagesBody}>
-        {messages.length > 0 ? messages.map(({ message, name, lastName, color,pinned,
+        {messages.length > 0 ? renderArr.map(({ message, name, lastName, color,pinned,
            createdAt,number, type,fullType,caption,emoji,emojiCompanion,_id }) => {
           let isTime
           if (!time) {
@@ -324,7 +332,8 @@ const ChatBar = ({divRef,selectedArr,setSelectedArr,isSomeSelected,setIsSomeSele
         }) : <AlertInfo name='You do not have messages yet!' />}
         </div>
       </div>  
-    <SendMessage isArrow={isArrow} />   
+      {!openPinned ? <SendMessage isArrow={isArrow} /> :
+      <UnpinBar pinnedMessagesMemo={pinnedMessagesMemo} handleUnpinAll={handleUnpinAll}/>}
     </div>
   );
 }

+ 19 - 20
src/components/HomePage/CentralBar/HeaderBar/PinnedBar/index.tsx

@@ -19,8 +19,8 @@ import { useSelector } from 'react-redux';
 import { useState,useEffect} from 'react';
 
 import { TMessages,TMessage } from '../../../../../typescript/redux/messages/types';
-import { getMessagesMemo } from '../../../../../redux/messages/selector';
-import { firstLetter,slicedWord,handleSort,prodAwsS3,copied,handleDownload } from '../../../../../helpers';
+import { getPinnedMessagesMemo } from '../../../../../redux/pinnedMessages/selector';
+import { firstLetter,slicedWord,prodAwsS3,copied,handleDownload } from '../../../../../helpers';
 import { pinMessageById } from '../../../../../api-data';
 
 const useStyles = makeStyles({
@@ -72,23 +72,27 @@ const useStyles = makeStyles({
   },
 })
 
-const PinnedBar = ({divRef}:{divRef: any | null}) => {
+interface IPinnedBar {
+  chatDivRef: any | null,
+  setOpenPinned: React.Dispatch<React.SetStateAction<boolean>>,
+}
+
+const PinnedBar = ({chatDivRef,setOpenPinned}:IPinnedBar) => {
   const classes = useStyles()
-  const messagesMemo = useSelector(getMessagesMemo)
-  const [pinnedArr, setPinnedArr] = useState<TMessages>([])
+  const pinnedMessagesMemo = useSelector(getPinnedMessagesMemo)
   const [openedPin, setOpenedPin] = useState<TMessage | null>(null)
   const [openedIndex, setOpenedIndex] = useState<number>(0)
   const [modal, setModal] = useState<boolean>(false)
   
   const handleActivePin = () => {
-    const childNodes = divRef.current.childNodes[0].childNodes
+    const childNodes = chatDivRef.current.childNodes[0].childNodes
     let toScrollNode: any
-    if (pinnedArr.length - 1 === openedIndex) {
+    if (pinnedMessagesMemo.length - 1 === openedIndex) {
       setOpenedIndex(0)
-      toScrollNode = [ ...childNodes ].find((el:any) => el.id === pinnedArr[0]._id)
+      toScrollNode = [ ...childNodes ].find((el:any) => el.id === pinnedMessagesMemo[0]._id)
     } else {
       setOpenedIndex(prevState => prevState + 1)
-      toScrollNode = [...childNodes].find((el: any) => el.id === pinnedArr[openedIndex + 1]._id)
+      toScrollNode = [...childNodes].find((el: any) => el.id === pinnedMessagesMemo[openedIndex + 1]._id)
     }
     if (toScrollNode) {
       toScrollNode = [...toScrollNode.childNodes].slice(-1)[0]
@@ -111,16 +115,11 @@ const PinnedBar = ({divRef}:{divRef: any | null}) => {
         setOpenedIndex(0)
       }
     }
-  } 
-  
-  useEffect(() => {
-    const messages = messagesMemo.filter((el) => el.pinned === true)
-    setPinnedArr(handleSort('updatedAt', messages, true))
-  }, [messagesMemo])
+  }
 
   useEffect(() => {
-    setOpenedPin(pinnedArr[openedIndex])
-  }, [openedIndex, pinnedArr])
+    setOpenedPin(pinnedMessagesMemo[openedIndex])
+  }, [pinnedMessagesMemo,openedIndex])
 
   return openedPin ?
     <Stack className={classes.container} direction="row">
@@ -130,7 +129,7 @@ const PinnedBar = ({divRef}:{divRef: any | null}) => {
             <Avatar alt={openedPin.name} src={openedPin.avatarUrl?`${prodAwsS3}/${openedPin.avatarUrl}`:undefined}
               sx={{ background: openedPin.color, width: 44, height: 44 }}>
               {!openedPin.avatarUrl&&`${firstLetter(openedPin.name)}${firstLetter(openedPin.lastName)}`}
-          </Avatar>
+            </Avatar>
           </ListItemIcon>           
           <ListItemText style={{marginLeft:20}}
             primary={`${firstLetter(openedPin.name)}${slicedWord(openedPin.name, 15, 1)}
@@ -139,7 +138,7 @@ const PinnedBar = ({divRef}:{divRef: any | null}) => {
             secondary={slicedWord(openedPin.message, 20, 1)}
             secondaryTypographyProps={{fontSize: 12 }} />
           <ListItemText style={{marginLeft:20}}
-            primary={`Pinned Message ${openedIndex + 1} of ${pinnedArr.length}`}
+            primary={`Pinned Message ${openedIndex + 1} of ${pinnedMessagesMemo.length}`}
             primaryTypographyProps={{ color: "#0379af",fontSize:16 }}
             secondary={`Type : ${openedPin.type.toUpperCase()}`}
             secondaryTypographyProps={{ fontSize:16 }}/>          
@@ -168,7 +167,7 @@ const PinnedBar = ({divRef}:{divRef: any | null}) => {
       <IconButton onClick={() => setModal(true)} aria-label="delete" size="medium">
         <CloseIcon className={classes.iconClose} fontSize='medium'/>
       </IconButton>
-      <IconButton aria-label="delete" size="medium">
+      <IconButton onClick={() => setOpenPinned(true)} aria-label="delete" size="medium">
         <MenuOpenIcon fontSize='medium'/>
       </IconButton>
       {modal &&

+ 45 - 9
src/components/HomePage/CentralBar/HeaderBar/index.tsx

@@ -1,15 +1,19 @@
 import Toolbar from '@mui/material/Toolbar'
 import AppBar from '@mui/material/AppBar';
-import { makeStyles } from '@material-ui/core'
+import { makeStyles,Typography } from '@material-ui/core'
 import Button from '@mui/material/Button';
 import { useState } from 'react';
 import { useSelector } from 'react-redux';
 
+import IconButton from '@mui/material/IconButton';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+import Divider from '@mui/material/Divider';
 import Credentials from './Credentials'
 import Buttons from './Buttons'
 import PinnedBar from './PinnedBar';
 import { removeSelectedMessagesById } from '../../../../api-data';
 import { getChatMemo } from '../../../../redux/chat/selector';
+import { TPinnedMessages } from '../../../../typescript/redux/pinnedMessages/types'; 
 
 const useStyles = makeStyles({
   toolBar: {
@@ -19,9 +23,16 @@ const useStyles = makeStyles({
     backgroundColor: '#ffffff',
     height:'7vh'
   },
+  toolBarPinned: {
+    color: '#6e6d6d',
+    display: 'flex',
+    backgroundColor: '#ffffff',
+    height: '7vh',
+    cursor:'pointer'
+  }, 
   toolBarRight: {
     display: 'flex',
-  },
+  },   
   buttonDelete: {
     color: '#f8f8f8',
     backgroundColor:'#1d74c5',
@@ -48,18 +59,27 @@ const useStyles = makeStyles({
     zIndex: 100,
     backgroundColor: 'rgba(104, 105, 104, 0.6)',
     overflowY: 'hidden',
+  },
+  iconArrow: {
+    '&:hover': {
+      transform: 'rotate(360deg)',
+      transition: 'all 250ms ease-out ',
+    }
   },  
 })
 
 interface IHeaderBar {
-  divRef: any | null,
+  chatDivRef: any | null,
   selectedArr: string[] | [],
   isSomeSelected: boolean,
   setIsSomeSelected: React.Dispatch<React.SetStateAction<boolean>>,
-  handleClearSelect: () => void
+  handleClearSelect: () => void,
+  openPinned: boolean,
+  setOpenPinned: React.Dispatch<React.SetStateAction<boolean>>,
+  pinnedMessagesMemo:TPinnedMessages
 }
 
-const HeaderBar = ({divRef,selectedArr,isSomeSelected,setIsSomeSelected,handleClearSelect}:IHeaderBar) => {
+const HeaderBar = ({chatDivRef,selectedArr,isSomeSelected,setIsSomeSelected,handleClearSelect,openPinned,setOpenPinned,pinnedMessagesMemo}:IHeaderBar) => {
   const classes = useStyles()
   const { companionId } = useSelector(getChatMemo)
   const [modal, setModal] = useState<boolean>(false)
@@ -78,16 +98,31 @@ const HeaderBar = ({divRef,selectedArr,isSomeSelected,setIsSomeSelected,handleCl
     }
   }    
 
-    return (!isSomeSelected?
+  return (<>
+    {openPinned &&
+      <AppBar position="static">
+        <Toolbar className={classes.toolBarPinned}>
+          <IconButton onClick={() => setOpenPinned(false)}
+             aria-label="delete" size="medium">
+            <ArrowBackIcon className={classes.iconArrow} fontSize='medium'/>
+          </IconButton>
+          <Typography style={{ marginLeft: 20, color: '#474747' }} variant="h6" color="initial">
+            {`${pinnedMessagesMemo.length} pinned messages`}
+          </Typography>
+        </Toolbar>
+      </AppBar>}
+    {openPinned&&isSomeSelected&&<Divider variant="inset"/>}
+    {!openPinned && !isSomeSelected &&
       <AppBar position="static">
         <Toolbar className={classes.toolBar}>
           <Credentials/>
           <div className={classes.toolBarRight}>
-            <PinnedBar divRef={divRef}/>
+            <PinnedBar chatDivRef={chatDivRef} setOpenPinned={setOpenPinned}/>
             <Buttons setIsSomeSelected={setIsSomeSelected}/>
           </div>
         </Toolbar>
-      </AppBar> :
+      </AppBar>} 
+    {isSomeSelected &&
       <AppBar position="static">
         <Toolbar className={classes.toolBar}>
           <Button color='primary' onClick={handleOpenModal}
@@ -113,7 +148,8 @@ const HeaderBar = ({divRef,selectedArr,isSomeSelected,setIsSomeSelected,handleCl
             </Button>
           </div>  
         </div>}         
-      </AppBar>      
+      </AppBar>}
+    </>
     )
 }
 

+ 34 - 6
src/components/HomePage/CentralBar/index.tsx

@@ -1,10 +1,13 @@
 import Grid from '@mui/material/Grid'
 import { makeStyles } from '@material-ui/core'
-import { useState,useRef } from 'react'
+import { useState,useEffect } from 'react'
+import { useSelector } from 'react-redux'
 
 import HeaderBar from './HeaderBar'
 import ChatBar from './ChatBar'
+import { getPinnedMessagesMemo } from '../../../redux/pinnedMessages/selector'
 import { TRightIsOpen } from '../../../typescript/redux/control/types'
+import { unpinAllMessagesById } from '../../../api-data'
 
 const useStyles = makeStyles({
   chatBar: {
@@ -12,22 +15,47 @@ const useStyles = makeStyles({
   },
 })
 
-const CentralBar = ({rightIsOpen,divRef}:{rightIsOpen:TRightIsOpen,divRef: any | null,}) => {
+interface ICentralBar {
+  rightIsOpen: TRightIsOpen,
+  chatDivRef: any | null,
+  companionId: string
+}
+
+const CentralBar = ({rightIsOpen,chatDivRef,companionId}:ICentralBar) => {
   const classes = useStyles()
+  const pinnedMessagesMemo = useSelector(getPinnedMessagesMemo)
   const [selectedArr, setSelectedArr] = useState<string[] | []>([])
+  const [openPinned, setOpenPinned] = useState<boolean>(false)
   const [isSomeSelected, setIsSomeSelected] = useState<boolean>(false)
   const handleClearSelect = () => {
-    selectedArr.length > 0 &&setSelectedArr([])
-    isSomeSelected&&setIsSomeSelected(false)
+    selectedArr.length > 0 && setSelectedArr([])
+    isSomeSelected && setIsSomeSelected(false)
+  }
+  const handleUnpinAll = () => {
+    openPinned && setOpenPinned(false)
+    unpinAllMessagesById(pinnedMessagesMemo.map(({_id}) => _id))
   }
+  
+  useEffect(() => {
+    if(pinnedMessagesMemo.length === 0 && openPinned) setOpenPinned(false)
+  }, [openPinned, pinnedMessagesMemo])
+  
+  useEffect(() => {
+    setIsSomeSelected(false)
+    setSelectedArr([])
+  },[companionId])  
 
     return ( 
      <Grid item lg={rightIsOpen?8:12}>
         <Grid item lg={12} >
-          <HeaderBar divRef={divRef} selectedArr={selectedArr} isSomeSelected={isSomeSelected} handleClearSelect={handleClearSelect} setIsSomeSelected={setIsSomeSelected}/>
+          <HeaderBar chatDivRef={chatDivRef} selectedArr={selectedArr} isSomeSelected={isSomeSelected}
+            handleClearSelect={handleClearSelect} setIsSomeSelected={setIsSomeSelected}
+            openPinned={openPinned} setOpenPinned={setOpenPinned} pinnedMessagesMemo={pinnedMessagesMemo}/>
         </Grid>          
         <Grid item lg={12} className={classes.chatBar}>
-          <ChatBar divRef={divRef} selectedArr={selectedArr} setSelectedArr={setSelectedArr} isSomeSelected={isSomeSelected} setIsSomeSelected={setIsSomeSelected}/>
+          <ChatBar chatDivRef={chatDivRef} selectedArr={selectedArr} setSelectedArr={setSelectedArr}
+            isSomeSelected={isSomeSelected} setIsSomeSelected={setIsSomeSelected}
+            openPinned={openPinned} pinnedMessagesMemo={pinnedMessagesMemo} handleUnpinAll={handleUnpinAll}/>
         </Grid>
       </Grid>
     )   

+ 8 - 8
src/components/HomePage/LeftBar/SearchLists/index.tsx

@@ -57,10 +57,10 @@ interface ISearchLists {
   date: any,
   setDate: React.Dispatch<any>,
   setDisabled: React.Dispatch<boolean>,
-  divRef: any | null
+  chatDivRef: any | null
 }
 
-const SearchLists = ({ value,setValue,sort,date,setDate,setDisabled,divRef}: ISearchLists) => {
+const SearchLists = ({ value,setValue,sort,date,setDate,setDisabled,chatDivRef}: ISearchLists) => {
     const classes = useStyles()
     const dispatch = useDispatch()
     const { chats, total } = useSelector(getStateMemo)
@@ -92,19 +92,19 @@ const SearchLists = ({ value,setValue,sort,date,setDate,setDisabled,divRef}: ISe
     }
   
     const handleScrollToTheMessage = (_id: string, companionId: string) => {
-      if (divRef.current && divRef.current.id === companionId) {
-         scrollTo(divRef,_id)
-      } else if (divRef.current && divRef.current.id !== companionId) {
+      if (chatDivRef.current && chatDivRef.current.id === companionId) {
+         scrollTo(chatDivRef,_id)
+      } else if (chatDivRef.current && chatDivRef.current.id !== companionId) {
         rightIsOpen&&dispatch(actionRightIsOpen(''))
         dispatch(asyncStartChatById(companionId))
         setTimeout(() => {
-          if(divRef.current) scrollTo(divRef,_id)
+          if(chatDivRef.current) scrollTo(chatDivRef,_id)
         }, 3000)        
-      } else if (!divRef.current) {
+      } else if (!chatDivRef.current) {
         rightIsOpen&&dispatch(actionRightIsOpen(''))
         dispatch(asyncStartChatById(companionId))
         setTimeout(() => {
-          if(divRef.current) scrollTo(divRef,_id)
+          if(chatDivRef.current) scrollTo(chatDivRef,_id)
       }, 3000)
       }
     }  

+ 2 - 2
src/components/HomePage/LeftBar/index.tsx

@@ -16,7 +16,7 @@ import { getAuthorizationState } from '../../../redux/authorization/selector';
 import { getLeftIsOpen } from '../../../redux/control/selector';
 import { actionLeftIsOpen } from '../../../redux/control/action';
 
-const LeftBar = ({divRef}:{divRef: any | null}) => {
+const LeftBar = ({chatDivRef}:{chatDivRef: any | null}) => {
   const dispatch = useDispatch()
   const { sort, nightMode } = useSelector(getAuthorizationState)
   const leftIsOpen = useSelector(getLeftIsOpen)
@@ -77,7 +77,7 @@ const LeftBar = ({divRef}:{divRef: any | null}) => {
             handleSearch={handleSearch} leftIsOpen={leftIsOpen} value={value} setDate={setDate}
             date={date} disabled={disabled} />:null}
         {leftIsOpen === 'searchChats' || leftIsOpen === 'searchAllMessages' ?<SearchLists value={value} setValue={setValue}
-          sort={sort} date={date} setDate={setDate} setDisabled={setDisabled} divRef={divRef}/>:null}
+          sort={sort} date={date} setDate={setDate} setDisabled={setDisabled} chatDivRef={chatDivRef}/>:null}
         {leftIsOpen === ''&&<ChatsList sort={sort}/>}
         {leftIsOpen === '' && popup && <SmallMenuBar setPopup={setPopup} />}
         {modal && modalRoot.current &&

+ 2 - 2
src/components/HomePage/RightBar/CredentialsList/ProfileLists/index.tsx

@@ -44,14 +44,14 @@ underline: {
   },
 })
 
-const ProfileLists = ({setDisabled,divRef}:{setDisabled: React.Dispatch<boolean>,divRef: any | null}) => {
+const ProfileLists = ({setDisabled,chatDivRef}:{setDisabled: React.Dispatch<boolean>,chatDivRef: any | null}) => {
     const classes = useStyles()
     const { sort } = useSelector(getChat)
     const messagesMemo = useSelector(getMessagesMemo)
     const [isActive, setIsActive] = useState<number>(0)
     const handleIsActive = (newValue: number): void => setIsActive(newValue)
     const handleScrollToTheMessage = (_id: string) => {
-      const childNodes = divRef.current.childNodes[0].childNodes
+      const childNodes = chatDivRef.current.childNodes[0].childNodes
       let toScrollNode = [...childNodes].find((el: any) => el.id === _id)
       if (toScrollNode) {
         toScrollNode = [...toScrollNode.childNodes].slice(-1)[0]

+ 2 - 2
src/components/HomePage/RightBar/CredentialsList/index.tsx

@@ -40,7 +40,7 @@ const useStyles = makeStyles({
   },
 })
 
-const CredentialsList = ({divRef}:{divRef: any | null}) => {
+const CredentialsList = ({chatDivRef}:{chatDivRef: any | null}) => {
   const classes = useStyles()
   const dispatch = useDispatch()
   const leftIsOpen  = useSelector(getLeftIsOpen)
@@ -59,7 +59,7 @@ const CredentialsList = ({divRef}:{divRef: any | null}) => {
       <div className={classes.scrollContainer}>
         <ProfilePicture />
         <ProfileMenu disabled={disabled}/>
-        <ProfileLists setDisabled={setDisabled} divRef={divRef}/>
+        <ProfileLists setDisabled={setDisabled} chatDivRef={chatDivRef}/>
       </div>
     </div>
   )

+ 2 - 2
src/components/HomePage/RightBar/SearchList/index.tsx

@@ -49,7 +49,7 @@ const useStyles = makeStyles({
   },
 })
 
-const SearchList= ({divRef}:{divRef: any | null}) => {
+const SearchList= ({chatDivRef}:{chatDivRef: any | null}) => {
     const classes = useStyles()
     const { sort } = useSelector(getChat)
     const messages = useSelector(getMessages)
@@ -57,7 +57,7 @@ const SearchList= ({divRef}:{divRef: any | null}) => {
     const [date, setDate] = useState<any>('');
     const handleSearch = (e: React.ChangeEvent<HTMLInputElement>): void => setValue(e.target.value)
     const handleScrollToTheMessage = (_id: string) => {
-      const childNodes = divRef.current.childNodes[0].childNodes
+      const childNodes = chatDivRef.current.childNodes[0].childNodes
       let toScrollNode = [...childNodes].find((el: any) => el.id === _id)
       if (toScrollNode) {
         toScrollNode = [...toScrollNode.childNodes].slice(-1)[0]

+ 3 - 3
src/components/HomePage/RightBar/index.tsx

@@ -4,11 +4,11 @@ import CredentialsList from './CredentialsList'
 import EditBar from './EditBar'
 import { TRightIsOpen } from '../../../typescript/redux/control/types'
 
-const RightBar = ({rightIsOpen,divRef}:{rightIsOpen:TRightIsOpen,divRef: any | null}) => {
+const RightBar = ({rightIsOpen,chatDivRef}:{rightIsOpen:TRightIsOpen,chatDivRef: any | null}) => {
   return (
     <Grid item lg={rightIsOpen?4:0}>
-      {rightIsOpen === 'credentials' && <CredentialsList divRef={divRef} />}
-      {rightIsOpen === 'search' && <SearchList divRef={divRef}/>}
+      {rightIsOpen === 'credentials' && <CredentialsList chatDivRef={chatDivRef} />}
+      {rightIsOpen === 'search' && <SearchList chatDivRef={chatDivRef}/>}
       {rightIsOpen === 'edit' && <EditBar/>}
     </Grid>
    )

+ 4 - 4
src/components/HomePage/index.tsx

@@ -25,16 +25,16 @@ const useStyles = makeStyles({
 const HomePage = () => {
   const classes = useStyles()
   const rightIsOpen = useSelector(getRightIsOpen)
-  const divRef = useRef<any | null>(null)
+  const chatDivRef = useRef<any | null>(null)
   const { companionId } = useSelector(getChatMemo)
  
 return (
     <Grid className={classes.container} container spacing={0} >
-      <LeftBar divRef={divRef} />
+      <LeftBar chatDivRef={chatDivRef} />
       {companionId ?
       <Grid item lg={9} className={classes.centralAndRight}>
-        <CentralBar rightIsOpen={rightIsOpen} divRef={divRef}/>
-        <RightBar rightIsOpen={rightIsOpen} divRef={divRef}/>
+        <CentralBar rightIsOpen={rightIsOpen} chatDivRef={chatDivRef} companionId={companionId}/>
+        <RightBar rightIsOpen={rightIsOpen} chatDivRef={chatDivRef}/>
       </Grid> :
       <Grid item lg={9} className={classes.centralBar}/>}
     </Grid>

+ 1 - 0
src/redux/control/action/index.ts

@@ -14,4 +14,5 @@ const actionScrollChat = createAction('control/scrollChat', (value:TScrollChat)
 }));
 
 
+
 export { actionLeftIsOpen,actionRightIsOpen,actionScrollChat };

+ 1 - 1
src/redux/control/reducer/index.ts

@@ -21,7 +21,7 @@ const reducerControl = createReducer(initialState, {
   [actionScrollChat.type]: (state, { payload: scrollChat }: IPayloadScrollChat) => {
     if (isEqual(state.scrollChat, scrollChat) === false) return {...state,scrollChat}
     return state;    
-  },  
+  },
 });
 
 export default reducerControl;

+ 6 - 1
src/redux/messages/operations/index.ts

@@ -2,6 +2,7 @@ import {
   actionGetMessagesSuccess,
   actionGetMessagesReject
 } from '../action';
+import { asyncFindPinnedMessages } from '../../pinnedMessages/operations'
 import { getMessagesById } from '../../../api-data';
 import { IMessagesState } from '../../../typescript/redux/messages/interfaces'
 
@@ -9,10 +10,14 @@ import { IMessagesState } from '../../../typescript/redux/messages/interfaces'
 const asyncGetMessagesById= (id:string,cb:any) => async (dispatch:any) => {
   try {
     const data = await getMessagesById<IMessagesState>(id)
-    data && dispatch(actionGetMessagesSuccess(data))
+    if (data) {
+      dispatch(actionGetMessagesSuccess(data))
+      dispatch(asyncFindPinnedMessages(data.messages))
+    }
     cb&&cb()
   } catch (e) {
     dispatch(actionGetMessagesReject())
+    
   } 
 };
 

+ 16 - 0
src/redux/pinnedMessages/action/index.ts

@@ -0,0 +1,16 @@
+import { createAction } from '@reduxjs/toolkit';
+import { TPinnedMessages } from '../../../typescript/redux/pinnedMessages/types'
+
+const actionGetPinnedMessagesSuccess = createAction('getPinnedMessages/success', (value:TPinnedMessages) => ({
+  payload: value,
+}));
+
+const actionGetPinnedMessagesReject = createAction('getPinnedMessages/reject', () => ({
+  payload: null,
+}));
+
+
+export {
+  actionGetPinnedMessagesSuccess,
+  actionGetPinnedMessagesReject,
+};

+ 24 - 0
src/redux/pinnedMessages/operations/index.ts

@@ -0,0 +1,24 @@
+import {
+  actionGetPinnedMessagesSuccess,
+  actionGetPinnedMessagesReject,
+} from '../action';
+
+import { TPinnedMessages, TPinnedMessage } from '../../../typescript/redux/pinnedMessages/types'
+import { handleSort } from '../../../helpers';
+
+
+const asyncFindPinnedMessages= (messages:TPinnedMessages) => async (dispatch:any) => {
+  try {
+    const pinnedMessages = handleSort('updatedAt', messages.filter((el: TPinnedMessage) => el.pinned === true), true)
+     if(pinnedMessages)  dispatch(actionGetPinnedMessagesSuccess(pinnedMessages))
+  } catch (e) {
+    dispatch(actionGetPinnedMessagesReject())
+  } 
+};
+
+
+export { asyncFindPinnedMessages };
+
+
+
+

+ 22 - 0
src/redux/pinnedMessages/reducer/index.ts

@@ -0,0 +1,22 @@
+import isEqual from 'lodash.isequal';
+import { createReducer } from '@reduxjs/toolkit';
+import { IPinnedMessagesPayload} from '../../../typescript/redux/pinnedMessages/interfaces';
+import { TPinnedMessages} from '../../../typescript/redux/pinnedMessages/types';
+import {
+  actionGetPinnedMessagesSuccess,
+  actionGetPinnedMessagesReject,
+} from '../action';
+
+const initialState: TPinnedMessages = []
+
+const reducerPinnedMessages = createReducer(initialState, {
+  [actionGetPinnedMessagesSuccess.type]: (state, { payload }: IPinnedMessagesPayload) => {
+    if (isEqual(state, payload) === false) return payload
+    return state;
+  },
+  [actionGetPinnedMessagesReject.type]: (state, _payload) => {
+    return state;
+  },
+});
+
+export default reducerPinnedMessages;

+ 8 - 0
src/redux/pinnedMessages/selector/index.ts

@@ -0,0 +1,8 @@
+import { createSelector } from 'reselect';
+import { IState } from '../../../typescript/redux/interfaces'
+
+const getPinnedMessages = (state: IState) => state.pinnedMessages;
+const getState = (state: IState) => state.pinnedMessages;
+const getPinnedMessagesMemo = createSelector([getPinnedMessages], pinnedMessages => pinnedMessages);
+
+export { getPinnedMessages,getState,getPinnedMessagesMemo };

+ 2 - 0
src/redux/rootReducer/index.ts

@@ -3,6 +3,7 @@ import { persistReducer } from 'redux-persist';
 import storage from 'redux-persist/lib/storage';
 
 import reducerMessages from '../messages/reducer'
+import reducerPinnedMessages from '../pinnedMessages/reducer';
 import reducerAllMessages from '../allMessages/reducer'
 import reducerContacts from '../contacts/reducer'
 import reducerChat from '../chat/reducer'
@@ -17,6 +18,7 @@ const authorizationPersistConfig = {
 
 export const rootReducer = combineReducers({
   messages: reducerMessages,
+  pinnedMessages: reducerPinnedMessages,
   allMessages: reducerAllMessages,
   chat:reducerChat,
   chats: reducerChats,

+ 1 - 1
src/typescript/redux/control/types.ts

@@ -2,4 +2,4 @@ export type TLeftIsOpen = (''  | 'contacts'| 'contact' | 'searchChats' | 'search
 
 export type TRightIsOpen = ('' | 'credentials' | 'search' | 'edit')
 
-export type TScrollChat = boolean
+export type TScrollChat = boolean

+ 2 - 0
src/typescript/redux/interfaces.ts

@@ -3,11 +3,13 @@ import { IContactsState } from './contacts/interfaces'
 import { IChatsState } from './chats/interfaces'
 import { TChat } from './chat/types'
 import { IMessagesState } from './messages/interfaces'
+import { TPinnedMessages } from './pinnedMessages/types'
 import { IAllMessagesState} from './allMessages/interfaces'
 import { IControlState } from './control/interfaces'
 
 export interface IState {
   messages: IMessagesState,
+  pinnedMessages: TPinnedMessages,
   allMessages:IAllMessagesState,
   contacts: IContactsState,
   chat:TChat,

+ 10 - 0
src/typescript/redux/pinnedMessages/interfaces.ts

@@ -0,0 +1,10 @@
+import { TPinnedMessages } from './types'
+
+export interface IPinnedMessagesPayload {
+  payload: TPinnedMessages,
+}
+
+
+
+
+

+ 25 - 0
src/typescript/redux/pinnedMessages/types.ts

@@ -0,0 +1,25 @@
+export type TPinnedMessage = {
+  message:string,
+  name: string,
+  lastName: string,
+  avatarUrl:string,
+  color: string,
+  number:string,
+  _id: string,
+  type: string,
+  fullType: string,
+  caption: string,
+  emoji: string,
+  emojiCompanion: string,
+  pinned: boolean,
+  idTime: string,
+  companionId: string,
+  companionIdFlow: string,
+  owner: any,
+  createdAt: string,
+  updatedAt: string,
+  __v: number
+}
+
+export type TPinnedMessages = TPinnedMessage[] | []
+