Browse Source

done upload images into chat

unknown 2 years ago
parent
commit
339bb330b6

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


+ 3 - 1
src/App.tsx

@@ -32,7 +32,9 @@ function App() {
   const token = useSelector(getToken)
   const { companionId } = useSelector(getChat)
   const dispatch = useDispatch()
-  const handleTypingClose = async () => await typingChat(companionId,false)
+  const handleTypingClose = async () => {
+    companionId&& await typingChat(companionId, false)
+  }
 
   useEffect(() => {
     if(!localStorage.isChecked) localStorage.isChecked = 'true'

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

@@ -52,7 +52,7 @@ const authorizeUser = async (number:string,country:string):Promise<string | unde
 
 const loginUser = async <T>(number:string,code:string):Promise<T | undefined> => {
   try {
-    const { data : {data} } = await axios.post('/auth/login', { number,code });
+    const { data : {data} } = await axios.patch('/auth/login', { number,code });
     return data
   } catch (e) {
     return undefined
@@ -61,7 +61,7 @@ const loginUser = async <T>(number:string,code:string):Promise<T | undefined> =>
 
 const logoutUser = async <T>():Promise<T | undefined> => {
   try {
-    const { data } = await axios.post('/auth/logout');
+    const { data } = await axios.patch('/auth/logout');
     return data
   } catch (e) {
     forbidden(e)
@@ -71,7 +71,7 @@ const logoutUser = async <T>():Promise<T | undefined> => {
 
 const onlineUser = async <T>():Promise<T | undefined> => {
   try {
-    const { data } = await axios.post('/auth/online');
+    const { data } = await axios.patch('/auth/online');
     return data
   } catch (e) {
     forbidden(e)
@@ -129,9 +129,9 @@ const getContacts = async <T>(): Promise<T | undefined> => {
   }
 };
 
-const startChat = async <T>(id:string): Promise<T | undefined> => {
+const getChat = async <T>(id:string): Promise<T | undefined> => {
   try {
-    const { data : {data} } = await axios.post('/chats',{id});
+    const { data: { data } } = await axios.get(`/chats/${id}`);
     return data
   } catch (e) {
     forbidden(e)
@@ -139,9 +139,9 @@ const startChat = async <T>(id:string): Promise<T | undefined> => {
   }
 };
 
-const getChat = async <T>(id:string): Promise<T | undefined> => {
+const startChat = async <T>(id:string): Promise<T | undefined> => {
   try {
-    const { data: { data } } = await axios.get(`/chats/${id}`);
+    const { data : {data} } = await axios.post('/chats',{id});
     return data
   } catch (e) {
     forbidden(e)
@@ -151,7 +151,7 @@ const getChat = async <T>(id:string): Promise<T | undefined> => {
 
 const muteChat = async <T>(id:string): Promise<T | undefined> => {
   try {
-    const { data: { data } } = await axios.post('/chats/mute', {id});
+    const { data: { data } } = await axios.patch('/chats/mute', {id});
     return data
   } catch (e) {
     forbidden(e)
@@ -161,7 +161,7 @@ const muteChat = async <T>(id:string): Promise<T | undefined> => {
 
 const seenChat = async <T>(id:string): Promise<T | undefined> => {
   try {
-    const { data: { data } } = await axios.post('/chats/seen', { id });
+    const { data: { data } } = await axios.patch('/chats/seen', { id });
     return data
   } catch (e) {
     forbidden(e)
@@ -171,7 +171,7 @@ const seenChat = async <T>(id:string): Promise<T | undefined> => {
 
 const typingChat = async <T>(id:string,typing:boolean): Promise<T | undefined> => {
   try {
-    const { data: { data } } = await axios.post('/chats/typing', { id,typing});
+    const { data: { data } } = await axios.patch('/chats/typing', { id,typing});
     return data
   } catch (e) {
     forbidden(e)
@@ -199,6 +199,16 @@ const sentMessageById = async <T>(id:string,message:any): Promise<T | undefined>
   }
 };
 
+const sentImgMessageById = async <T>(id:string,formData: object): Promise<T | undefined> => {
+  try {
+    const { data: { data } } = await axios.post(`/messages/img/${id}`, formData);
+    return data
+  } catch (e) {
+    forbidden(e)
+    return undefined
+  }
+};
+
 const getMessagesById = async <T>(id:string): Promise<T | undefined> => {
   try {
     const { data : {data} } = await axios.get(`/messages/${id}`);
@@ -229,5 +239,6 @@ export {
   typingChat,
   getChats,
   sentMessageById,
+  sentImgMessageById,
   getMessagesById
 };

+ 3 - 10
src/components/AuthPage/Authorization/index.tsx

@@ -54,6 +54,7 @@ interface IAuthorizationForm {
   country: string,
   setCountry: React.Dispatch<React.SetStateAction<string>>,
   isChecked: boolean,
+  isValidCredentials: () => boolean
 }
 
 interface ICountry {
@@ -70,18 +71,10 @@ const Authorization = ({
   country,
   setCountry,
   isChecked,
+  isValidCredentials
 }: IAuthorizationForm) => {
   const classes = useStyles()
 
-    const isValidCredentials = () => {
-    const numberLength = number.split(' ').join('').trim().length
-    if (numberLength < 13 || numberLength > 13) return false
-    if (!country || country === 'Country') return false
-    if(number.slice(0,1) === '+') return true
-    return true
-  }
-
-
   const handleTextField = (e: React.ChangeEvent<HTMLInputElement>) => {
     const value = e.target.value
     const name = e.target.name
@@ -100,7 +93,7 @@ const Authorization = ({
   }
 
   return (
-    <div className={classes.container} >
+    <div className={classes.container}>
       <img className={classes.picture} alt="QRCode" src={qrCode} width='270' height='270' />
       <h2 className={classes.title}>Telegram</h2>
       <h4 className={classes.title + ' ' + classes.titleConfirm}>

+ 20 - 17
src/components/AuthPage/index.tsx

@@ -7,7 +7,6 @@ import SMSCode from './SMSCode'
 import Registration from './Registration'
 import { authorizeUser } from '../../api-data'
 import { asyncLogin } from '../../redux/authorization/operations'
-import { actionIsLoading } from '../../redux/loading/action'
 import { format } from '../../helpers'
 
 const AuthPage = () => {
@@ -20,27 +19,26 @@ const AuthPage = () => {
 
   const dispatch = useDispatch()
 
-  useEffect(() => {
-    const isCheckedLC = localStorage.isChecked
-    isCheckedLC && setIsChecked(isCheckedLC === 'true'?true:false)
-  }, [])
-
   const handleIsQR = (): void => setIsQR(!isQR)
 
-  const handleSendCode = async (): Promise<void> => {
-    try {
-      dispatch(actionIsLoading(true))
-      const res = await authorizeUser(format(number), country)
-      res && setIsCode(res)
-    }  finally {
-      dispatch(actionIsLoading(false))
-    }
+  const isValidCredentials = () => {
+    const numberLength = number.split(' ').join('').trim().length
+     if (numberLength < 13 || numberLength > 13) return false
+     if (!country || country === 'Country') return false
+     if(number.slice(0,1) === '+') return true
+      return true
   }
 
   const handleIsValidCode = async (e: React.ChangeEvent<HTMLInputElement>):Promise<void> => {
     if (isCode && format(e.target.value) === isCode) 
       dispatch(await asyncLogin(number, isCode, () => setIsReg(!isReg)))
-    }
+    }  
+
+  const handleSendCode = async () => {
+      const res = await authorizeUser(format(number), country)
+      res && setIsCode(res)
+  }
+
   const handleIsCheck = (e: React.ChangeEvent<HTMLInputElement>): void => {
     const flag = e.target.checked
     setIsChecked(flag);
@@ -52,8 +50,12 @@ const AuthPage = () => {
     setCountry('Country')
     setNumber('')
   }
+
+  useEffect(() => {
+    const isCheckedLC = localStorage.isChecked
+    isCheckedLC && setIsChecked(isCheckedLC === 'true'?true:false)
+  }, [])
   
- 
   return (
     isReg?<Registration/>:
     isCode ? <SMSCode
@@ -68,7 +70,8 @@ const AuthPage = () => {
           number={number}
           country={country}
           setCountry={setCountry}
-          isChecked={isChecked} />
+          isChecked={isChecked}
+          isValidCredentials={isValidCredentials}/>
   )
 };
 

+ 54 - 0
src/components/HomePage/RightBar/ChatBar/Messages/MessageLeftImage/index.tsx

@@ -0,0 +1,54 @@
+import { makeStyles } from "@material-ui/core/styles";
+
+import { timeStamp } from '../../../../../../helpers'
+
+const useStyles = makeStyles({
+    container: {
+      display: "flex",
+      justifyContent: "flex-start",
+      width:'auto',
+      maxWidth: '80%',
+      marginBottom:15
+  },
+  imageWrapper: {
+    width: 300,
+    position:'relative'
+  },
+    image: {
+      borderRadius: 10,
+      width: 300,
+      maxHeight: 400,
+    },  
+    time: {
+      position: "absolute",
+      fontSize: ".65em",
+      fontWeight:600,
+      bottom: -4,
+      right: -4,
+      color: '#ffffff',
+      backgroundColor: '#3a3a3a',
+      padding: 3,
+      borderRadius:5
+    },
+});
+
+interface IMessagesLeftImage {
+  imgUrl:string,
+  updatedAt:string,
+  color:string
+}
+
+const MessagesLeftImage = ({imgUrl,updatedAt,color}:IMessagesLeftImage) => {
+  const classes = useStyles();
+
+  return (
+    <div className={classes.container}>
+      <div className={classes.imageWrapper}>
+        <img className={classes.image} alt='message pic' src={`http://localhost:3000/${imgUrl}`}
+        style={{ backgroundColor: imgUrl?'':color }} width='300' height='400' />
+        <div className={classes.time}>{timeStamp(updatedAt)}</div>
+      </div>
+    </div>    
+)};
+
+export  default  MessagesLeftImage

+ 3 - 3
src/components/HomePage/RightBar/ChatBar/Messages/MessageLeft/index.tsx

@@ -62,7 +62,7 @@ const useStyles = makeStyles({
 });
 
 
-interface IMessageLeft {
+interface IMessageLeftText {
   message:string,
   avatarUrl:string,
   name:string,
@@ -71,7 +71,7 @@ interface IMessageLeft {
   color:string
 }
 
-const MessageLeft = ({message,avatarUrl,name,lastName,updatedAt,color}:IMessageLeft) => {
+const MessageLeftText = ({message,avatarUrl,name,lastName,updatedAt,color}:IMessageLeftText) => {
   const classes = useStyles();
   return (
   <div className={classes.container}>
@@ -93,4 +93,4 @@ const MessageLeft = ({message,avatarUrl,name,lastName,updatedAt,color}:IMessageL
   );
 };
 
-export default MessageLeft
+export default MessageLeftText

+ 54 - 0
src/components/HomePage/RightBar/ChatBar/Messages/MessagesRightImage/index.tsx

@@ -0,0 +1,54 @@
+import { makeStyles } from "@material-ui/core/styles";
+
+import { timeStamp } from '../../../../../../helpers'
+
+const useStyles = makeStyles({
+    container: {
+      display: "flex",
+      justifyContent: "flex-end",
+      width:'auto',
+      maxWidth: '80%',
+      marginBottom:15
+  },
+  imageWrapper: {
+    width: 300,
+    position:'relative'
+  },
+    image: {
+      borderRadius: 10,
+      width: 300,
+      maxHeight: 400,
+    },  
+    time: {
+      position: "absolute",
+      fontSize: ".65em",
+      fontWeight:600,
+      bottom: -4,
+      right: -4,
+      color: '#ffffff',
+      backgroundColor: '#3a3a3a',
+      padding: 3,
+      borderRadius:5
+    },
+});
+
+interface IMessagesRightImage {
+  imgUrl:string,
+  updatedAt:string,
+  color:string
+}
+
+const MessagesRightImage = ({imgUrl,updatedAt,color}:IMessagesRightImage) => {
+  const classes = useStyles();
+
+  return (
+    <div className={classes.container}>
+      <div className={classes.imageWrapper}>
+        <img className={classes.image} alt='message pic' src={`http://localhost:3000/${imgUrl}`}
+        style={{ backgroundColor: imgUrl?'':color }} width='300' height='400' />
+        <div className={classes.time}>{timeStamp(updatedAt)}</div>
+      </div>
+    </div>    
+)};
+
+export  default  MessagesRightImage

+ 3 - 5
src/components/HomePage/RightBar/ChatBar/Messages/MessagesRight/index.tsx

@@ -62,7 +62,7 @@ const useStyles = makeStyles({
     },
 });
 
-interface IMessageRight {
+interface MessagesRightText {
   message:string,
   avatarUrl:string,
   name:string,
@@ -71,7 +71,7 @@ interface IMessageRight {
   color:string
 }
 
-const MessageRight = ({message,avatarUrl,name,lastName,updatedAt,color}:IMessageRight) => {
+const MessagesRightText = ({message,avatarUrl,name,lastName,updatedAt,color}:MessagesRightText) => {
   const classes = useStyles();
 
   return (
@@ -93,6 +93,4 @@ const MessageRight = ({message,avatarUrl,name,lastName,updatedAt,color}:IMessage
   </div>    
 )};
 
-
-
-export  default  MessageRight
+export  default  MessagesRightText

+ 18 - 6
src/components/HomePage/RightBar/ChatBar/SendMessage/index.tsx

@@ -7,11 +7,11 @@ import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
 import Avatar from '@mui/material/Avatar';
 import CloseIcon from '@mui/icons-material/Close';
 import { useState } from "react";
-import { useSelector, useDispatch } from "react-redux";
+import { useSelector } from "react-redux";
 
 import FilesMenu from "../FilesMenu";
 import NotDone from "../../../../reusableComponents/NotDone";
-import { asyncSentMessageById } from '../../../../../redux/messages/operations'
+import { sentMessageById,sentImgMessageById } from '../../../../../api-data'
 import { getChat } from '../../../../../redux/chat/selector'
 import { playNotification } from "../../../../../helpers";
 import { typingChat } from "../../../../../api-data";
@@ -141,19 +141,31 @@ interface ISendMessage{
 
 const SendMessage = ({isArrow,handleScrollTo}:ISendMessage) => {
     const classes = useStyles();
-    const dispatch = useDispatch()
     const { companionId } = useSelector(getChat)
     const [value, setValue] = useState<string>('')
     const [file, setFile] = useState<any>(null)
     const [isOpenMenu, setIsOpenMenu] = useState<boolean>(false)
     const [isOpenEmoji, setIsOpenEmoji] = useState<boolean>(false)
-    const sentMessage = () => {
-        const message = value ? value : file.path;
+    const sentMessage = async () => {
         setValue('')
         setFile(null)
         isOpenMenu&&setIsOpenMenu(false)
         isOpenEmoji && setIsOpenEmoji(false)
-        dispatch(asyncSentMessageById(companionId, message))
+        if (value) sentMessageById(companionId, value)
+        if (file && file.type) {
+            if (file.type === 'image/png' || file.type === 'image/jpeg') {
+              const formData: any = new FormData()
+              formData.append("img", file);
+              console.log('image')
+              await sentImgMessageById(companionId, formData)
+            }
+            if (file.type === 'audio/mpeg') {
+                console.log('mp3')
+            }
+            if (file.type === 'video/mp4') {
+                console.log('mp4')
+            }
+        }
         setTimeout(handleScrollTo, 3000);
         playNotification('http://localhost:3000/send.mp3')
     }    

+ 27 - 9
src/components/HomePage/RightBar/ChatBar/index.tsx

@@ -4,8 +4,10 @@ import { useSelector,useDispatch } from "react-redux";
 import shortid from 'shortid';
 
 import SendMessage from "./SendMessage";
-import MessageLeft from './Messages/MessageLeft'
-import MessageRight from './Messages/MessagesRight'
+import MessageLeftText from './Messages/MessageLeftText'
+import MessageLeftImage from './Messages/MessageLeftImage'
+import MessagesRightText from './Messages/MessagesRightText'
+import MessagesRightImage from './Messages/MessagesRightImage'
 import AlertInfo from "../../../reusableComponents/AlertInfo";
 import { getMessages } from '../../../../redux/messages/selector'
 import { getNumber } from '../../../../redux/authorization/selector'
@@ -76,10 +78,10 @@ const ChatBar = () => {
   return (
       <div ref={divRef} className={classes.container} onScroll={debouncedHandleScroll}>
         <div  className={classes.messagesBody}>
-        {messages.length > 0 ? messages.map(({message,avatarUrl,name,lastName,color,updatedAt,number},i:number) => {
+        {messages.length > 0 ? messages.map(({message,avatarUrl,name,lastName,color,updatedAt,number,type}) => {
           if (number !== userNumber) {
-            return (
-            <MessageLeft
+            if(type === 'text') return (
+            <MessageLeftText
             key={shortid.generate()}
             message={message}
             updatedAt={updatedAt}
@@ -87,10 +89,17 @@ const ChatBar = () => {
             name={name}
             lastName={lastName}
             color={color}
-          />)
+              />)
+            if(type === 'image') return (
+            <MessageLeftImage
+            key={shortid.generate()}    
+            imgUrl={message}
+            updatedAt={updatedAt}
+            color={color} 
+          />)            
           } else {
-            return (
-            <MessageRight
+            if(type === 'text') return (
+            <MessagesRightText
             key={shortid.generate()}    
             message={message}
             updatedAt={updatedAt}
@@ -98,7 +107,16 @@ const ChatBar = () => {
             name={name}
             lastName={lastName}
             color={color}    
-          />)}}):<AlertInfo name='You do not have messages yet!' />}
+              />)
+            if(type === 'image') return (
+            <MessagesRightImage
+            key={shortid.generate()}    
+            imgUrl={message}
+            updatedAt={updatedAt}
+            color={color}    
+              />)            
+          }
+        }) : <AlertInfo name='You do not have messages yet!' />}
       </div>         
       <SendMessage isArrow={isArrow} handleScrollTo={handleScrollTo}/>   
       </div>

+ 3 - 13
src/redux/authorization/operations/index.ts

@@ -1,4 +1,3 @@
-import { actionIsLoading } from '../../loading/action';
 import {
   actionLogInSuccess,
   actionLogInReject,
@@ -13,7 +12,6 @@ import { TResPromiseAll } from '../../../typescript/redux/authorization/types'
 
 const asyncCreateUser = (name:string, lastName: string,file:object) => async (dispatch:any) => {
   try {
-    dispatch(actionIsLoading(true));
     const formData: any = new FormData()
     formData.append("avatar", file);
     const data = await Promise.all<TResPromiseAll>(
@@ -22,14 +20,11 @@ const asyncCreateUser = (name:string, lastName: string,file:object) => async (di
     token&&dispatch(actionLogInSuccess(token))
   } catch (e) {
     dispatch(actionLogInReject())
-  } finally {
-    dispatch(actionIsLoading(false));
-  }
+  } 
 };
 
 const asyncLogin = (number:string, code: string,cb:() => void ) => async (dispatch:any) => {
   try {
-    dispatch(actionIsLoading(true));
     const data = await loginUser<{ token: string, registered: boolean }>(number, code);
     const token = data?.token
     const registered = data?.registered
@@ -40,9 +35,7 @@ const asyncLogin = (number:string, code: string,cb:() => void ) => async (dispat
   } catch (e) {
     dispatch(actionLogInReject());
     cb()
-  } finally {
-    dispatch(actionIsLoading(false));
-  }
+  } 
 };
 
 const asyncLogout = () => async (dispatch:any) => {
@@ -59,15 +52,12 @@ const asyncLogout = () => async (dispatch:any) => {
 
 const asyncCurrentUser = () => async (dispatch:any) => {
   try {
-    dispatch(actionIsLoading(true));
     const data = await currentUser<IAuthorizationState>()
     data && dispatch(actionCurrentSuccess(data));
     if(!data?.token) throw new Error('old token')
   } catch (e) {
     dispatch(actionCurrentReject());
-  } finally {
-    dispatch(actionIsLoading(false));
-  }
+  } 
 };
 
 export { asyncCreateUser, asyncLogin, asyncLogout, asyncCurrentUser };

+ 2 - 7
src/redux/messages/operations/index.ts

@@ -2,7 +2,7 @@ import {
   actionGetMessagesSuccess,
   actionGetMessagesReject
 } from '../action';
-import { getMessagesById,sentMessageById } from '../../../api-data';
+import { getMessagesById } from '../../../api-data';
 import { TMessages } from '../../../typescript/redux/messages/types'
 
 
@@ -16,13 +16,8 @@ const asyncGetMessagesById= (id:string,cb:any) => async (dispatch:any) => {
   } 
 };
 
-const asyncSentMessageById= (id:string,message:any) => async (dispatch:any) => {
-  try {
-    await sentMessageById(id, message)
-  } catch(e) {}
-};
 
-export { asyncGetMessagesById,asyncSentMessageById };
+export { asyncGetMessagesById };
 
 
 

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

@@ -9,8 +9,6 @@ const initialState: IMessagesState = {
   messages: []
 }
 
-
-
 const reducerMessages = createReducer(initialState, {
   [actionGetMessagesSuccess.type]: (state, { payload: messages }: IMessagesPayload) => {
     return {messages};

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

@@ -6,6 +6,7 @@ export type TMessage = {
   color: string,
   number:string,
   _id: string,
+  type: string,
   companionId: string,
   owner: any,
   createdAt: string,