Преглед на файлове

finishe status online and mute ability

unknown преди 3 години
родител
ревизия
40a3641ffb

Файловите разлики са ограничени, защото са твърде много
+ 1 - 1
.eslintcache


+ 1 - 1
src/App.tsx

@@ -43,7 +43,7 @@ function App() {
     const handleKeepIn = async () => {
       if (localStorage.isChecked === 'false') {
         dispatch(asyncLogout())
-      } else if(localStorage.isChecked === 'false') {
+      } else if(localStorage.isChecked === 'true') {
         await onlineUser()
       }
     }

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

@@ -133,6 +133,25 @@ const startChat = async <T>(id:string): Promise<T | undefined> => {
   }
 };
 
+const getChat = async <T>(id:string): Promise<T | undefined> => {
+  try {
+    const { data: { data } } = await axios.get(`/chats/${id}`);
+    return data
+  } catch (e) {
+    return undefined
+  }
+};
+
+const muteChat = async <T>(id:string): Promise<T | undefined> => {
+  try {
+    const { data: { data } } = await axios.post('/chats/mute', {id});
+    success(`MUTE`);
+    return data
+  } catch (e) {
+    return undefined
+  }
+};
+
 const getChats = async <T>(): Promise<T | undefined> => {
   try {
     const { data: { data } } = await axios.get('/chats');
@@ -174,6 +193,8 @@ export {
   addContact,
   getContacts,
   startChat,
+  getChat,
+  muteChat,
   getChats,
   sentMessageById,
   getMessagesById

+ 42 - 11
src/components/HomePage/LeftBar/ChatsList/index.tsx

@@ -5,6 +5,7 @@ import ListItemText from '@mui/material/ListItemText';
 import ListItemIcon from '@mui/material/ListItemIcon';
 import { styled } from '@mui/material/styles';
 import Badge from '@mui/material/Badge';
+import VolumeOffIcon from '@mui/icons-material/VolumeOff';
 import { makeStyles, Typography } from '@material-ui/core'
 import { useState,useEffect } from 'react';
 import shortid from 'shortid';
@@ -69,7 +70,16 @@ const useStyles = makeStyles({
     backgroundColor: "#959595",
     },
   },
-  listItem: {},
+  listItemInnerText: {
+    display: 'flex',
+    alignContent: 'center',
+    alignItems: 'center',
+    flexWrap: 'nowrap',
+  },
+  listItemInnerText__icon: {
+    marginLeft: 5,
+    color: '#959595',
+  },
   listItem_iconAvatar: {
     marginRight:10
   },
@@ -106,6 +116,24 @@ const useStyles = makeStyles({
     '&:hover': {
       outline: 'solid 3px #3ee415',
     }
+  },
+    listItem_iconRightBtnMute: {
+    background: '#a7aaa7',
+    borderRadius: '50%',
+    color: '#ffffff',
+    border: 'none',
+    height: 24,
+    width: 24,
+    textAlign: 'center',
+    display: 'flex',
+    alignItems: 'center',
+    justifyContent: 'center',
+    alignContent: 'center',
+    fontSize: 12,
+    marginLeft: 'auto',
+    '&:hover': {
+      outline: 'solid 3px #cccbcb',
+    }
   },
   listItem_iconRightBtnHidden: {
     background: 'inherit',
@@ -132,7 +160,7 @@ const ChatsList = () => {
   const classes = useStyles()
   const dispatch = useDispatch()
   const [selectedIndex, setSelectedIndex] = useState<number>(1);
-  const { total, chats , lastMessages } = useSelector(getState)
+  const { total, chats , lastMessages,lastOnline } = useSelector(getState)
  
 
   const handleListItemClick = async (i: number, companionId: string) => {
@@ -154,19 +182,19 @@ const ChatsList = () => {
   useEffect(() => {
     dispatch(asyncGetChats())
   }, [dispatch])
-  
+
+
   return total !== '0' ? (
     <List className={classes.list} component="nav"
           aria-label="main mailbox folders">
-      {chats.map(({name, lastName, avatarUrl, updatedAt, color,companionId,online }, i: number) => 
+      {chats.map(({name, lastName, avatarUrl, updatedAt, color,companionId,mute }, i: number) => 
           <ListItemButton
-          className={classes.listItem}
           key={shortid.generate()}
           selected={selectedIndex === i}
-          onClick={(e) => handleListItemClick(i,companionId)}
+          onClick={() => handleListItemClick(i,companionId)}
           >
           <ListItemIcon className={classes.listItem_iconAvatar}>
-            <StyledBadge overlap="circular"  variant={online === 'true'?'dot':'standard'}
+            <StyledBadge overlap="circular"  variant={lastOnline[i].online === 'true'?'dot':'standard'}
                   anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}>
                  <Avatar alt={name} src={avatarUrl?`http://localhost:3000/${avatarUrl}`:undefined}
                      sx={{ background: color, width: 54, height: 54 }}>
@@ -174,18 +202,21 @@ const ChatsList = () => {
                   </Avatar>
               </StyledBadge>
           </ListItemIcon> 
-          <ListItemText primary={`${firstLetter(name)}${slicedWord(name, 15, 1)} 
-             ${firstLetter(lastName)}${slicedWord(lastName, 15, 1)}`}
+          <ListItemText primary={<div className={classes.listItemInnerText}>
+            <span>{`${firstLetter(name)}${slicedWord(name, 15, 1)} 
+             ${firstLetter(lastName)}${slicedWord(lastName, 15, 1)}`}</span>
+            {mute&&<VolumeOffIcon className={classes.listItemInnerText__icon} fontSize='small' />}</div>}
              secondary={lastMessages[i] ? slicedWord(lastMessages[i].message, 35) :
              `${firstLetter(name)}${slicedWord(name, 8, 1)} joined Telegram`} />
           <ListItemIcon className={classes.listItem_iconRight}>
                <div className={classes.listItem_iconTimeChecked}>
                  <img alt='double check' width="16" height='16' src={doubleCheck} />
               <Typography className={classes.listItem_icon_time} variant="h6" color="initial">
-                {timeStamp(updatedAt)}</Typography>
+                {lastMessages[i] ? timeStamp(lastMessages[i].updatedAt) :
+                timeStamp(updatedAt)}</Typography>
                </div>
             {lastMessages[i] ? <button onClick={(e) => handleNewMsgS(e, i)}
-              className={classes.listItem_iconRightBtn}>0</button> :
+              className={mute?classes.listItem_iconRightBtnMute:classes.listItem_iconRightBtn}>0</button> :
               <button  className={classes.listItem_iconRightBtnHidden}/>}
           </ListItemIcon>            
         </ListItemButton>)}

+ 9 - 4
src/components/HomePage/RightBar/HeaderBar/Buttons/MenuList/index.tsx

@@ -1,15 +1,18 @@
 import { useState } from 'react';
-import { useDispatch } from 'react-redux';
+import { useDispatch,useSelector } from 'react-redux';
 import { styled } from '@mui/material/styles';
 import IconButton from '@mui/material/IconButton';
 import Menu from '@mui/material/Menu';
 import MenuItem from '@mui/material/MenuItem';
+import NotificationsNoneIcon from '@mui/icons-material/NotificationsNone';
 import VolumeOffIcon from '@mui/icons-material/VolumeOff';
 import CheckBoxIcon from '@mui/icons-material/CheckBox';
 import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
 import MoreVertIcon from '@mui/icons-material/MoreVert';
 
 import { actionIsOpen } from '../../../../../../redux/control/action'
+import { getChat } from '../../../../../../redux/chat/selector'
+import { muteChat } from '../../../../../../api-data'
 
 const StyledMenu = styled((props:any) => (
   <Menu
@@ -52,6 +55,7 @@ const MenuList = () => {
   const dispatch = useDispatch()
   const [anchorEl, setAnchorEl] = useState<any>(null);
   const open = Boolean(anchorEl);
+  const { companionId,mute } = useSelector(getChat)
   const handleClick = (e: React.MouseEvent<HTMLButtonElement>): void => {
     dispatch(actionIsOpen('menu'))
     setAnchorEl(e.currentTarget)
@@ -59,6 +63,7 @@ const MenuList = () => {
 
   const handleClose = (i:number|undefined):void => {
     console.log('chosen one element from small menu by id', i)
+    if(i === 0) muteChat(companionId)
     dispatch(actionIsOpen(''))
     setAnchorEl(null)
   }
@@ -75,9 +80,9 @@ const MenuList = () => {
         open={open}
         onClose={handleClose}
       >
-        <MenuItem onClick={() =>  handleClose(0)}>
-            <VolumeOffIcon />
-            Mute
+        <MenuItem onClick={() => handleClose(0)}>
+          {mute ? <NotificationsNoneIcon /> : <VolumeOffIcon />}
+          {mute ? 'Unmute':'Mute'}
           </MenuItem>
         <MenuItem onClick={() =>  handleClose(1)}>
             <CheckBoxIcon/>

+ 9 - 2
src/components/HomePage/RightBar/HeaderBar/Credentials/index.tsx

@@ -2,15 +2,22 @@ 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 { useDispatch,useSelector } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
+import { useEffect } from 'react';
 
 import { actionIsOpen } from '../../../../../redux/control/action'
 import { getChat } from '../../../../../redux/chat/selector'
+import { asyncGetChatById } from '../../../../../redux/chat/operations'
 import { firstLetter,slicedWord,timeStamp } from '../../../../../helpers'
 
 const Credentials = () => {
   const dispatch = useDispatch()
-  const { name, lastName, avatarUrl, color, online } = useSelector(getChat)
+  const { name, lastName, avatarUrl, color, online, companionId } = useSelector(getChat)
+    useEffect(() => {
+    const handleReset = () => companionId&&dispatch(asyncGetChatById(companionId))
+    const idInterval = setInterval(handleReset, 3000);
+    return () => clearInterval(idInterval);
+  }, [dispatch, companionId]);
   return (
     <ListItemButton onClick={() => dispatch(actionIsOpen('credentials'))}>
       <ListItemIcon >

+ 4 - 2
src/components/HomePage/RightBar/HeaderBar/RightLists/CredentialsList/ProfileMenu/index.tsx

@@ -10,6 +10,7 @@ import Switch from '@mui/material/Switch';
 import { makeStyles } from '@material-ui/core'
 
 import { getChat } from '../../../../../../../redux/chat/selector'
+import { muteChat } from '../../../../../../../api-data'
 
 const useStyles = makeStyles({
     container: {
@@ -28,7 +29,8 @@ const label = { inputProps: { 'aria-label': 'Switch demo' } };
 
 const ProfileMenu = () => {
   const classes = useStyles()
-  const { number } = useSelector(getChat)
+  const { number, mute, companionId } = useSelector(getChat)
+  const handleMute = () => muteChat(companionId)
   return (
     <Paper className={classes.container}>
       <MenuList className={classes.list}>
@@ -43,7 +45,7 @@ const ProfileMenu = () => {
             <NotificationsIcon fontSize="medium" />
           </ListItemIcon>
           <ListItemText primary='Notification' />
-          <Switch {...label} defaultChecked />
+          <Switch onClick={handleMute} {...label} defaultChecked={!mute} />
         </MenuItem>
       </MenuList>
     </Paper>

+ 5 - 1
src/redux/chat/action/index.ts

@@ -4,8 +4,12 @@ import { TChat } from '../../../typescript/redux/chat/types'
 const actionSelectChat = createAction('selectChat/success', (value:TChat) => ({
   payload: value,
 }));
+const actionGetChat = createAction('getChat/success', (value:TChat) => ({
+  payload: value,
+}));
 
 
 export {
-  actionSelectChat
+  actionSelectChat,
+  actionGetChat
 };

+ 12 - 3
src/redux/chat/operations/index.ts

@@ -1,8 +1,9 @@
 import { actionIsLoading } from '../../loading/action';
 import {
-   actionSelectChat
+  actionSelectChat,
+  actionGetChat
 } from '../action';
-import { startChat} from '../../../api-data';
+import { startChat,getChat } from '../../../api-data';
 
 import { TChat } from '../../../typescript/redux/chat/types'
 
@@ -16,8 +17,16 @@ const asyncStartChatById = (id:string) => async (dispatch:any) => {
   }
 };
 
+const asyncGetChatById = (id:string) => async (dispatch:any) => {
+  try {
+    const data = await getChat<TChat>(id)
+    data&&dispatch(actionGetChat(data))
+  } catch(e) {}
+};
+
+
 
-export { asyncStartChatById };
+export { asyncStartChatById,asyncGetChatById };
 
 
 

+ 6 - 1
src/redux/chat/reducer/index.ts

@@ -2,7 +2,8 @@ import { createReducer } from '@reduxjs/toolkit';
 import { IChatPayload,IChatState } from '../../../typescript/redux/chat/interfaces';
 
 import {
-  actionSelectChat
+  actionSelectChat,
+  actionGetChat
 } from '../action';
 
 const initialState: IChatState = {
@@ -12,6 +13,7 @@ const initialState: IChatState = {
      avatarUrl:'',
      color: '',
      online: '',
+     mute: false,
      number:'',
      _id: '',
      companionId: '',
@@ -28,6 +30,9 @@ const reducerChat = createReducer(initialState, {
   [actionSelectChat.type]: (_,{ payload:chat }:IChatPayload) => {
     return {chat}
   },
+  [actionGetChat.type]: (_,{ payload:chat }:IChatPayload) => {
+    return {chat}
+  },  
 });
 
 export default reducerChat;

+ 2 - 1
src/redux/chats/reducer/index.ts

@@ -11,7 +11,8 @@ const initialState: IChatsState = {
   limit: "0",
   page: "0",
   chats: [],
-  lastMessages: []
+  lastMessages: [],
+  lastOnline: [],
 }
 
 

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

@@ -4,6 +4,7 @@ export type TChat = {
   avatarUrl:string,
   color: string,
   online: string,
+  mute: boolean,
   number:string,
   _id: string,
   companionId: string,

+ 7 - 4
src/typescript/redux/chats/interfaces.ts

@@ -1,11 +1,12 @@
-import { TChats,TLastMessages } from './types'
+import { TChats,TLastMessages, TLastOnlineArr } from './types'
 
 export interface IChatsState  {
   total: string,
   limit: string,
   page: string,
   chats: TChats,
-  lastMessages: TLastMessages
+  lastMessages: TLastMessages,
+  lastOnline: TLastOnlineArr
 }
 
 export interface IChatsPayload {
@@ -14,7 +15,8 @@ export interface IChatsPayload {
   limit: string,
   page: string,
   chats: TChats,
-  lastMessages: TLastMessages
+  lastMessages: TLastMessages,
+  lastOnline: TLastOnlineArr
   },
 }
 
@@ -23,7 +25,8 @@ export interface IChatsRes  {
   limit: string,
   page: string,
   chats: TChats,
-  lastMessages: TLastMessages
+  lastMessages: TLastMessages,
+  lastOnline: TLastOnlineArr
 }
 
 

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

@@ -4,6 +4,7 @@ export type TChat = {
   avatarUrl:string,
   color: string,
   online: string,
+  mute: boolean,
   number:string,
   _id: string,
   companionId: string,
@@ -18,10 +19,20 @@ export type TChats = TChat[] | []
 export type TLastMessage = {
   message: string,
   companionId: string,
+  createdAt: string,
+  updatedAt: string,
 }
 
 export type TLastMessages = TLastMessage[] | []
 
+export type TLastOnline = {
+  _id: string,
+  online: string,
+  updatedAt: string,
+}
+
+export type TLastOnlineArr = TLastOnline[] | []
+