瀏覽代碼

done left bar seaerch menu

unknown 3 年之前
父節點
當前提交
6f6c961bd1
共有 30 個文件被更改,包括 214 次插入195 次删除
  1. 1 1
      .eslintcache
  2. 2 2
      src/api-data/index.ts
  3. 3 3
      src/components/HomePage/LeftBar/AddContact/index.tsx
  4. 5 1
      src/components/HomePage/LeftBar/ChatsList/ChatItem/index.tsx
  5. 3 3
      src/components/HomePage/LeftBar/ChatsList/index.tsx
  6. 8 5
      src/components/HomePage/LeftBar/ContactsList/index.tsx
  7. 12 7
      src/components/HomePage/LeftBar/MenuBar/index.tsx
  8. 30 15
      src/components/HomePage/LeftBar/SearchBar/index.tsx
  9. 8 6
      src/components/HomePage/LeftBar/SearchLists/AudioList/index.tsx
  10. 2 77
      src/components/HomePage/LeftBar/SearchLists/ChatListRecent/ChatItem/index.tsx
  11. 4 4
      src/components/HomePage/LeftBar/SearchLists/ChatListRecent/index.tsx
  12. 9 5
      src/components/HomePage/LeftBar/SearchLists/FilesList/index.tsx
  13. 1 1
      src/components/HomePage/LeftBar/SearchLists/MediaList/MediaListItem/index.tsx
  14. 8 4
      src/components/HomePage/LeftBar/SearchLists/MediaList/index.tsx
  15. 8 4
      src/components/HomePage/LeftBar/SearchLists/TextList/index.tsx
  16. 9 5
      src/components/HomePage/LeftBar/SearchLists/VideoList/index.tsx
  17. 22 11
      src/components/HomePage/LeftBar/SearchLists/index.tsx
  18. 25 22
      src/components/HomePage/LeftBar/index.tsx
  19. 1 1
      src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/CredentialsList/ProfileLists/MediaList/MediaListItem/index.tsx
  20. 15 3
      src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/CredentialsList/ProfileMenu/index.tsx
  21. 14 7
      src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/CredentialsList/ProfilePicture/index.tsx
  22. 3 3
      src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/EditBar/EditList/index.tsx
  23. 3 2
      src/helpers/index.ts
  24. 1 1
      src/redux/authorization/operations/index.ts
  25. 4 0
      src/redux/authorization/reducer/index.ts
  26. 3 2
      src/redux/authorization/selector/index.ts
  27. 2 0
      src/redux/chat/reducer/index.ts
  28. 4 0
      src/typescript/redux/authorization/interfaces.ts
  29. 2 0
      src/typescript/redux/chat/types.ts
  30. 2 0
      src/typescript/redux/chats/types.ts

File diff suppressed because it is too large
+ 1 - 1
.eslintcache


+ 2 - 2
src/api-data/index.ts

@@ -79,9 +79,9 @@ const onlineUser = async <T>():Promise<T | undefined> => {
   }
 };
 
