unknown 3 lat temu
rodzic
commit
b54060fa29

Plik diff jest za duży
+ 1 - 1
.eslintcache


+ 132 - 0
src/components/HomePage/LeftBar/EditBar/EditList/index.tsx

@@ -0,0 +1,132 @@
+import { makeStyles, TextField } from '@material-ui/core'
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import Avatar from '@mui/material/Avatar';
+import AddAPhotoIcon from '@mui/icons-material/AddAPhoto';
+import { useState,useEffect} from 'react';
+import { useDropzone } from 'react-dropzone';
+import { format,firstLetter } from '../../../../../helpers'
+import { IAuthorizationState } from '../../../../../typescript/redux/authorization/interfaces'
+
+const useStyles = makeStyles({
+  container: {
+    display: 'flex',
+    alignItems: 'center',
+    alignContent:'center',
+    flexDirection: 'column',
+    width: '100%',
+    margin: '0 auto',
+    padding: 20,
+    paddingTop:0,
+    position: 'relative',
+    backgroundColor: '#ffffff',
+  },
+  imgWrapper: {
+    cursor: 'pointer',
+    marginBottom: 30,
+    position: 'relative',
+  },
+  imgDropZoneOverlay: {
+    position: 'absolute',
+    width: 120,
+    height: 120,
+    borderRadius: '50%',
+    backgroundColor: '#6868687d',
+    left: 0,
+    zIndex: 1,
+    display: 'flex',
+    justifyContent: 'center',
+    alignContent: 'center',
+    alignItems:'center'
+  },
+  addPhoto: {
+    color: '#ffffff',
+    transform: 'scale(1.1)',
+    '&:hover': {
+      transform: 'scale(1.3)',
+    },
+  },
+  avatarArrow: {
+    cursor: 'pointer',
+    alignSelf: 'flex-end',
+    '&:hover': {
+      backgroundColor: 'rgb(62, 149, 231)'
+    }
+  }
+})
+
+interface IEditList {
+  user: IAuthorizationState,
+  name: string,
+  setName: any,
+  lastName: string,
+  setLastName: any,
+  openBtn: boolean,
+  setOpenBtn: any,  
+}
+
+const EditList = (props: IEditList) => {
+  const classes = useStyles()
+  const {user,name,setName,lastName,setLastName,openBtn,setOpenBtn} = props
+  const { avatarUrl, color } = user
+  const { getRootProps, getInputProps, acceptedFiles } = useDropzone({
+        noDrag: true,
+        accept:'image/*'
+    });
+  const [file,setFile] = useState<any>(null)
+
+  const handleTextField = (e: React.ChangeEvent<HTMLInputElement>) => {
+  !openBtn&&setOpenBtn(true)
+  const value = format(e.target.value)
+  const name = e.target.name
+    switch (name) {
+      case 'name':
+        setName(value)
+        break;
+      case 'lastName':
+        setLastName(value)
+        break;
+      default:
+        break;
+    }
+  }
+
+  useEffect(() => {
+    if (acceptedFiles.slice(-1)[0]) setFile(acceptedFiles.slice(-1)[0])
+  }, [setFile, acceptedFiles])
+
+  return (
+    <div className={classes.container} >     
+      <ListItemAvatar className={classes.imgWrapper}>
+        <div {...getRootProps({ className: classes.imgDropZoneOverlay })}>
+          <AddAPhotoIcon className={classes.addPhoto} fontSize='large' />
+          <input {...getInputProps()}/>
+        </div>
+         <Avatar alt={name} src={avatarUrl?`http://localhost:3000/${avatarUrl}`:undefined}
+           sx={{ background: color, width: 120, height: 120}}>
+           {`${firstLetter(name)}${firstLetter(lastName)}`}
+         </Avatar>
+      </ListItemAvatar>                 
+      <TextField
+        id="name"
+        name='name'
+        label="Name"
+        value={name}
+        fullWidth
+        variant='outlined'
+        onChange={handleTextField}
+        style={{marginBottom:20}}
+        />
+      <TextField
+        id="lastName"
+        name='lastName'
+        label="LastName"
+        value={lastName}
+        fullWidth
+        variant='outlined'
+        onChange={handleTextField}
+      />        
+    </div>
+  )
+};
+
+export default EditList;

