Browse Source

done user update && some markup changes

Ivar 3 years ago
parent
commit
eec15697fe

+ 54 - 74
src/actions/authActions.js

@@ -46,110 +46,90 @@ import {
    )
 
 
-   export const actionChangeUser = (userId, nick, login ) => (
-      actionPromise('changeUser', gql(`mutation changeUser($user: UserInput) {
-         UserUpsert (user: $user) {
-            _id
-            createdAt
-            login
+
+   const actionUpdateUserAvatar = (userId, avatarId) => (
+      actionPromise('updateUserAv', gql(`mutation updateUserAv($user:UserInput) {
+         UserUpsert(user:$user) {
+            _id   
+            login  
             nick
             avatar {
                url
             }
          }
-      }`, { user: {_id: userId, nick, login}  }
-      ))
-   )
-
-   export const actionRemoveUser = (userId) => (
-      actionPromise('changeUser', gql(`mutation changeUser($user: UserInput) {
-         UserDelete (user: $user){
-           _id
-         }     
-      }`, { user: { _id: userId }  }
-      ))
+      }`, { user: {_id: userId, avatar: {_id: avatarId} } }))
    )
 
-
-
-
-
-   // export const actionChangePass = (login, password, newPassword) => (
-   //    actionPromise('changePass', gql(`mutation change($login: String! $password: String! $newPassword: String!) {
-   //       UserUpsert(user: {login: $login, password: $password, newPassword: $newPassword}) {
-   //          _id
-   //          login
-   //        }
-   //    }
-   //    `, {login, password, newPassword})      
-   //    )
-   // )
-   // // changePassword( login: String! password: String! newPassword: String! ): User
-
-
-
-
-
-
-   const actionUpdateUser = (userId, newLogin, newNick, avatarId, newChats) => (
+   const actionUpdateUserLogin = (userId, newLogin, newNick) => (
       actionPromise('updateUser', gql(`mutation updateUser($user:UserInput) {
          UserUpsert(user:$user) {
             _id   
             login  
             nick
          }
-      }`, { user: {_id: userId, login: newLogin, nick: newNick, avatar: {_id: avatarId} } }))
+      }`, { user: {_id: userId, login: newLogin, nick: newNick } }))
    )
 
-      // имеет сомнительную пользу, так как позволяет обновить только аву, 
-      // ниже метод обновляющий также логин и ник в форме
-   export const actionSetAvatar = (name, file) => (
+   export const actionSetUserInfo = (name, file, newLogin, newNick) => (
       async (dispatch, getState) => {
-         let fileObj = await dispatch(actionUploadFile(name, file))
-         console.log(fileObj._id)
          let {auth} = getState()
-         let userId = auth?.payload?.sub?.id 
+         let userId = auth.payload?.sub?.id
+         // console.log(userId, file, newLogin, newNick)
+         // debugger
+         if (file) {
+            let fileObj = await dispatch(actionUploadFile(name, file))
+            await dispatch(actionUpdateUserAvatar(userId, fileObj?._id))
+         } 
+         await dispatch(actionUpdateUserLogin(userId, newLogin, newNick))         
+         await dispatch(actionAboutMe())             
+      }
+   )
+
 
-         await dispatch(actionUpdateUser(userId, fileObj._id))
 
-         await dispatch(actionAboutMe())    
+   const actionChangePass = (login, password, newPassword) => (
+      actionPromise('changePass', gql(`mutation changePass($login: String! $password: String! $newPassword: String!) {
+         changePassword(login: $login, password: $password, newPassword: $newPassword)
       }
+      `, {login, password, newPassword})      
+      )
    )
 
-   export const actionSetUserInfo = (name, file, newLogin, newNick) => (
+   export const actionSetUserPass = (password, newPassword) => (
       async (dispatch, getState) => {
-         let {promise} = getState()
-         let {_id: userId, avatar: {_id: avatarId} } = promise.myProfile?.payload
-
-         console.log(userId, file, avatarId, newLogin, newNick)
+         let {auth} = getState()
+         let userLog = auth.payload?.sub?.login
 
-         if (file) {
-            let fileObj = await dispatch(actionUploadFile(name, file))
-            await dispatch(actionUpdateUser(userId, newLogin, newNick, fileObj?._id))
-         } else {
-            await dispatch(actionUpdateUser(userId, newLogin, newNick, avatarId))
-         }
-         await dispatch(actionAboutMe())    
+         console.log(userLog, password, newPassword)
+         await dispatch(actionChangePass(userLog, password, newPassword))         
       }
    )
 
 
-      // !!!! ПОДХОД ВЕРНЫЙ ТОЛЬКО ДЛЯ ЗАГРУЗКИ МНОГИХ ФАЙЛОВ В СООБЩЕНИЕ
-   // позволяет загрузить файл и взамен получить url  
-   // нужен для предпросмотра, когда юзер еще не определился нужно ли добавлять этот url в стейт
-   export const actionGroupFiles = (name, file) => (
-      async (dispatch, getState) => {
-         let fileObj = await dispatch(actionUploadFile(name, file))
-         let URL = fileObj.avatar.url
-         console.log(fileObj._id)
-         let {auth} = getState()
-         let userId = auth?.payload?.sub?.id 
 
-         await dispatch(actionUpdateUser(userId, fileObj._id))
 
-         await dispatch(actionAboutMe())    
-      }
+   // так же нужен setUserChats
+      // дописать
+   // происходит когда юзер уходит сам, иначе в чат добавляются юзерю, а не наоборот
+   const actionUpdateUserCahts = (userId, newChats) => (
+      actionPromise('updateUser', gql(`mutation updateUser($user:UserInput) {
+         UserUpsert(user:$user) {
+            _id   
+            login  
+            nick
+         }
+      }`, { user: {_id: userId, } }))
    )
 
 
-   // так же нужен setUserChats
+
+
+      // не работает
+   // export const actionRemoveUser = (userId) => (
+   //    actionPromise('changeUser', gql(`mutation changeUser($user: UserInput) {
+   //       UserDelete (user: $user){
+   //         _id
+   //       }     
+   //    }`, { user: { _id: userId }  }
+   //    ))
+   // )

+ 1 - 1
src/actions/index.js

@@ -2,8 +2,8 @@
 export {
    actionFullLogin, 
    actionFullRegister, 
-   actionSetAvatar,
    actionSetUserInfo,
+   actionSetUserPass,
 } from './authActions'
 export {
    actionAddChat, 

+ 28 - 1
src/actions/msgActions.js

@@ -4,8 +4,11 @@ import {
    actionMsgListInChat, 
    actionAddMsgInChat,
    actionUpdateMsgInChat,
-   actionRemoveMsgInChat,
 } from '../reducers'
+import {   
+   actionUploadFile
+} from './mediaActions'
+
 
 
 export const actionGetMsgsByChat = (chatId, skipCount=0, limitCount=50) => (
@@ -133,3 +136,27 @@ export const actionRemoveMsg = (msgId) => (
    }`, { msg: { _id: msgId } }
    ))
 )
+
+
+
+
+
+
+
+
+
+   
+      // !!!! ПОДХОД ВЕРНЫЙ ТОЛЬКО ДЛЯ ЗАГРУЗКИ МНОГИХ ФАЙЛОВ В СООБЩЕНИЕ - перенести в сообщения
+   // позволяет загрузить файл и взамен получить url  
+   // нужен для предпросмотра, когда юзер еще не определился нужно ли добавлять этот url в стейт
+   export const actionGroupFiles = (name, file) => (
+      async (dispatch, getState) => {
+         let fileObj = await dispatch(actionUploadFile(name, file))
+         let URL = fileObj.avatar.url
+         console.log(fileObj._id)
+         let {auth} = getState()
+         let userId = auth.payload?.sub?.id  
+      }
+   )
+
+

+ 80 - 7
src/components/MainMenu.js

@@ -4,22 +4,32 @@ import MenuIcon from '@mui/icons-material/Menu';
 import Menu from '@mui/material/Menu';
 import MenuItem from '@mui/material/MenuItem';
 
+
+import Drawer from '@mui/material/Drawer';
+import Box from '@mui/material/Box';
+import List from '@mui/material/List';
+import Divider from '@mui/material/Divider';
+import ListItem from '@mui/material/ListItem';
+import ListItemText from '@mui/material/ListItemText';
+
 import {actionAuthLogout} from "../reducers"
 import {connect}  from 'react-redux';
 
-import {CProfileModal} from '../components'
+import {CProfileModal, CUserAvatar} from '../components'
 
 
 const LogoutBtn = ({onLogout}) => (
-   <MenuItem onClick={onLogout}>
-      Выйти
-   </MenuItem>
+   <>
+      <ListItem button onClick={onLogout} >
+         <ListItemText primary={'Выйти'} />
+      </ListItem>
+   </>
 )
 const CLogoutBtn = connect(null, {onLogout: actionAuthLogout})(LogoutBtn)
 
 export const MainMenu = () => {
    const [anchorEl, setAnchorEl] = useState(null)
-   const open = Boolean(anchorEl)
+   const open = !!anchorEl
 
    const handleClick = (event) => {
      setAnchorEl(event.currentTarget)
@@ -50,12 +60,13 @@ export const MainMenu = () => {
          'aria-labelledby': 'basic-button',
          }}
          >
+
+            <CProfileModal />
+
             <MenuItem onClick={handleClose}>
                Контакты
             </MenuItem>
 
-            <CProfileModal onModalOpen={handleClose}/>
-
             <CLogoutBtn />
                                     
          </Menu>
@@ -64,3 +75,65 @@ export const MainMenu = () => {
 }
 
 
+
+export const MenuDrawer = ({}) => {
+   const [state, setState] = useState(false);
+   const open = !!state
+
+ 
+   const toggleDrawer = (open) => (event) => {
+     if ( event.type === 'keydown' && 
+          ( event.key === 'Tab' || 
+            event.key === 'Shift')) {
+       return
+     } 
+     setState(open)
+   } 
+
+   return (
+     <div>
+         <IconButton edge="start" color="inherit" aria-label="menu" sx={{ mr: 1 }}
+            id="basic-button"
+            aria-controls={open ? 'basic-menu' : undefined}
+            aria-haspopup="true"
+            aria-expanded={open ? 'true' : undefined}
+            onClick={toggleDrawer(true)}
+         >
+            
+            <MenuIcon />
+            <CUserAvatar sx={{ ml: 1}} />
+         </IconButton>
+         
+
+
+         <Drawer
+            open={state}
+            onClose={toggleDrawer(false)}
+         >
+
+            <Box
+            sx={{ width: 250 }}
+            role="presentation"
+            >
+               <Box sx={{ m: 2, display: 'flex', justifyContent: 'center' }}>
+                  <CUserAvatar bigSize={true} />
+               </Box>               
+
+               <List>
+                  <CProfileModal />
+
+                  <ListItem button >
+                     <ListItemText primary={'Контакты'} />
+                  </ListItem>
+
+                  <Divider />
+
+                  <CLogoutBtn />
+
+               </List>
+            </Box>
+
+         </Drawer>
+     </div>
+   );
+ }

+ 262 - 18
src/components/ProfileModal.js

@@ -1,7 +1,8 @@
 import React, {useEffect, useState, useRef} from 'react';
 import Box from '@mui/material/Box';
 import Modal from '@mui/material/Modal';
-import MenuItem from '@mui/material/MenuItem';
+import ListItem from '@mui/material/ListItem';
+import ListItemText from '@mui/material/ListItemText';
 import Button from '@mui/material/Button';
 import IconButton from '@mui/material/IconButton';
 import Typography from '@mui/material/Typography';
@@ -14,7 +15,7 @@ import {UserAvatar} from '../components'
 
 import { printStrReq } from "../helpers";
 import {connect}  from 'react-redux'
-import {actionSetUserInfo} from '../actions'
+import {actionSetUserInfo, actionSetUserPass} from '../actions'
 
 
 const styleModalParrent = {
@@ -34,17 +35,241 @@ const styleModalParrent = {
 }
 
 
+const PassModal = ({onСonfirm, minPass='2', char=false, bigChar=false, number=false, regError}) => {
+   const [open, setOpen] = useState(false);
+   const handleOpen = () => {
+     setOpen(true);
+   }
+   const handleClose = () => {
+     setOpen(false);
+   }
 
+   const [oldPass, setOldPass] = useState('')
+   const [oldPassBlur, setOldPassBlur] = useState(false)
+   
 
-const ProfileModal = ({minLog='2', myProfile, onСonfirm, onModalOpen}) => {
+   const [pass, setPass] = useState('')
+   const [passBlur, setPassBlur] = useState(false)
+
+   const [pass2, setPass2] = useState('')
+   const [pass2Blur, setPass2Blur] = useState(false)
+
+
+   const [wrongAlert, setWrongAlert] = useState(false)
+
+   useEffect(() => {
+      if (regError?.payload === null) {
+         setWrongAlert(true)
+      } else {
+         setWrongAlert(false)
+      }
+   },[regError])
+
+
+   const checkPass = (password) => {
+      if (  password.length >= minPass && 
+            !password.match(/\s/) && 
+            (char ? password.match(/[a-zа-яё]/) : true) && 
+            (bigChar ? password.match(/[A-ZА-ЯЁ]/) : true) && 
+            (number ? password.match(/[\d]/) : true) ) {
+      return true
+      } else {
+         return false
+      }
+   }
+
+   const printPassReq = (password) => {
+      let str = ''
+      if (checkPass(password)) {
+         str += ' '
+      } else if (password.match(/\s/)) {
+         str += 'Пароль не должен содержать пробелы '
+      } else {
+         str += 'Пароль должен содержать: '
+         str += printStrReq(password, minPass) + ','
+         if (!(char ? password.match(/[a-zа-яё]/) : true)) {
+            str += ' строчные буквы,'
+         }
+         if (!(bigChar ? password.match(/[A-ZА-ЯЁ]/) : true)) {
+            str += ' прописные буквы,'
+         }
+         if  (!(number ? password.match(/[\d]/) : true)) {
+            str += ' цифры,'
+         }
+      }
+      return str.slice(0, -1)
+   }
+ 
+   return (
+     <>
+      <Button variant="text" color="error" onClick={handleOpen} >
+         Новый пароль
+      </Button> 
+
+       <Modal
+         hideBackdrop
+         open={open}
+         onClose={handleClose}
+         aria-labelledby="child-modal-title"
+         aria-describedby="child-modal-description"
+       >
+         <Box sx={{ ...styleModalParrent,   width: '40%', maxWidth: '400px', }}>
+            <Box sx={{ display: 'flex', justifyContent: 'end' }}>
+               <IconButton aria-label="delete" onClick={handleClose}>
+                  <CloseIcon />
+               </IconButton>
+            </Box>
+
+            <Box sx={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', mt: 4 }}>
+               <Typography variant="body1">
+                  Введите старый пароль
+               </Typography>
+               <TextField
+                  onChange={(e) => {
+                        e.target.value = e.target.value.trim()
+                        setOldPass(e.target.value.trim())
+                     }
+                  }  
+                  onBlur={() => {
+                        setOldPassBlur(true)              
+                     }
+                  } 
+                  onFocus={() => {
+                        setOldPassBlur(false)              
+                     }
+                  }
+                  error={oldPassBlur ? (checkPass(oldPass) ? false : true) : false}               
+                  helperText={printPassReq(oldPass)}            
+   
+                  inputProps={{
+                     maxLength: 100
+                     }}
+                  required
+                  variant="standard"
+                  margin="none"
+                  fullWidth
+                  name="password"
+                  label=""
+                  type="password"
+                  id="oldPasswordUser"
+                  sx={{mt: 1}}
+               />
+            </Box>
+
+            <Box sx={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', mt: 4 }}>
+               <Typography variant="body1">
+                  Введите новый пароль
+               </Typography>
+               <TextField
+                  onChange={(e) => {
+                        e.target.value = e.target.value.trim()
+                        setPass(e.target.value.trim())
+                     }
+                  }  
+                  onBlur={() => {
+                        setPassBlur(true)              
+                     }
+                  } 
+                  onFocus={() => {
+                        setPassBlur(false)              
+                     }
+                  }
+                  error={passBlur ? (checkPass(pass) ? false : true) : false}               
+                  helperText={printPassReq(pass)}            
+   
+                  inputProps={{
+                     maxLength: 100
+                     }}
+                  required
+                  variant="standard"
+                  margin="none"
+                  fullWidth
+                  name="password"
+                  label=""
+                  type="password"
+                  id="passwordUser"
+                  sx={{mt: 1}}
+               />
+            </Box>
+
+            <Box sx={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', mt: 4 }}>
+               <Typography variant="body1">
+                  Повторите новый пароль
+               </Typography>
+               <TextField
+                  onChange={(e) => {
+                        e.target.value = e.target.value.trim()
+                        setPass2(e.target.value.trim())
+                     }
+                  }  
+                  onBlur={() => {
+                        setPass2Blur(true)              
+                     }
+                  } 
+                  onFocus={() => {
+                        setPass2Blur(false)              
+                     }
+                  }
+                  error={pass2Blur ? (checkPass(pass2) ? false : true) : false}               
+                  helperText={printPassReq(pass2)}            
+   
+                  inputProps={{
+                     maxLength: 100
+                     }}
+                  required
+                  variant="standard"
+                  margin="none"
+                  fullWidth
+                  name="password"
+                  label=""
+                  type="password"
+                  id="passwordUser2"
+                  sx={{mt: 1}}
+               />
+            </Box>
+
+
+            { wrongAlert ?
+                  <Typography component="p" variant="body2" mt={1} ml={2} 
+                     sx={{fontWeight: 'medium', fontSize: '0.75rem', color: '#d32f2f'}}>
+                        Неверный пароль
+                  </Typography> :
+                  <></>
+               }
+
+            <Box sx={{ display: 'flex', justifyContent: 'end', mt: 2}}>
+               <Button  variant="contained" 
+                        disabled={( checkPass(oldPass) && 
+                                    checkPass(pass) && 
+                                    pass === pass2 ) ? false : true}
+
+                        onClick={() => onСonfirm(oldPass, pass)}>
+                  Изменить 
+               </Button>
+            </Box>
+
+         </Box>
+       </Modal>
+     </>
+   );
+ }
+ const CPassModal = connect( (state) => ({regError: state.promise.changePass || {}}), 
+                              {onСonfirm : actionSetUserPass})(PassModal)
+
+
+
+
+
+
+
+
+const ProfileModal = ({minLog='2', myProfile, onСonfirm, logError}) => {
   const [open, setOpen] = useState(false)
-   // console.log(myProfile)
   // const {login, nick, avatar: {url}} = myProfile
 
    const [login, setLogin] = useState(myProfile.login)
    const [logBlur, setLogBlur] = useState(false)
    const [nick, setNick] = useState(myProfile.nick)
-   const currAvatar = useRef(myProfile.avatar?.url)
 
    const [img, setImg] = useState(null)
    const {
@@ -61,13 +286,23 @@ const ProfileModal = ({minLog='2', myProfile, onСonfirm, onModalOpen}) => {
    });
 
   const handleOpen = () => setOpen(true)
-  const handleClose = () => (setImg(null), setOpen(false))
+  const handleClose = () => (setOpen(false))
+
+  const [wrongAlert, setWrongAlert] = useState(false)
+
+  useEffect(() => {
+     if (logError?.payload === null) {
+        setWrongAlert(true)
+     } else {
+        setWrongAlert(false)
+     }
+  },[logError])
 
   return (
     <div>
-      <MenuItem onClick={handleOpen}>
-               Профиль
-      </MenuItem>
+         <ListItem button onClick={handleOpen} >
+            <ListItemText primary={'Мой профиль'} />
+         </ListItem>
 
       <Modal
         open={open}
@@ -91,15 +326,17 @@ const ProfileModal = ({minLog='2', myProfile, onСonfirm, onModalOpen}) => {
             
             <Box sx={{ display: 'flex', justifyContent: 'start', mt: 2,  }}>
 
-               <UserAvatar profile={{  login: login, nick: nick, avatar: {url: myProfile.avatar?.url || ''},
-                                       localUrl: img && URL.createObjectURL(img)}} />
 
                <form action="/upload" method="post" encType="multipart/form-data" id='formUser'> 
                   <section className="container">
-                     <div {...getRootProps({className: 'dropzone'})}>
+                     <Box {...getRootProps({className: 'dropzone'})} sx={{ cursor: 'pointer', height: '70px', display: 'flex' }} >
+
+                        <UserAvatar profile={{  login: login, nick: nick, avatar: {url: myProfile.avatar?.url || ''},
+                                       localUrl: img && URL.createObjectURL(img)}} bigSize={true} />
+
                         <input {...getInputProps()} type="file" name="media" id='mediaUser' />
-                        <p>Изменить аватар</p>
-                     </div>
+                        <Box sx={{ p: '20px', ml: 1 }} >Изменить аватар</Box>
+                     </Box>
                   </section>
                </form>
 
@@ -164,11 +401,17 @@ const ProfileModal = ({minLog='2', myProfile, onСonfirm, onModalOpen}) => {
 
 
             <Box sx={{ display: 'flex', justifyContent: 'center', mt: 4 }}>
-               <Button variant="text" color="error" >
-                  Новый пароль
-               </Button>    
+                  <CPassModal />
             </Box>
 
+            { wrongAlert ?
+                  <Typography component="p" variant="body2" mt={2} ml={2} 
+                     sx={{fontWeight: 'medium', fontSize: '0.75rem', color: '#d32f2f'}}>
+                        Логин уже существует
+                  </Typography> :
+                  <></>
+               }
+
             <Box sx={{ display: 'flex', justifyContent: 'end', mt: 2}}>
                <Button  variant="contained" 
                         disabled={(login?.length >= minLog) ? false : true}
@@ -183,7 +426,8 @@ const ProfileModal = ({minLog='2', myProfile, onСonfirm, onModalOpen}) => {
     </div>
   );
 }
-export const CProfileModal = connect(  state => ({myProfile: state.promise?.myProfile?.payload || {}}), 
+export const CProfileModal = connect(  state => (  {  myProfile: state.promise?.myProfile?.payload || {},
+                                                      logError: state.promise.updateUser || {} }), 
                                        {onСonfirm : actionSetUserInfo})(ProfileModal)
 
 

+ 0 - 0
src/components/Search.js


+ 51 - 0
src/components/SearchBlock.js

@@ -0,0 +1,51 @@
+import React from 'react';
+import { styled, alpha } from '@mui/material/styles';
+import InputBase from '@mui/material/InputBase';
+import SearchIcon from '@mui/icons-material/Search';
+
+const Search = styled('div')(({ theme }) => ({
+  position: 'relative',
+  borderRadius: theme.shape.borderRadius,
+  backgroundColor: alpha(theme.palette.common.white, 0.15),
+  '&:hover': {
+    backgroundColor: alpha(theme.palette.common.white, 0.25),
+  },
+  marginLeft: 1,
+  width: '100%',
+}));
+
+const SearchIconWrapper = styled('div')(({ theme }) => ({
+  padding: theme.spacing(0, 2),
+  height: '100%',
+  position: 'absolute',
+  pointerEvents: 'none',
+  display: 'flex',
+  alignItems: 'center',
+  justifyContent: 'center',
+}));
+
+const StyledInputBase = styled(InputBase)(({ theme }) => ({
+  color: 'inherit',
+  '& .MuiInputBase-input': {
+    padding: theme.spacing(1, 1, 1, 0),
+    // vertical padding + font size from searchIcon
+    paddingLeft: `calc(1em + ${theme.spacing(4)})`,
+    transition: theme.transitions.create('width'),
+    width: '100%',
+  },
+}));
+
+export const SearchBlock = () => {
+   return (
+   <Search>
+      <SearchIconWrapper>
+        <SearchIcon />
+      </SearchIconWrapper>
+      <StyledInputBase
+      placeholder="Поиск..."
+      inputProps={{ 'aria-label': 'search' }}
+      />
+   </Search>
+   )
+}
+

+ 7 - 5
src/components/UserAvatar.js

@@ -5,7 +5,7 @@ import {backURL}  from '../helpers'
 import {connect}  from 'react-redux'
 
 
-export const UserAvatar = ({ profile }) => {
+export const UserAvatar = ({  profile, bigSize=false }) => {
   //  console.log(profile)
    
    function stringToColor(string) {
@@ -64,7 +64,7 @@ export const UserAvatar = ({ profile }) => {
       } else if (profile.avatar?.url) {
         return backURL + profile.avatar?.url
       } else {
-        return null
+        return false
       }
     }
 
@@ -72,9 +72,11 @@ export const UserAvatar = ({ profile }) => {
    return (
       <>
       {
-         !!getUrl() ?
-         <Avatar alt={profile.nick || profile.login } src={getUrl()} /> :
-         <Avatar  {...stringAvatar(profile.nick || profile.login)} /> 
+         getUrl() ?
+         <Avatar  sx={ bigSize ? { height: '70px', width: '70px' } : { height: '40px', width: '40px' } } 
+                  alt={profile.nick || profile.login } src={getUrl()} /> :
+         <Avatar  sx={ bigSize ? { height: '70px', width: '70px' } : { height: '40px', width: '40px' } }
+                  {...stringAvatar(profile.nick || profile.login)} /> 
       }        
       </>
    ) 

+ 2 - 1
src/components/index.js

@@ -2,8 +2,9 @@
 export {CChatList} from './ChatList'
 export {Msg} from './MsgList'
 export {CPreloaded} from './Preload'
-export {MainMenu} from './MainMenu'
+export {MainMenu, MenuDrawer} from './MainMenu'
 export {Header} from './Header'
+export {SearchBlock} from './SearchBlock'
 export {FloatBtn} from './FloatBtn'
 export {UserAvatar, CUserAvatar} from './UserAvatar'
 export {CProfileModal} from './ProfileModal'

+ 3 - 6
src/pages/Main.js

@@ -13,7 +13,7 @@ import { createTheme, ThemeProvider } from '@mui/material/styles';
 import SendIcon from '@mui/icons-material/Send';
 
 
-import {MainMenu, CChatList, Header, CMsgDropZone, CUserAvatar} from "../components"
+import {MenuDrawer, SearchBlock, CChatList, Header, CMsgDropZone, CUserAvatar} from "../components"
 import {
    actionChangePass,
    actionAddChat
@@ -36,13 +36,10 @@ export const Main = ({}) => {
 
                      <Grid item height="60px"> 
                         <Header> 
-                           <MainMenu />
 
-                           <Typography variant="body1" color="inherit" component="div">
-                              шапка1: общее меню, поиск
-                           </Typography>
+                           <MenuDrawer />
 
-                           <CUserAvatar />
+                           <SearchBlock />
 
                         </Header>                        
                      </Grid>

+ 2 - 2
src/pages/Register.js

@@ -209,7 +209,7 @@ const RegisterForm = ({minLog='2', minPass='2', char=false, bigChar=false, numbe
 
             <Button
                disabled={( login.length >= minLog && 
-                           pass.length >= minPass && 
+                           checkPass(pass) && 
                            pass === pass2) ? false : true}
 
               type="submit"
@@ -232,7 +232,7 @@ const RegisterForm = ({minLog='2', minPass='2', char=false, bigChar=false, numbe
           </Box>
    )
 }
-const CRegisterForm = connect( (state) => ({regError: state.promise.register}), {onRegister: actionFullRegister})(RegisterForm)
+const CRegisterForm = connect( (state) => ({regError: state.promise.register || {}}), {onRegister: actionFullRegister})(RegisterForm)
 
 
 const theme = createTheme()