-const updateCredentials = async <T>(name: string,lastName: string):Promise<T | undefined> => {
+const updateCredentials = async <T>(body:object):Promise<T | undefined> => {
   try {
-    const { data : {data} } = await axios.patch('/users/current', { name, lastName });
+    const { data : {data} } = await axios.patch('/users/current', body);
     return data
   } catch (e) {
     forbidden(e)

+ 3 - 3
src/components/HomePage/LeftBar/AddContact/index.tsx

@@ -30,10 +30,10 @@ const useStyles = makeStyles({
 })
 
 interface IAddContact {
-  setIMenu: React.Dispatch<React.SetStateAction<number | null>>
+  setSelectedIndex: React.Dispatch<React.SetStateAction<number | null>>
 }
 
-const AddContact = ({setIMenu}:IAddContact) => {
+const AddContact = ({setSelectedIndex}:IAddContact) => {
   const classes = useStyles()
   const dispatch = useDispatch()
   const [number, setNumber] = useState<string>('')
@@ -45,7 +45,7 @@ const AddContact = ({setIMenu}:IAddContact) => {
   const handleAddContact = async () => {
     dispatch(asyncAddContact(number))
     setNumber('')
-    setIMenu(1)  
+    setSelectedIndex(1)  
   }
 
   const isValidNumber = () => {

+ 5 - 1
src/components/HomePage/LeftBar/ChatsList/ChatItem/index.tsx

@@ -1,6 +1,5 @@
 import { makeStyles,Typography } from '@material-ui/core'
 import { useState } from 'react';
-import { useDispatch } from 'react-redux';
 import { styled } from '@mui/material/styles';
 import Menu from '@mui/material/Menu';
 import MenuItem from '@mui/material/MenuItem';
@@ -13,6 +12,7 @@ import ListItemText from '@mui/material/ListItemText';
 import ListItemIcon from '@mui/material/ListItemIcon';
 import Badge from '@mui/material/Badge';
 import DoneAllIcon from '@mui/icons-material/DoneAll';
+import PushPinIcon from '@mui/icons-material/PushPin';
 
 import { muteChat,removeChatForBoth } from '../../../../../api-data';
 import { TChat } from '../../../../../typescript/redux/chats/types';
@@ -255,6 +255,10 @@ const  ChatItem = ({chat,handleListItemClick,handleNewMsgs}:IChatItem) => {
         open={open}
         onClose={handleClose}
       >
+        <MenuItem onClick={() => handleClose('pin')}>
+            <PushPinIcon /> 
+            Pin to top
+         </MenuItem>  
         <MenuItem onClick={() => handleClose('mute')}>
           {mute ? <NotificationsNoneIcon /> : <VolumeOffIcon />}
           {mute ? 'Unmute chat':'Mute chat'}

+ 3 - 3
src/components/HomePage/LeftBar/ChatsList/index.tsx

@@ -40,7 +40,7 @@ const useStyles = makeStyles({
   },
 })
 
-const ChatsList = () => {
+const ChatsList = ({sort}:{sort:boolean}) => {
   const classes = useStyles()
   const dispatch = useDispatch()
   const ref = useRef<any>(null)
@@ -73,7 +73,7 @@ const ChatsList = () => {
       dispatch(asyncStartChatById(companionId))
       dispatch(actionScroll(true))
     }
-    const sorted = sortByRecent(chats)
+    const sorted = sortByRecent(chats,sort)
     setSortedChats(sorted)
     if (chat.companionId&&!sorted.find((el) => el.companionId === chat.companionId))dispatch(actionRemoveChat())
     if (ref.current) {
@@ -89,7 +89,7 @@ const ChatsList = () => {
       })
     }
       ref.current = sorted
-  }, [chats, chat, dispatch]) 
+  }, [chats, chat,sort, dispatch]) 
 
   return total !== '0' ? (
     <List className={classes.list} component="nav"

+ 8 - 5
src/components/HomePage/LeftBar/ContactsList/index.tsx

@@ -1,6 +1,6 @@
 import List from '@mui/material/List';
 import { makeStyles } from '@material-ui/core'
-import { useEffect,useState } from 'react';
+import { useEffect } from 'react';
 import { useSelector,useDispatch } from 'react-redux';
 
 import AlertInfo from '../../../reusableComponents/AlertInfo'
@@ -10,6 +10,8 @@ import { asyncGetContacts } from '../../../../redux/contacts/operations'
 import { asyncStartChatById } from '../../../../redux/chat/operations'
 import { getIsOpen } from '../../../../redux/control/selector'
 import { actionIsOpen } from '../../../../redux/control/action';
+import { handleSort } from '../../../../helpers';
+import { TContacts } from '../../../../typescript/redux/contacts/types';
 
 const useStyles = makeStyles({
   list: {
@@ -38,9 +40,10 @@ const useStyles = makeStyles({
 
 interface IContactList {
   value: string,
-  handleClick: any
+  handleClick: any,
+  sort: boolean
 }
-const  ContactsList = ({value,handleClick} : IContactList) => {
+const  ContactsList = ({value,handleClick,sort} : IContactList) => {
   const classes = useStyles()
   const dispatch = useDispatch()
   const { total, contacts } = useSelector(getState)
@@ -52,7 +55,7 @@ const  ContactsList = ({value,handleClick} : IContactList) => {
     dispatch(asyncStartChatById(companionId))
   }
 
-  const filteredContacts = () => [...contacts].sort((a, b) => (a.name > b.name) ? 1 : -1).filter((el) => {
+  const filteredContacts = () => handleSort('name',contacts,sort).filter((el:any) => {
     const credentials = el.name + ' ' + el.lastName
     if(credentials.toLowerCase().includes(value.toLowerCase())) return el
   })
@@ -64,7 +67,7 @@ const  ContactsList = ({value,handleClick} : IContactList) => {
     return () => clearInterval(idInterval);
   }, [dispatch,isOpen]);
 
-  const arr = filteredContacts()
+  const arr:TContacts = filteredContacts()
   
   return total !== '0' ? (
     <List

+ 12 - 7
src/components/HomePage/LeftBar/MenuBar/index.tsx

@@ -11,6 +11,9 @@ import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
 import BugReportIcon from '@mui/icons-material/BugReport';
 import Switch from '@mui/material/Switch';
 import { makeStyles } from '@material-ui/core'
+import { useDispatch } from 'react-redux';
+import { asyncCurrentUser } from '../../../../redux/authorization/operations';
+import { updateCredentials } from '../../../../api-data';
 
 const useStyles = makeStyles({
     overlay: {
@@ -48,14 +51,16 @@ const useStyles = makeStyles({
 const label = { inputProps: { 'aria-label': 'Switch demo' } };
 
 interface IContactsList {
-  handleSelectedMenu: (i:number) => void
+  handleSelectedMenu: (i: number) => void,
+  nightMode: boolean
 }
 
-const MenuBar = ({handleSelectedMenu}:IContactsList) => {
+const MenuBar = ({handleSelectedMenu,nightMode}:IContactsList) => {
   const classes = useStyles()
-  const handleSwitch = (e: React.MouseEvent<HTMLElement>) => {
-    e.stopPropagation()
-    console.log('clicked switch input')
+  const dispatch = useDispatch()
+  const handleNightMode = () => {
+      updateCredentials({ nightMode: !nightMode })
+      dispatch(asyncCurrentUser())
   }
   return (
     <div className={classes.overlay} id='overlay'>
@@ -73,12 +78,12 @@ const MenuBar = ({handleSelectedMenu}:IContactsList) => {
           </ListItemIcon>
           <ListItemText>Settings</ListItemText>
         </MenuItem>
-        <MenuItem>
+        <MenuItem style={{cursor:'default'}}>
           <ListItemIcon className={classes.listIcon}>
             <Brightness3Icon fontSize="medium" />
           </ListItemIcon>
           <ListItemText>Night Mode</ListItemText>
-          <Switch onClick={handleSwitch} {...label} />
+          <Switch onClick={handleNightMode} checked={nightMode} {...label} style={{cursor:'pointer'}}/>
         </MenuItem>
         <a style={{ textDecoration: 'none', color: 'inherit' }} target='blank'
           href='https://www.makeuseof.com/tag/useful-telegram-features/'>

+ 30 - 15
src/components/HomePage/LeftBar/SearchBar/index.tsx

@@ -4,8 +4,13 @@ import MenuIcon from '@mui/icons-material/Menu';
 import SearchIcon from '@mui/icons-material/Search';
 import InputBase from '@mui/material/InputBase';
 import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+import Switch from '@mui/material/Switch';
 import { styled } from '@mui/material/styles';
 import { makeStyles } from '@material-ui/core'
+import { useDispatch } from 'react-redux';
+import { updateCredentials } from '../../../../api-data';
+import { asyncCurrentUser } from '../../../../redux/authorization/operations';
+
 
 const Search = styled('div')(({ theme }:any) => ({
   position: 'relative',
@@ -16,7 +21,7 @@ const Search = styled('div')(({ theme }:any) => ({
     color:'#2184f7',
   }, 
   marginLeft: 0,
-  width: '100%',
+  maxWidth: '80%',
   [theme.breakpoints.up('sm')]: {
     marginLeft: theme.spacing(1),
     width: 'auto',
@@ -41,7 +46,7 @@ const StyledInputBase = styled(InputBase)(({ theme }) => ({
     padding: theme.spacing(1, 1, 1, 0),
     paddingLeft: `calc(1em + ${theme.spacing(4)})`,
     transition: theme.transitions.create('width'),
-    width: '100%',
+    maxWidth: '80%',
     [theme.breakpoints.up('sm')]: {
       width: '35ch',
       '&:focus': {
@@ -54,7 +59,7 @@ const StyledInputBase = styled(InputBase)(({ theme }) => ({
 
 const useStyles = makeStyles({
   toolBar: {
-    color:'#b1aeae',
+    color: '#b1aeae',
   },
   iconBtn: {
     '&:hover': {
@@ -70,34 +75,44 @@ const useStyles = makeStyles({
   },
 })
 
+const label = { inputProps: { 'aria-label': 'Switch demo' } };
+
 interface ISearchBar {
   handleClick:() => void,
   handleFocus:() => void,
   handleSearch:(e: React.ChangeEvent<HTMLInputElement>) => void,
-  isOpen: boolean,
-  iMenu: number | null,
-  value:string
+  isSearch: boolean,
+  selectedIndex: number | null,
+  value: string,
+  sort : boolean
 }
 
-const SearchBar = ({handleClick,handleFocus,handleSearch,isOpen,iMenu,value}:ISearchBar) => {
+const SearchBar = ({ handleClick, handleFocus, handleSearch, isSearch, selectedIndex, value,sort }: ISearchBar) => {
+  const dispatch = useDispatch()
+  const handleSort = () => {
+    updateCredentials({ sort: !sort })
+    dispatch(asyncCurrentUser())
+  }
+  
   const classes = useStyles()
     return (
         <Toolbar className={classes.toolBar}>
             <IconButton  onClick={handleClick}>
-                {isOpen ? <ArrowBackIcon className={classes.iconArrow} /> : <MenuIcon className={classes.iconBtn} />}
+                {isSearch ? <ArrowBackIcon className={classes.iconArrow} /> : <MenuIcon className={classes.iconBtn} />}
             </IconButton>
           <Search>
-                <SearchIconWrapper>
-                    <SearchIcon />
-                </SearchIconWrapper>
-                <StyledInputBase
+              <SearchIconWrapper>
+                  <SearchIcon />
+              </SearchIconWrapper>
+              <StyledInputBase
                  value={value}
                  onFocus={handleFocus}
                  onChange={handleSearch}
-                 placeholder={iMenu === 2 ?'Search contacts':'Search'}
+                 placeholder={selectedIndex === 1 ?'Search contacts':'Search'}
                  inputProps={{ 'aria-label': 'search' }}
-                />
-            </Search>
+              />
+          </Search>
+          <Switch onClick={handleSort} checked={sort} {...label} />
         </Toolbar>
     )
 }

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

@@ -13,7 +13,7 @@ import { TAllMessages } from '../../../../../typescript/redux/allMessages/types'
 const useStyles = makeStyles({
   container: {
     width: '100%',
-    maxHeight: '860px',
+    maxHeight: '840px',
     overflowY: 'scroll',
   '&::-webkit-scrollbar': {
     width: '0.4em'
@@ -46,10 +46,11 @@ const useStyles = makeStyles({
     }
   },  
 })
-const AudioList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
+const AudioList = ({ allMessagesMemo,value }: { allMessagesMemo: TAllMessages,value:string }) => {
   const classes = useStyles()
     const filteredMessagesMemo =  allMessagesMemo.filter(({type}) => type === 'audio')
-    return filteredMessagesMemo.length > 0 ?(
+  return(
+    <>
       <List className={classes.container}>
         {filteredMessagesMemo.map(({ message, createdAt, fullType }) =>
           <div key={createdAt}>
@@ -66,8 +67,9 @@ const AudioList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
             </ListItem>
             <Divider variant="inset"/>
         </div>)}
-    </List>
-   ): <AlertInfo name='You do not have Audio yet!'/>  
+      </List>
+      {value &&  filteredMessagesMemo.length === 0 && <AlertInfo name={`Can not find Audio by request: ${value}`} />}
+      {!value && filteredMessagesMemo.length === 0 && <AlertInfo name='You do not have Audio yet!'/>}
+   </>)
 }
-
 export default AudioList

+ 2 - 77
src/components/HomePage/LeftBar/SearchLists/ChatListRecent/ChatItem/index.tsx

@@ -1,55 +1,12 @@
 import { makeStyles,Typography } from '@material-ui/core'
-import { useState } from 'react';
-import { styled } from '@mui/material/styles';
-import Menu from '@mui/material/Menu';
-import MenuItem from '@mui/material/MenuItem';
-import VolumeOffIcon from '@mui/icons-material/VolumeOff';
 import ListItemButton from '@mui/material/ListItemButton';
 import Avatar from '@mui/material/Avatar';
 import ListItemText from '@mui/material/ListItemText';
 import ListItemIcon from '@mui/material/ListItemIcon';
-import DoneAllIcon from '@mui/icons-material/DoneAll';
-import PushPinIcon from '@mui/icons-material/PushPin';
 
 import { TChat } from '../../../../../../typescript/redux/chats/types';
 import { firstLetter,slicedWord,timeStampEU } from '../../../../../../helpers';
 
-const StyledMenu = styled((props:any) => (
-  <Menu
-    elevation={0}
-    anchorOrigin={{
-      vertical: 'top',
-      horizontal: 'right',
-    }}
-    transformOrigin={{
-      vertical: 'bottom',
-      horizontal: 'right',
-    }}
-    {...props}
-  />
-))(({ theme }:any) => ({
-  '& .MuiPaper-root': {
-    borderRadius: 10,
-    marginTop: theme.spacing(0),
-    minWidth: 220,
-    color:
-      theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[500],
-    boxShadow:
-      'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
-    '& .MuiMenu-list': {
-      padding: '8px 8px',
-    },
-    '& .MuiMenuItem-root': {
-      marginBottom: theme.spacing(1),
-      '& .MuiSvgIcon-root': {
-        fontSize: 21,
-        color: theme.palette.text.secondary,
-        marginRight: theme.spacing(4),
-      }
-    },
-  },
-}));
-
 const useStyles = makeStyles({
   listItemInnerText: {
     display: 'flex',
@@ -78,29 +35,10 @@ interface IChatItem {
 
 const  ChatItem = ({chat,handleListItemClick}:IChatItem) => {
   const classes = useStyles()
-  const [anchorEl, setAnchorEl] = useState<any>(null);
-  const [selected, setSelected] = useState<boolean>(false);
-  const open = Boolean(anchorEl);
   const {name,lastName,avatarUrl,color,companionId,lastMessage,lastMessageCreatedAt,createdAt} = chat
 
-  const handleClose = (type: string | undefined): void => {
-    if (type === 'pin') console.log('pin to top')
-    setAnchorEl(null)
-    setSelected(false)
-  }
-  const handleContextMenu = (e: React.MouseEvent<HTMLDivElement>):void => {
-    e.preventDefault()
-    setAnchorEl(e.currentTarget)
-    setSelected(true)
-  }  
-
   return (
-    <div>
-      <ListItemButton
-        selected={selected}
-        onClick={() => handleListItemClick(companionId)}
-        onContextMenu={(e) => handleContextMenu(e)}
-      >
+      <ListItemButton onClick={() => handleListItemClick(companionId)}>
         <ListItemIcon className={classes.listItem_iconAvatar}>
           <Avatar alt={name} src={avatarUrl?`http://localhost:3000/${avatarUrl}`:undefined}
             sx={{ background: color, width: 54, height: 54 }}>
@@ -116,20 +54,7 @@ const  ChatItem = ({chat,handleListItemClick}:IChatItem) => {
             {timeStampEU(lastMessageCreatedAt?lastMessageCreatedAt:createdAt)}
           </Typography>
         </ListItemIcon>            
-      </ListItemButton>
-      <StyledMenu
-        id="demo-positioned-menu"
-        aria-labelledby="demo-positioned-button"
-        anchorEl={anchorEl}
-        open={open}
-        onClose={handleClose}
-      >
-         <MenuItem onClick={() => handleClose('pin')}>
-            <PushPinIcon /> 
-            Pin to top
-          </MenuItem>      
-       </StyledMenu>    
-    </div>
+      </ListItemButton>    
   );
 }
 export default ChatItem

+ 4 - 4
src/components/HomePage/LeftBar/SearchLists/ChatListRecent/index.tsx

@@ -15,7 +15,7 @@ const useStyles = makeStyles({
   },
   container: {
     width: '100%',
-    maxHeight: '860px',
+    maxHeight: '840px',
     overflowY: 'scroll',
   '&::-webkit-scrollbar': {
     width: '0.4em'
@@ -46,20 +46,20 @@ interface IChatListRecent {
 const ChatListRecent = ({value,filteredAndSorted,handleListItemClick}:IChatListRecent) => {
   const classes = useStyles()
 
-
 return (
   <>
     {!value && filteredAndSorted.length > 0 &&
     <Stack direction="row" className={classes.stack}>
       {filteredAndSorted.slice(0, 6).map((chat) =>
       <RecentItem key={chat.companionId} handleListItemClick={handleListItemClick} chat={chat} />)}
-      </Stack>}
+    </Stack>}
     {value && filteredAndSorted.length > 0 &&
       <List className={classes.container} component="nav" aria-label="main mailbox folders">
         {filteredAndSorted.map((chat) =>
         <ChatItem key={chat.companionId} handleListItemClick={handleListItemClick} chat={chat} />)}
       </List>}
-    {value && filteredAndSorted.length === 0 &&<AlertInfo name={`Can not find chat by request: ${value}`}/>}
+    {value && filteredAndSorted.length === 0 && <AlertInfo name={`Can not find Chat by request: ${value}`} />}
+    {!value && filteredAndSorted.length === 0 &&<AlertInfo name='You do not have any Chats yet!'/>}
   </>)  
 }
 

+ 9 - 5
src/components/HomePage/LeftBar/SearchLists/FilesList/index.tsx

@@ -13,7 +13,7 @@ import { TAllMessages } from '../../../../../typescript/redux/allMessages/types'
 const useStyles = makeStyles({
   container: {
     width: '100%',
-    maxHeight: '860px',
+    maxHeight: '840px',
     overflowY: 'scroll',
   '&::-webkit-scrollbar': {
     width: '0.4em'
@@ -47,10 +47,11 @@ const useStyles = makeStyles({
   },  
 })
 
-const FilesList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
+const FilesList = ({ allMessagesMemo,value }: { allMessagesMemo: TAllMessages,value: string }) => {
   const classes = useStyles()
     const filteredMessagesMemo =  allMessagesMemo.filter(({type}) => type !== 'text')
-    return filteredMessagesMemo.length > 0 ?(
+  return (
+    <>
       <List className={classes.container}>
         {filteredMessagesMemo.map(({ message, createdAt, fullType }) =>
           <div key={createdAt}>
@@ -67,8 +68,11 @@ const FilesList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
             </ListItem>
             <Divider variant="inset"/>
         </div>)}
-    </List>
-   ): <AlertInfo name='You do not have Files yet!'/>  
+      </List>
+      {value &&  filteredMessagesMemo.length === 0 && <AlertInfo name={`Can not find Files by request: ${value}`} />}
+      {!value && filteredMessagesMemo.length === 0 && <AlertInfo name='You do not have Files yet!'/>}
+    </>
+  )
 }
 
 export default FilesList

+ 1 - 1
src/components/HomePage/LeftBar/SearchLists/MediaList/MediaListItem/index.tsx

@@ -22,7 +22,7 @@ const useStyles = makeStyles({
     alignItems: 'center'
   },
   wrapper: {
-    width: '40%',
+    width: '30%',
     maxHeight: '80%',
     position: 'relative',
     display: 'flex',

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

@@ -8,7 +8,7 @@ import { TAllMessages } from '../../../../../typescript/redux/allMessages/types'
 const useStyles = makeStyles({
   container: {
     width: '100%',
-    maxHeight: '830px',
+    maxHeight: '840px',
     overflowY: 'scroll',
   '&::-webkit-scrollbar': {
     width: '0.4em'
@@ -30,15 +30,19 @@ const useStyles = makeStyles({
   },  
 })
 
-const MediaList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
+const MediaList = ({ allMessagesMemo,value }: { allMessagesMemo: TAllMessages,value:string }) => {
   const classes = useStyles()
   const filteredMessagesMemo =  allMessagesMemo.filter(({ type }) => type === 'image')
-  return filteredMessagesMemo.length > 0 ?(
+  return (
+    <>
       <ImageList className={classes.container} cols={3} rowHeight={164}>
         {filteredMessagesMemo.map(({message,createdAt,fullType,updatedAt}) => 
           <MediaListItem key={createdAt} message={message} fullType={fullType} updatedAt={updatedAt}/>)}
       </ImageList>
-   ): <AlertInfo name='You do not have Media yet!'/>  
+      {value &&  filteredMessagesMemo.length === 0 && <AlertInfo name={`Can not find Media by request: ${value}`} />}
+      {!value && filteredMessagesMemo.length === 0 && <AlertInfo name='You do not have Media yet!'/>}
+     </>
+   )
 }
 
 export default MediaList

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

@@ -15,7 +15,7 @@ import { TAllMessages } from '../../../../../typescript/redux/allMessages/types'
 const useStyles = makeStyles({
   container: {
     width: '100%',
-    maxHeight: '860px',
+    maxHeight: '840px',
     overflowY: 'scroll',
   '&::-webkit-scrollbar': {
     width: '0.4em'
@@ -49,10 +49,11 @@ const useStyles = makeStyles({
   },  
 })
 
-const TextList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
+const TextList = ({ allMessagesMemo,value }: { allMessagesMemo: TAllMessages,value: string }) => {
   const classes = useStyles()
   const filteredMessagesMemo =  allMessagesMemo.filter(({type}) => type === 'text')
-   return filteredMessagesMemo.length > 0 ?(
+  return (
+  <>
     <List className={classes.container}>
        {filteredMessagesMemo.map(({ message, createdAt, lastName, name, color, avatarUrl }) =>
       <div key={createdAt}>
@@ -73,7 +74,10 @@ const TextList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
           <Divider variant="inset" />
       </div>)}
     </List>
-   ): <AlertInfo name='You do not have Text yet!'/>  
+    {value &&  filteredMessagesMemo.length === 0 && <AlertInfo name={`Can not find Text by request: ${value}`} />}
+    {!value && filteredMessagesMemo.length === 0 && <AlertInfo name='You do not have Text yet!'/>} 
+  </>
+  ) 
 }
 
 export default TextList

+ 9 - 5
src/components/HomePage/LeftBar/SearchLists/VideoList/index.tsx

@@ -13,7 +13,7 @@ import { TAllMessages } from '../../../../../typescript/redux/allMessages/types'
 const useStyles = makeStyles({
   container: {
     width: '100%',
-    maxHeight: '860px',
+    maxHeight: '840px',
     overflowY: 'scroll',
   '&::-webkit-scrollbar': {
     width: '0.4em'
@@ -46,10 +46,11 @@ const useStyles = makeStyles({
     }
   },  
 })
-const VideoList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
+const VideoList = ({ allMessagesMemo,value }: { allMessagesMemo: TAllMessages,value:string }) => {
   const classes = useStyles()
     const filteredMessagesMemo =  allMessagesMemo.filter(({type}) => type === 'video')
-    return filteredMessagesMemo.length > 0 ?(
+  return (
+    <>
       <List className={classes.container}>
         {filteredMessagesMemo.map(({ message, createdAt, fullType }) =>
           <div key={createdAt}>
@@ -66,8 +67,11 @@ const VideoList = ({ allMessagesMemo }: { allMessagesMemo: TAllMessages }) => {
             </ListItem>
             <Divider variant="inset"/>
         </div>)}
-    </List>
-   ): <AlertInfo name='You do not have Audio yet!'/>  
+      </List>
+      {value &&  filteredMessagesMemo.length === 0 && <AlertInfo name={`Can not find Video by request: ${value}`} />}
+      {!value && filteredMessagesMemo.length === 0 && <AlertInfo name='You do not have Video yet!'/>}
+    </>
+   )  
 }
 
 export default VideoList

+ 22 - 11
src/components/HomePage/LeftBar/SearchLists/index.tsx

@@ -15,9 +15,11 @@ import { asyncGetChats } from '../../../../redux/chats/operations';
 import { getStateMemo } from '../../../../redux/chats/selector';
 import { getAllMessagesMemo } from '../../../../redux/allMessages/selector';
 import { getIsOpen } from '../../../../redux/control/selector';
-import { sortByRecent } from '../../../../helpers';
+import { sortByRecent,handleSort } from '../../../../helpers';
 import { asyncStartChatById } from '../../../../redux/chat/operations';
 import { actionIsOpen } from '../../../../redux/control/action';
+import { TAllMessages } from '../../../../typescript/redux/allMessages/types';
+import { TChats } from '../../../../typescript/redux/chats/types';
 
 
 const useStyles = makeStyles({
@@ -38,14 +40,15 @@ const useStyles = makeStyles({
 
 interface ISearchLists {
   value: string,
-  setValue: (value: string) => void
+  setValue: (value: string) => void,
+  sort: boolean
 }
 
-const SearchLists = ({ value,setValue }: ISearchLists) => {
+const SearchLists = ({ value,setValue,sort }: ISearchLists) => {
     const classes = useStyles()
     const dispatch = useDispatch()
     const { chats } = useSelector(getStateMemo)
-    const allMessagesMemo = useSelector(getAllMessagesMemo)
+    const messagesMemo = useSelector(getAllMessagesMemo)
     const isOpen = useSelector(getIsOpen)
     const [isActive, setIsActive] = useState<number>(0)
     const handleIsActive = (_e: React.SyntheticEvent<Element, Event>, newValue: number): void => {
@@ -58,10 +61,17 @@ const SearchLists = ({ value,setValue }: ISearchLists) => {
       isOpen&&dispatch(actionIsOpen(''))
       dispatch(asyncStartChatById(companionId))
     }
-    const filterAndSort = () => sortByRecent(chats).filter((el) => {
+    const filterChats= (arr:any) => arr.filter((el:any) => {
       const credentials = el.name + ' ' + el.lastName
       if(credentials.toLowerCase().includes(value.toLowerCase())) return el
     })
+  const filterMessages = (arr: any) => arr.filter((el: any) => {
+      if (!el.fullType && el.message.toLowerCase().includes(value.toLowerCase())) {
+        return el
+      } else if (el.fullType&& el.fullType.toLowerCase().includes(value.toLowerCase())) {
+        return el
+      }
+    })  
     useEffect(() => {
       dispatch(asyncGetAllMessages())
       dispatch(asyncGetChats())
@@ -73,7 +83,8 @@ const SearchLists = ({ value,setValue }: ISearchLists) => {
     return () => clearInterval(idInterval);
     }, [dispatch]);
   
-    const filteredAndSorted = filterAndSort()  
+    const filteredAndSorted:TChats = filterChats(sortByRecent(chats,sort))
+    const allMessagesMemo:TAllMessages = filterMessages(handleSort('updatedAt',messagesMemo,sort))
   
     return (
     <>
@@ -92,11 +103,11 @@ const SearchLists = ({ value,setValue }: ISearchLists) => {
         </BottomNavigation>
             {isActive === 0 && <ChatListRecent value={value}
               filteredAndSorted={filteredAndSorted} handleListItemClick={handleListItemClick} />}
-            {isActive === 1 && <FilesList allMessagesMemo={allMessagesMemo}/>}
-            {isActive === 2 && <MediaList allMessagesMemo={allMessagesMemo}/>}
-            {isActive === 3 && <TextList allMessagesMemo={allMessagesMemo}/>}
-            {isActive === 4 && <AudioList allMessagesMemo={allMessagesMemo}/>}
-            {isActive === 5 && <VideoList allMessagesMemo={allMessagesMemo}/>}
+            {isActive === 1 && <FilesList allMessagesMemo={allMessagesMemo} value={value}/>}
+            {isActive === 2 && <MediaList allMessagesMemo={allMessagesMemo} value={value}/>}
+            {isActive === 3 && <TextList allMessagesMemo={allMessagesMemo} value={value}/>}
+            {isActive === 4 && <AudioList allMessagesMemo={allMessagesMemo} value={value}/>}
+            {isActive === 5 && <VideoList allMessagesMemo={allMessagesMemo} value={value}/>}
     </>      
     )
 }

+ 25 - 22
src/components/HomePage/LeftBar/index.tsx

@@ -1,4 +1,5 @@
-import React, { useState, useRef, useEffect } from 'react';
+import { useState, useRef, useEffect } from 'react';
+import { useSelector } from 'react-redux';
 import { createPortal } from 'react-dom';
 
 import Grid from '@mui/material/Grid'
@@ -10,34 +11,36 @@ import MenuBar from './MenuBar'
 import ContactsList from './ContactsList'
 import AddContact from './AddContact'
 import NotDone from '../../reusableComponents/NotDone'
+import { getState } from '../../../redux/authorization/selector'
 
 const LeftBar = () => {
-  const [isOpen, setIsOpen] = useState<boolean>(false)
+  const { sort,nightMode } = useSelector(getState)
+  const [isSearch, setIsSearch] = useState<boolean>(false)
   const [isMenu, setIsMenu] = useState<boolean>(false)
   const [isMenuSm, setIsMenuSm] = useState<boolean>(false);
-  const [iMenu, setIMenu] = useState<number | null>(null)
+  const [selectedIndex, setSelectedIndex] = useState<number | null>(null)
   const [value, setValue] = useState<string>('')
   const modalRoot = useRef<HTMLDivElement|null>(null);
-  const handleFocus = (): void => setIsOpen(true)
+  const handleFocus = (): void => setIsSearch(true)
   const handleClick = (): void => {
-  setValue('')
-  if (iMenu) setIMenu(null)
-  if(!isOpen) return setIsMenu(!isMenu)
-     setIsOpen(false)
+    setValue('')
+    if (selectedIndex) setSelectedIndex(null)
+    if(!isSearch) return setIsMenu(!isMenu)
+    setIsSearch(false)
   }
   const handleSearch = (e: React.ChangeEvent<HTMLInputElement>):void => setValue(e.target.value)
   const handleEnterOpenMenuSm = (): void => {
-  if(!isMenuSm) setIsMenuSm(true)
+    if(!isMenuSm) setIsMenuSm(true)
   }
   const handleLeaveCloseMenuSm = (e: any): void => {
-  if(isMenuSm&&e.pageX > 480) setIsMenuSm(false)
+    if(isMenuSm&&e.pageX > 480) setIsMenuSm(false)
   }
   const handleSelectedMenu = (i: number) => {
-    setIsOpen(true)
+    setIsSearch(true)
     setIsMenu(false)
     setIsMenuSm(false)
     setValue('')
-    setIMenu(i)
+    setSelectedIndex(i)
   }
   
   useEffect(() => {
@@ -64,17 +67,17 @@ const LeftBar = () => {
 
     return (
       <Grid item lg={3} onMouseEnter={handleEnterOpenMenuSm} onMouseLeave={handleLeaveCloseMenuSm}>
-        <SearchBar handleClick={handleClick} handleFocus={handleFocus}
-          handleSearch={handleSearch} isOpen={isOpen} iMenu={iMenu} value={value}/>
-        {!iMenu&&isOpen && <SearchLists value={value} setValue={setValue}/>}
-        {!iMenu&&!isOpen &&<ChatsList/>}
-        {!iMenu && isMenuSm && !isOpen && <SmallMenuBar handleSelectedMenu={handleSelectedMenu}
-          setIsMenuSm={setIsMenuSm} />}
+        <SearchBar handleClick={handleClick} handleFocus={handleFocus} sort={sort}
+          handleSearch={handleSearch} isSearch={isSearch} selectedIndex={selectedIndex} value={value}/>
+        {!selectedIndex&&isSearch && <SearchLists value={value} setValue={setValue} sort={sort}/>}
+        {!selectedIndex&&!isSearch &&<ChatsList sort={sort}/>}
+        {!selectedIndex && isMenuSm && !isSearch && <SmallMenuBar
+          handleSelectedMenu={handleSelectedMenu} setIsMenuSm={setIsMenuSm} />}
         {isMenu && modalRoot.current &&
-          createPortal(<MenuBar handleSelectedMenu={handleSelectedMenu} />, modalRoot.current)}
-        {iMenu === 1 && <ContactsList handleClick={handleClick} value={value}/>}
-        {iMenu === 2 && <NotDone name='Settings' />}
-        {iMenu === 3 && <AddContact setIMenu={setIMenu}/>}
+          createPortal(<MenuBar handleSelectedMenu={handleSelectedMenu} nightMode={nightMode}/>, modalRoot.current)}
+        {selectedIndex === 1 && <ContactsList handleClick={handleClick} value={value} sort={sort}/>}
+        {selectedIndex === 2 && <NotDone name='Settings' />}
+        {selectedIndex === 3 && <AddContact setSelectedIndex={setSelectedIndex}/>}
     </Grid>
     )
 }

+ 1 - 1
src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/CredentialsList/ProfileLists/MediaList/MediaListItem/index.tsx

@@ -22,7 +22,7 @@ const useStyles = makeStyles({
     alignItems: 'center'
   },
   wrapper: {
-    width: '40%',
+    width: '30%',
     maxHeight: '80%',
     position: 'relative',
     display: 'flex',

+ 15 - 3
src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/CredentialsList/ProfileMenu/index.tsx

@@ -9,12 +9,13 @@ import NotificationsIcon from '@mui/icons-material/Notifications';
 import SortIcon from '@mui/icons-material/Sort';
 import Switch from '@mui/material/Switch';
 import Divider from '@mui/material/Divider';
+import AlternateEmailIcon from '@mui/icons-material/AlternateEmail';
 import { CopyToClipboard } from 'react-copy-to-clipboard';
 import { makeStyles } from '@material-ui/core'
 
 import { getChat } from '../../../../../../../redux/chat/selector'
 import { muteChat,sortChat } from '../../../../../../../api-data'
-import { copied } from '../../../../../../../helpers';
+import { copied,firstLetter,slicedWord } from '../../../../../../../helpers';
 
 const useStyles = makeStyles({
     container: {
@@ -32,9 +33,11 @@ const label = { inputProps: { 'aria-label': 'Switch demo' } };
 
 const ProfileMenu = () => {
   const classes = useStyles()
-  const { number, mute,sort,companionId } = useSelector(getChat)
+  const { number, mute,sort,companionId,originalName,originalLastName } = useSelector(getChat)
   const handleMute = () => muteChat(companionId)
   const handleSort = () => sortChat(companionId)
+  const credentials = `${firstLetter(originalName)}${slicedWord(originalName, 15, 1)}
+        ${firstLetter(originalLastName)}${slicedWord(originalLastName, 15, 1)}`
   return (
     <Paper className={classes.container}>
       <MenuList className={classes.list}>
@@ -54,7 +57,7 @@ const ProfileMenu = () => {
           <ListItemText primary='Notification' />
           <Switch style={{ cursor:'pointer'}} onClick={handleMute} {...label} defaultChecked={!mute} />
         </MenuItem>
-        <Divider variant="inset"/>
+        <Divider variant="inset" />
         <MenuItem style={{cursor:'default'}}>
           <ListItemIcon className={classes.listIcon}>
             <SortIcon fontSize="medium" />
@@ -62,6 +65,15 @@ const ProfileMenu = () => {
           <ListItemText primary={`Sort by Date`} />
           <Switch style={{ cursor:'pointer'}} onClick={handleSort} {...label} defaultChecked={sort} />
         </MenuItem>
+        <Divider variant="inset"/>        
+        <CopyToClipboard onCopy={() => copied('Username')} text={credentials}>
+          <MenuItem style={{cursor:'default'}}>
+            <ListItemIcon className={classes.listIcon}>
+               <AlternateEmailIcon fontSize="medium" />
+            </ListItemIcon>
+            <ListItemText primary={credentials} secondary='Username' />
+          </MenuItem>
+        </CopyToClipboard>        
         <Divider/>
       </MenuList>
     </Paper>

+ 14 - 7
src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/CredentialsList/ProfilePicture/index.tsx

@@ -10,28 +10,35 @@ const useStyles = makeStyles({
   imgContainer: {
     position:'relative',
     width: '100%',
-    height: 488,
+    height: 468,
     color: '#ffffff',
     display: 'flex',
     justifyContent: 'center',
     alignContent: 'center',
     alignItems: 'center',
-    fontSize:200,
+    fontSize: 200,
   },
   nameTile: {
     position:'absolute',
     color: '#ffffff',
+    backgroundColor: '#6e6e6e7d',
+    borderRadius: 10,
+    padding:'0px 6px 2px 6px',
     fontWeight:600,
     fontSize: 24,
     zIndex:10,
-    top: 415,
+    top: 395,
     left:35
   },
   timeTile: {
     position:'absolute',
-    color: '#cfcfcf',
-    fontSize: 18,
-    top: 450,
+    color: '#ffffff',
+    backgroundColor:'#6e6e6e7d',
+    borderRadius: 10,
+    padding:'0px 6px 2px 6px',
+    fontSize: 19,
+    fontWeight:600,
+    top: 430,
     left:35
   },    
 })
@@ -41,7 +48,7 @@ const ProfilePicture = () => {
   const  { name,lastName,avatarUrl,online,color }  = useSelector(getChat)
   return (
     <div className={classes.container}>
-      {avatarUrl ? <img className={classes.imgContainer} width='488px' height='488px' alt='avatar'
+      {avatarUrl ? <img className={classes.imgContainer} width='488px' height='468px' alt='avatar'
         src={`http://localhost:3000/${avatarUrl}`}></img> :
         <div className={classes.imgContainer} style={{ background: `linear-gradient(${color} 75%, #4e4e4e)` }}>
         {`${firstLetter(name)}${firstLetter(lastName)}`}</div>}

+ 3 - 3
src/components/HomePage/RightBar/HeaderBar/RightListsAndBars/EditBar/EditList/index.tsx

@@ -56,7 +56,7 @@ interface IEditList {
 const EditList = (props: IEditList) => {
   const classes = useStyles()
   const {chat,name,setName,lastName,setLastName,mute,setMute,openBtn,setOpenBtn} = props
-  const { avatarUrl,color,name:Name,lastName:LastName } = chat
+  const { avatarUrl,color,originalName,originalLastName } = chat
   const handleNotifications = () => {
     setMute(!mute)
     !openBtn&&setOpenBtn(true)
@@ -86,8 +86,8 @@ const EditList = (props: IEditList) => {
          </Avatar>
       </ListItemAvatar>          
       <Typography style={{color: '#080808',fontSize:22,fontWeight:500}}>
-        {`${firstLetter(Name)}${slicedWord(Name, 15, 1)} 
-        ${firstLetter(LastName)}${slicedWord(LastName, 15, 1)}`}
+        {`${firstLetter(originalName)}${slicedWord(originalName, 15, 1)} 
+        ${firstLetter(originalLastName)}${slicedWord(originalLastName, 15, 1)}`}
       </Typography>
       <Typography style={{fontSize:17,marginBottom:20}}>original name</Typography>          
       <TextField

+ 3 - 2
src/helpers/index.ts

@@ -121,12 +121,13 @@ const handleSort = (sortBy: string, data: any,sort:boolean): any => {
     });
 };
 
-const sortByRecent = (chats:TChats) => [...chats].sort((a, b) => {
+const sortByRecent = (chats:TChats,sort:boolean) => [...chats].sort((a, b) => {
   const aCreatedAt = a.lastMessageCreatedAt ? a.lastMessageCreatedAt : a.createdAt
   const bCreatedAt = b.lastMessageCreatedAt ? b.lastMessageCreatedAt : b.createdAt
   const aTime = timeStampEUFilter(aCreatedAt)
   const bTime = timeStampEUFilter(bCreatedAt)
-  return aTime < bTime ? 1 : -1
+  const direction = sort ? aTime < bTime: aTime > bTime
+  return direction ? 1 : -1
 })
 
 

+ 1 - 1
src/redux/authorization/operations/index.ts

@@ -15,7 +15,7 @@ const asyncCreateUser = (name:string, lastName: string,file:object) => async (di
     const formData: any = new FormData()
     formData.append("avatar", file);
     const data = await Promise.all<TResPromiseAll>(
-    [updateUserAvatar(formData), updateCredentials(name, lastName)])
+    [updateUserAvatar(formData), updateCredentials({ name, lastName, originalName:name, originalLastName:lastName})])
     const token = data.find(el => el?.token)?.token
     token&&dispatch(actionLogInSuccess(token))
   } catch (e) {

+ 4 - 0
src/redux/authorization/reducer/index.ts

@@ -12,6 +12,8 @@ import {
 const initialState:IAuthorizationState = {
   name: "",
   lastName: "",
+  originalName: "",
+  originalLastName: "",
   avatarUrl: "",
   color: "",
   code: "",
@@ -20,6 +22,8 @@ const initialState:IAuthorizationState = {
   online: "",
   number: "" ,
   country: "",
+  sort: false,
+  nightMode: false,
   createdAt: "",
   updatedAt: "",
   __v: 0,

+ 3 - 2
src/redux/authorization/selector/index.ts

@@ -6,7 +6,8 @@ const getName = (state: IState) => state.authorization.name;
 const getLastName = (state: IState) => state.authorization.lastName;
 const getCountry = (state: IState) => state.authorization.country;
 const getAvatarUrl = (state: IState) => state.authorization.avatarUrl;
-const getId= (state:IState) => state.authorization._id;
+const getId = (state: IState) => state.authorization._id;
+const getSort= (state:IState) => state.authorization.sort;
 const getState= (state:IState) => state.authorization;
 
-export { getToken,getNumber,getName,getLastName,getCountry,getAvatarUrl,getId,getState };
+export { getToken,getNumber,getName,getLastName,getCountry,getAvatarUrl,getId,getSort,getState };

+ 2 - 0
src/redux/chat/reducer/index.ts

@@ -11,6 +11,8 @@ import {
 const initialState: TChat = {
      name: '',
      lastName: '',
+     originalName: '',
+     originalLastName: '',
      avatarUrl:'',
      color: '',
      online: '',

+ 4 - 0
src/typescript/redux/authorization/interfaces.ts

@@ -2,6 +2,8 @@
 export interface IAuthorizationState  {
   name?: string | null,
   lastName?: string | null,
+  originalName?: string | null,
+  originalLastName?: string | null,
   avatarUrl?: string | null,
   color?: string | null,
   code?: string | null,
@@ -10,6 +12,8 @@ export interface IAuthorizationState  {
   online: string,
   number?: string | null ,
   country?: string | null,
+  sort: boolean,
+  nightMode: boolean,
   createdAt?: string | null,
   updatedAt?: string | null,
   __v?: number | null,

+ 2 - 0
src/typescript/redux/chat/types.ts

@@ -1,6 +1,8 @@
 export type TChat = {
   name: string,
   lastName: string,
+  originalName: string,
+  originalLastName: string,
   avatarUrl:string,
   color: string,
   online: string,

+ 2 - 0
src/typescript/redux/chats/types.ts

@@ -1,6 +1,8 @@
 export type TChat = {
   name: string,
   lastName: string,
+  originalName: string,
+  originalLastName: string,
   avatarUrl:string,
   color: string,
   online: string,