+ 27 - 0
src/components/HomePage/LeftBar/EditBar/SubmitBtn/index.tsx

@@ -0,0 +1,27 @@
+import { makeStyles} from '@material-ui/core'
+import Avatar from '@mui/material/Avatar';
+import DoneIcon from '@mui/icons-material/Done';
+
+const useStyles = makeStyles({
+  avatarArrow: {
+    cursor: 'pointer',
+    marginLeft: 'auto',
+    marginRight: 20,
+    '&:hover': {
+      backgroundColor: 'rgb(62, 149, 231)'
+    }
+  }
+})
+
+const SubmitBtn = ({handleSubmit}:{handleSubmit:() => void}) => {
+  const classes = useStyles()  
+
+  return (
+    <Avatar onClick={handleSubmit} className={classes.avatarArrow}
+      sx={{width: 56, height: 56,backgroundColor: 'rgb(41, 139, 231)',color: '#ffffff'}}>
+      <DoneIcon fontSize="medium" />  
+    </Avatar>        
+  )
+};
+
+export default SubmitBtn;

+ 36 - 0
src/components/HomePage/LeftBar/EditBar/ToolBar/index.tsx

@@ -0,0 +1,36 @@
+import Stack from '@mui/material/Stack';
+import IconButton from '@mui/material/IconButton';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+import { makeStyles, Typography } from '@material-ui/core'
+
+const useStyles = makeStyles({
+  container: {
+    paddingLeft: 10,
+    paddingBottom: 3,
+    width: 482,
+    display: 'flex',
+    alignContent: 'center',
+    alignItems: 'center',
+  },
+  iconArrow: {
+    '&:hover': {
+      transform: 'rotate(360deg)',
+      transition: 'all 250ms ease-out ',
+    }
+  },
+})
+
+const ToolBar = () => {
+  const classes = useStyles()
+
+  return (
+    <Stack className={classes.container} direction="row" spacing={21}>
+      <IconButton aria-label="delete" size="medium">
+        <ArrowBackIcon className={classes.iconArrow} fontSize='medium'/>
+      </IconButton>
+      <Typography style={{marginLeft:20,color: '#474747'}} variant="h6" color="initial">Edit profile</Typography>
+    </Stack>
+    )
+}
+
+export default ToolBar

+ 53 - 0
src/components/HomePage/LeftBar/EditBar/index.tsx

@@ -0,0 +1,53 @@
+import { makeStyles } from '@material-ui/core'
+import { useState,useEffect } from 'react';
+import { useSelector } from 'react-redux';
+import ToolBar from './ToolBar'
+import EditList from './EditList'
+import SubmitBtn from './SubmitBtn';
+import { getState } from '../../../../redux/authorization/selector'
+
+const useStyles = makeStyles({
+    containerAbsolute: {
+        position: 'absolute',
+        top: 58,
+        width: 506,
+        maxHeight: '905px',
+        minHeight: '905px',
+        overflow: 'hidden',
+        backgroundColor: '#f3f2f2',
+    }
+})
+
+const EditBar= () => {
+  const classes = useStyles()
+  const user = useSelector(getState)
+  const [name, setName] = useState<string>('')
+  const [lastName, setLastName] = useState<string>('')
+  const [openBtn, setOpenBtn] = useState<boolean>(false)
+  const {name:Name,lastName:LastName} = user
+
+  const handleSubmit = () => {
+   
+    openBtn&&setOpenBtn(false)
+  }
+
+  
+  useEffect(() => {
+    Name&&setName(Name)
+    LastName && setLastName(LastName)
+  }, [Name, LastName])  
+
+    return (
+    <div>
+      <ToolBar />
+      <div className={classes.containerAbsolute}>
+          <EditList user={user} name={name} setName={setName}
+            lastName={lastName} setLastName={setLastName} 
+            openBtn={openBtn} setOpenBtn={setOpenBtn} />
+          {openBtn&&<SubmitBtn handleSubmit={handleSubmit}/>}
+      </div>
+   </div>
+  )
+}
+
+export default EditBar

