2 Commits d2260ec165 ... cca472ae25

Autor SHA1 Mensaje Fecha
  serg1557733 cca472ae25 add media query and some fix hace 1 año
  serg1557733 91b01cda95 add media resize hace 1 año

+ 25 - 10
frontend/src/components/chatPage/ChatPage.jsx

@@ -8,6 +8,7 @@ import { removeToken} from '../../reducers/userDataReducer'
 import { useDispatch, useSelector } from 'react-redux';
 import {getSocket} from'../../reducers/socketReducer';
 import { sendMessage, storeMessage } from '../../reducers/messageReducer';
+import { editMessage } from '../../reducers/messageReducer';
 import './chatPage.scss';
 
 
@@ -20,14 +21,20 @@ export const ChatPage = () => {
     const token = useSelector(state => localStorage.getItem('token') || state.userDataReducer.token);
     const user = useSelector(state => state.getUserSocketReducer.socketUserData)
     const socket = useSelector(state => state.getUserSocketReducer.socket)
-
+    const editOldMessage = useSelector(state => state.messageReducer.editMessage)
     const [message, setMessage] = useState({message: ''});
-
+    const isTabletorMobile = (window.screen.width < 730);
+    
+    
     useEffect(() => {
         if(token){
             SOCKET_EVENTS.map(event => dispatch(getSocket(event)))       
         }
-    }, [token])
+
+        console.log('editMessage chat', editOldMessage)
+
+    }, [token, editOldMessage])
+
 
 
     return (
@@ -45,19 +52,23 @@ export const ChatPage = () => {
                                         e.preventDefault()
                                         dispatch(sendMessage({user, socket}))
                                         dispatch(getSocket('allmessages'))
+                                        dispatch(editMessage({editMessage: ''}))
                                         setMessage({message: ''})
                                     }}
-                        sx={{
+                        sx={(isTabletorMobile)?{
+                            display: 'flex',
+                            margin: '10px 2px'}
+                        :{
                             display: 'flex',
-                            margin: '20px 5px'
-                        }}
-                    >
+                            margin: '20px 5px'}
+                           
+                        }>
             
                         <TextareaAutosize
                             id="outlined-basic" 
                             label="Type a message..." 
                             variant="outlined" 
-                            value={message.message}
+                            value={message.message || editOldMessage}
                             placeholder='type you message...'
                             minRows={3}
                             maxRows={4}