+ 44 - 0
src/components/HomePage/LeftBar/SettingsBar/SettingsMenu/index.tsx

@@ -0,0 +1,44 @@
+import { useSelector } from 'react-redux';
+import Paper from '@mui/material/Paper';
+import MenuList from '@mui/material/MenuList';
+import MenuItem from '@mui/material/MenuItem';
+import ListItemText from '@mui/material/ListItemText';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import PhoneIcon from '@mui/icons-material/Phone';
+import { CopyToClipboard } from 'react-copy-to-clipboard';
+import { makeStyles } from '@material-ui/core'
+
+import { getNumber } from '../../../../../redux/authorization/selector'
+import { copied} from '../../../../../helpers';
+
+const useStyles = makeStyles({
+    container: {
+    width: '100%',
+    },
+    list: {
+      background:'#fdfdfd'
+    },
+})
+
+
+const SettingsMenu = () => {
+  const classes = useStyles()
+  const number = useSelector(getNumber)
+
+  return (
+    <Paper className={classes.container}>
+      <MenuList className={classes.list}>
+        <CopyToClipboard onCopy={() => copied('Number')} text={number}>
+           <MenuItem>
+              <ListItemIcon style={{marginRight:15}}>
+                <PhoneIcon fontSize="medium" />
+              </ListItemIcon>
+              <ListItemText primary={number} secondary='Phone' />
+            </MenuItem>
+          </CopyToClipboard>   
+      </MenuList>
+    </Paper>
+  );
+}
+
+export default SettingsMenu

+ 62 - 0
src/components/HomePage/LeftBar/SettingsBar/SettingsPicture/index.tsx

@@ -0,0 +1,62 @@
+import { makeStyles } from '@material-ui/core'
+import { firstLetter,slicedWord,timeStampEU } from '../../../../../helpers'
+import { useSelector } from 'react-redux';
+import { getState } from '../../../../../redux/authorization/selector'
+
+const useStyles = makeStyles({
+  container: {
+    width:'100%'
+  },
+  imgContainer: {
+    position:'relative',
+    width: '100%',
+    height: 468,
+    color: '#ffffff',
+    display: 'flex',
+    justifyContent: 'center',
+    alignContent: 'center',
+    alignItems: 'center',
+    fontSize: 200,
+  },
+  nameTile: {
+    position:'absolute',
+    color: '#ffffff',
+    backgroundColor: '#6e6e6e7d',
+    borderRadius: 10,
+    padding:'0px 6px 2px 6px',
+    fontWeight:600,
+    fontSize: 24,
+    zIndex:10,
+    top: 395,
+    left:35
+  },
+  timeTile: {
+    position:'absolute',
+    color: '#ffffff',
+    backgroundColor:'#6e6e6e7d',
+    borderRadius: 10,
+    padding:'0px 6px 2px 6px',
+    fontSize: 19,
+    fontWeight:600,
+    top: 430,
+    left:35
+  },    
+})
+
+const SettingsPicture = () => {
+  const classes = useStyles()
+  const  { name,lastName,avatarUrl,online,color }  = useSelector(getState)
+  return (
+    <div className={classes.container}>
+      {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>}
+      <span className={classes.nameTile}>{`${firstLetter(name)}${slicedWord(name, 15, 1)}
+        ${firstLetter(lastName)}${slicedWord(lastName, 15, 1)}`}</span>
+      <span className={classes.timeTile}>{online === 'true'?'online':`last seen ${timeStampEU(online)}`}</span>
+    </div>
+  )
+}
+
+export default SettingsPicture

+ 82 - 0
src/components/HomePage/LeftBar/SettingsBar/ToolBar/MenuList/index.tsx

@@ -0,0 +1,82 @@
+import { useState } from 'react';
+import { useDispatch } 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 LogoutIcon from '@mui/icons-material/Logout';
+import MoreVertIcon from '@mui/icons-material/MoreVert';
+
+import { asyncLogout } from '../../../../../../redux/authorization/operations';
+
+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(5),
+    minWidth: 180,
+    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: '4px 4px',
+    },
+    '& .MuiMenuItem-root': {
+      marginBottom: theme.spacing(1),
+      '& .MuiSvgIcon-root': {
+        fontSize: 21,
+        color: theme.palette.text.secondary,
+        marginRight: theme.spacing(4),
+      }
+    },
+  },
+}));
+
+const MenuList = () => {
+  const dispatch = useDispatch()
+  const [anchorEl, setAnchorEl] = useState<any>(null);
+  const open = Boolean(anchorEl);
+  const handleClick = (e: React.MouseEvent<HTMLButtonElement>): void =>
+    setAnchorEl(e.currentTarget)
+
+  const handleClose = (type: string | undefined): void => {
+    if (type === 'logout') dispatch(asyncLogout())
+    setAnchorEl(null)
+  }
+  
+  return (
+    <>
+      <IconButton onClick={handleClick} aria-label="delete"
+        style={{marginLeft:5}} size="medium">
+        <MoreVertIcon fontSize='medium'/>
+      </IconButton>
+      <StyledMenu
+        id="demo-positioned-menu"
+        aria-labelledby="demo-positioned-button"
+        anchorEl={anchorEl}
+        open={open}
+        onClose={handleClose}
+      >
+        <MenuItem style={{fontWeight:500}}  onClick={() => handleClose('logout')}>
+            <LogoutIcon/>
+            Log Out
+        </MenuItem>        
+      </StyledMenu>
+    </>
+  );
+}
+
+export default MenuList

+ 46 - 0
src/components/HomePage/LeftBar/SettingsBar/ToolBar/index.tsx

@@ -0,0 +1,46 @@
+import Stack from '@mui/material/Stack';
+import IconButton from '@mui/material/IconButton';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+import EditIcon from '@mui/icons-material/Edit';
+import MenuList from './MenuList';
+import { makeStyles, Typography } from '@material-ui/core'
+
+const useStyles = makeStyles({
+  container: {
+    width: '100%',
+    maxWidth: '100%',
+    padding:10,
+    display: 'flex',
+    alignContent: 'center',
+    alignItems: 'center',
+  },
+  iconArrow: {
+    '&:hover': {
+      transform: 'rotate(360deg)',
+      transition: 'all 250ms ease-out ',
+    }
+  },
+})
+
+interface IToolBar {
+  setSelectedIndex:(selectedIndex:number | null) => void
+}
+
+const ToolBar = ({setSelectedIndex}:IToolBar) => {
+  const classes = useStyles()
+  const handelEdit = () => setSelectedIndex(4)
+  return (
+    <Stack className={classes.container} direction="row" spacing={21}>
+      <IconButton  aria-label="delete" size="medium">
+        <ArrowBackIcon className={classes.iconArrow} fontSize='medium'/>
+      </IconButton>
+      <Typography style={{ marginLeft: 20, color: '#474747' }} variant="h6" color="initial">Settings</Typography>
+      <IconButton onClick={handelEdit} style={{ marginLeft: 'auto' }}  aria-label="delete" size="medium">
+        <EditIcon  fontSize='medium' /> 
+      </IconButton>
+      <MenuList/>   
+    </Stack>
+    )
+}
+
+export default ToolBar

+ 19 - 0
src/components/HomePage/LeftBar/SettingsBar/index.tsx