@@ -89,10 +100,14 @@ export const ChatPage = () => {
                     </Box>            
                 </Box>
 
-                <Box className='usersBox'>
+                <Box className={(isTabletorMobile)?'usersBoxMobile':'usersBox'}>
 
                     <Button 
-                        sx={{margin:'10px 5px'}}
+                        sx={(isTabletorMobile) ? 
+                            {
+                                maxHeight:'25px', 
+                                maxWidth: '20px'} 
+                            :{margin:'10px 5px'}}
                         variant="outlined"
                         onClick={()=> {
                                 localStorage.removeItem('token');

+ 32 - 3
frontend/src/components/chatPage/chatPage.scss

@@ -1,11 +1,12 @@
 .rootContainer {
-    max-width: 90%;
+    max-width: 95%;
+    max-height: 95%;
     margin: 0 auto;
 }
 
 .rootBox {
     display: flex;
-    height: 100vh;
+    height: 97vh;
 }
 .rootMessageForm {
     display: flex;
@@ -56,6 +57,13 @@
     background-color: rgb(240, 231, 136);
     cursor: pointer;
 }
+.myData {
+    align-self: flex-end;
+}
+.data {
+    align-self: flex-start;
+}
+
 // .editMessage{
 //     background-color: rgb(246, 245, 235);
 //     transform:translate(-120px, -90px);
@@ -70,7 +78,7 @@
     flex-grow :2;
     flex-direction: column;
     overflow: scroll;
-    height: 100vh  
+    height: 90vh  
     
 }
 .usersBox { 
@@ -91,3 +99,24 @@
 
     }
 }
+
+.usersBoxMobile { 
+    align-content: flex-end;
+    text-align: center;
+    text-overflow: ellipsis;
+    padding: 5px;
+    width: 20%;
+    overflow: 'scroll';
+    font-size: 11px;
+    border-radius: 10px;
+    background-color:rgb(243, 243, 243);
+    .online {
+        border-radius: 5px;
+        text-overflow: ellipsis;
+        padding: 5px;
+        margin-bottom: 5px;
+        background-color:rgb(247, 233, 233);
+        font-weight: 500;
+
+    }
+}

+ 22 - 12
frontend/src/components/chatPage/messageForm/MessegaForm.jsx

@@ -3,7 +3,9 @@ import { dateFormat } from '../utils/dateFormat';
 import { useSelector } from 'react-redux';   
 import { Fragment, useRef, useEffect, useMemo} from 'react';
 import { scrollToBottom } from '../utils/scrollToBottom';
-           
+import { useDispatch } from 'react-redux';
+import { editMessage } from '../../../reducers/messageReducer';
+   
 export const MessageForm = () => {
 
     const randomColor = require('randomcolor');  
@@ -11,9 +13,9 @@ export const MessageForm = () => {
     const user = useSelector(state => state.getUserSocketReducer.socketUserData)
     const usersOnline = useSelector(state => state.getUserSocketReducer.usersOnline)
     const userColor = useMemo(() => randomColor(),[]);
-       
+    const dispatch = useDispatch();
+   
     const endMessages = useRef(null);
- 
 
     useEffect(() => {
         scrollToBottom(endMessages)
@@ -59,25 +61,33 @@ export const MessageForm = () => {
                             onClick = {(e) => {
                                 if(e.target.className.includes('myMessage')){
                                     e.currentTarget.className += ' editMessage' 
+                                    startMessages.map( item => {
+                                        if((item.userName === user.userName) && (item.text === e.target.textContent)){
+                                            console.log('edit message',e.target.textContent )
+                                            dispatch(editMessage({editMessage: e.target.textContent}))                                        
+                                        }
+                                        })
                                     }
-                                //add function to edit message
+                                  
                             }}
-
                             className={ 
                                 (item.userName === user.userName)? 'message myMessage' :'message'}
                         >
 
                             <p>{item.text}</p>  
 
-                            <div className='time'>
-                                {dateFormat(item).time}
-                            </div> 
+                        </div>
+                            <div className={ 
+                                (item.userName === user.userName)? 'myData' :'date'}>
+                                <div className='time'>
+                                    {dateFormat(item).time}
+                                </div> 
+                                
+                                <div className='date'>
+                                    {dateFormat(item).year}
+                                </div>
                             
-                            <div className='date'>
-                                {dateFormat(item).year}
                             </div>
-                        </div>
-                
                     </Fragment>
                 )}
 

+ 32 - 20
frontend/src/components/chatPage/userInfo/UserInfo.jsx

@@ -2,6 +2,7 @@ import {Button,Avatar} from '@mui/material';
 import { useSelector } from 'react-redux';
 import { banUser } from '../service/banUser';
 import { muteUser } from '../service/muteUser';
+import './userInfo.scss';
 
 
 export const UserInfo = () => {
@@ -9,20 +10,25 @@ export const UserInfo = () => {
     //add foto loading function
     const allUsers = useSelector(state => state.getUserSocketReducer.allUsers)
     const user = useSelector(state => state.getUserSocketReducer.socketUserData)
-    const usersOnline = useSelector(state => state.getUserSocketReducer.usersOnline)
+    const usersOnline = [...new Set(useSelector(state => state.getUserSocketReducer.usersOnline))];//Set?
     const socket = useSelector(state => state.getUserSocketReducer.socket)
 
+    const isTabletorMobile = (window.screen.width < 730);
+
     return (
-            <>
-                <Avatar sx={{ 
-                    bgcolor: 'grey',
-                    width: '100px',
-                    height: '100px',
-                    fontSize: 14,
-                    margin: '20px auto'
-                    }}>
-                    {user.userName}
-                </Avatar>
+            <> 
+                 <Avatar  sx={ (isTabletorMobile) ? {} : 
+                            {
+                            bgcolor: 'grey',
+                            width: '100px',
+                            height: '100px',
+                            fontSize: 14,
+                            margin: '20px auto',
+                            cursor: 'pointer'
+                            }} /> 
+                
+
+                   
                     {user.isAdmin ? 
                         allUsers.map((item) =>
                             <div 
@@ -47,10 +53,14 @@ export const UserInfo = () => {
                                             onClick={()=>{
                                                 muteUser(item.userName, item?.isMutted, socket)
                                             }}
-                                            sx={{
+                                            sx={(isTabletorMobile) 
+                                                ? 
+                                                {height: '15px',
+                                                 maxWidth:'20px'}: 
+                                                {
                                                 margin:'3px',
-                                                height: '25px'
-                                            }}>
+                                                height: '25px'}}>
+
                                                 {item.isMutted
                                                 ? 
                                                 'unmute'
@@ -62,23 +72,25 @@ export const UserInfo = () => {
                                             onClick={()=>{ 
                                                 banUser(item.userName, item.isBanned, socket)
                                             }}
-                                            sx={{
+                                            sx={(isTabletorMobile) 
+                                                ? 
+                                                {height: '15px',
+                                                margin:'2px'} : 
+                                                {
                                                 margin:'3px',
-                                                height: '25px'
-                                            }}>
+                                                height: '25px'}}
+                                       >
                                                 {item?.isBanned ? 'unban' : 'ban'}
                                         </Button> 
                                     </>}
                             
                                 </div>
-                                    { usersOnline.map((user, i) => {
+                                    {usersOnline.map((user, i) => {
                                         if(item.userName === user.userName){
                                             return <span key={i} style={{color: 'green'}}>online</span>
                                         }})}
                             </div>) 
-
                     :
-
                     usersOnline.map((item, i) =>
                         <div 
                             key={i}

+ 7 - 0
frontend/src/components/chatPage/userInfo/userInfo.scss

@@ -0,0 +1,7 @@
+.userAvatar {
+    background-color: grey;
+    width: 100px;
+    height: 100px;
+    font-size: 14;
+    margin: 20px auto;
+}

+ 14 - 0
frontend/src/components/chatPage/utils/Time.jsx

@@ -0,0 +1,14 @@
+import TimeAgo from 'react-timeago'
+import frenchStrings from 'react-timeago/lib/language-strings/fr'
+import buildFormatter from 'react-timeago/lib/formatters/buildFormatter'
+
+
+
+export const Time = () => {
+    
+    const formatter = buildFormatter(frenchStrings)
+
+return (
+    <TimeAgo date='Feb 1, 1966' formatter={formatter} />
+    )
+}

+ 12 - 2
frontend/src/reducers/messageReducer.js

@@ -2,7 +2,8 @@ import { createSlice} from '@reduxjs/toolkit';
 
 const initialState = {
     startMessages: [],
-    message:''
+    message:'',
+    editMessage: ''
 }
 
 export const sendMessageToSocket = (state, data) => {
@@ -12,11 +13,19 @@ export const sendMessageToSocket = (state, data) => {
             } 
     };
 
+
+export const editMessageToSocket = (state, data) => {
+        if (state.message && state.message.length < 200) {    
+           data.socket.emit('editmessage', {...data.user, message: state.message}); //add backend functional later find by id and edit   
+       } 
+};
+
 const messageReducerSlice = createSlice({
     name: 'messageReducer',
     initialState,
     reducers: {
         storeMessage: (state, action) => {state.message = action.payload.message},
+        editMessage: (state, action) => {state.editMessage = action.payload.editMessage},
         sendMessage: (state, action) => sendMessageToSocket(state, action.payload),
         clearMessage: (state) => {state.message = ''}
         
@@ -31,5 +40,6 @@ export default messageReducer;
 export const {
     storeMessage, 
     sendMessage,
-    clearMessage
+    clearMessage,
+    editMessage
     } = actions;

+ 196 - 0
package-lock.json

@@ -0,0 +1,196 @@
+{
+  "name": "chat-react",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "dependencies": {
+        "react-responsive": "^9.0.0-beta.10",
+        "react-timeago": "^7.1.0"
+      }
+    },
+    "node_modules/css-mediaquery": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
+      "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q=="
+    },
+    "node_modules/hyphenate-style-name": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+      "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/matchmediaquery": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.1.tgz",
+      "integrity": "sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==",
+      "dependencies": {
+        "css-mediaquery": "^0.1.2"
+      }
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/react": {
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+      "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
+    "node_modules/react-responsive": {
+      "version": "9.0.0-beta.10",
+      "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-9.0.0-beta.10.tgz",
+      "integrity": "sha512-41H8g4FYP46ln16rsHvs9/0ZoZxAPfnNiHET86/5pgS+Vw8fSKfLBuOS2SAquaxOxq7DgPviFoHmybgVvSKCNQ==",
+      "dependencies": {
+        "hyphenate-style-name": "^1.0.0",
+        "matchmediaquery": "^0.3.0",
+        "prop-types": "^15.6.1",
+        "shallow-equal": "^1.2.1"
+      },
+      "engines": {
+        "node": ">=0.10"
+      },
+      "peerDependencies": {
+        "react": ">=16.8.0"
+      }
+    },
+    "node_modules/react-timeago": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/react-timeago/-/react-timeago-7.1.0.tgz",
+      "integrity": "sha512-rouF7MiEm55fH791Y8cg+VobIJgx8gtNJ+gjr86R4ZqO1WKPkXiXjdT/lRzrvEkUzsxT1exHqV2V+Zdi114H3A==",
+      "peerDependencies": {
+        "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/shallow-equal": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
+      "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
+    }
+  },
+  "dependencies": {
+    "css-mediaquery": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
+      "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q=="
+    },
+    "hyphenate-style-name": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+      "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+    },
+    "loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "requires": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      }
+    },
+    "matchmediaquery": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.1.tgz",
+      "integrity": "sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==",
+      "requires": {
+        "css-mediaquery": "^0.1.2"
+      }
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+    },
+    "prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "requires": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "react": {
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+      "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+      "peer": true,
+      "requires": {
+        "loose-envify": "^1.1.0"
+      }
+    },
+    "react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
+    "react-responsive": {
+      "version": "9.0.0-beta.10",
+      "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-9.0.0-beta.10.tgz",
+      "integrity": "sha512-41H8g4FYP46ln16rsHvs9/0ZoZxAPfnNiHET86/5pgS+Vw8fSKfLBuOS2SAquaxOxq7DgPviFoHmybgVvSKCNQ==",
+      "requires": {
+        "hyphenate-style-name": "^1.0.0",
+        "matchmediaquery": "^0.3.0",
+        "prop-types": "^15.6.1",
+        "shallow-equal": "^1.2.1"
+      }
+    },
+    "react-timeago": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/react-timeago/-/react-timeago-7.1.0.tgz",
+      "integrity": "sha512-rouF7MiEm55fH791Y8cg+VobIJgx8gtNJ+gjr86R4ZqO1WKPkXiXjdT/lRzrvEkUzsxT1exHqV2V+Zdi114H3A==",
+      "requires": {}
+    },
+    "shallow-equal": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
+      "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
+    }
+  }
+}

+ 6 - 0
package.json

@@ -0,0 +1,6 @@
+{
+  "dependencies": {
+    "react-responsive": "^9.0.0-beta.10",
+    "react-timeago": "^7.1.0"
+  }
+}