@@ -0,0 +1,19 @@
+import ToolBar from "./ToolBar"
+import SettingsPicture from "./SettingsPicture"
+import SettingsMenu from "./SettingsMenu"
+
+interface ISettingsBar {
+  setSelectedIndex:(selectedIndex:number | null) => void
+}
+
+const SettingsBar = ({setSelectedIndex}:ISettingsBar) => {
+  return (
+    <div style={{backgroundColor: '#f3f2f2',height:'100%'}}>
+      <ToolBar setSelectedIndex={setSelectedIndex}/>
+      <SettingsPicture />
+      <SettingsMenu/>
+    </div>
+    )
+}
+
+export default SettingsBar

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

@@ -10,7 +10,8 @@ import ChatsList from './ChatsList'
 import MenuBar from './MenuBar'
 import ContactsList from './ContactsList'
 import AddContact from './AddContact'
-import NotDone from '../../reusableComponents/NotDone'
+import SettingsBar from './SettingsBar';
+import EditBar from './EditBar';
 import { getState } from '../../../redux/authorization/selector'
 
 const LeftBar = () => {
@@ -67,8 +68,9 @@ const LeftBar = () => {
 
     return (
       <Grid item lg={3} onMouseEnter={handleEnterOpenMenuSm} onMouseLeave={handleLeaveCloseMenuSm}>
-        <SearchBar handleClick={handleClick} handleFocus={handleFocus} sort={sort}
-          handleSearch={handleSearch} isSearch={isSearch} selectedIndex={selectedIndex} value={value}/>
+        {selectedIndex !== 2 && selectedIndex !== 4 &&
+          <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
@@ -76,8 +78,9 @@ const LeftBar = () => {
         {isMenu && modalRoot.current &&
           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}/>}
+        {selectedIndex === 2 && <SettingsBar setSelectedIndex={setSelectedIndex}/>}
+        {selectedIndex === 3 && <AddContact setSelectedIndex={setSelectedIndex} />}
+        {selectedIndex === 4 && <EditBar/>}
     </Grid>
     )
 }

+ 0 - 1
src/components/HomePage/RightBar/index.tsx

@@ -3,7 +3,6 @@ import { makeStyles } from '@material-ui/core'
 import HeaderBar from './HeaderBar'
 import ChatBar from './ChatBar'
 import { useSelector } from 'react-redux'
-import { useState } from 'react'
 import { getIsOpen } from '../../../redux/control/selector'
 import { getChatMemo } from '../../../redux/chat/selector'
 

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

@@ -40,11 +40,9 @@ const asyncLogin = (number:string, code: string,cb:() => void ) => async (dispat
 
 const asyncLogout = () => async (dispatch:any) => {
   try {
-    const data = await logoutUser<object>();
-    if (data) {
-     dispatch(actionLogOutSuccess());
-     setToken.unset()
-    }
+    await logoutUser<object>();
+    dispatch(actionLogOutSuccess());
+    setToken.unset()
   } catch (e) {
     dispatch(actionLogOutReject());
   } 

+ 14 - 14
src/typescript/redux/authorization/interfaces.ts

@@ -1,22 +1,22 @@
 
 export interface IAuthorizationState  {
-  name?: string | null,
-  lastName?: string | null,
-  originalName?: string | null,
-  originalLastName?: string | null,
-  avatarUrl?: string | null,
-  color?: string | null,
-  code?: string | null,
-  _id?: string | null,
-  token?: string | null,
+  name: string,
+  lastName: string,
+  originalName: string,
+  originalLastName: string,
+  avatarUrl: string ,
+  color: string,
+  code: string,
+  _id: string ,
+  token: string,
   online: string,
-  number?: string | null ,
-  country?: string | null,
+  number: string,
+  country: string,
   sort: boolean,
   nightMode: boolean,
-  createdAt?: string | null,
-  updatedAt?: string | null,
-  __v?: number | null,
+  createdAt: string,
+  updatedAt: string,
+  __v: number,
 }