Pārlūkot izejas kodu

added page edit my data

makstravm 2 gadi atpakaļ
vecāks
revīzija
55316319b1

+ 6 - 10
src/App.js

@@ -4,22 +4,19 @@ import { Router, Route, Switch, Redirect } from 'react-router-dom';
 import createHistory from "history/createBrowserHistory";
 import { connect, Provider } from 'react-redux';
 import store from './redux/redux-store';
-import { Authorization } from './components/Authorization';
-import { Container, Content, Main } from './pages/Content';
+import { Content, Main } from './pages/Content';
 import { CProfilePage } from './pages/ProfilePage';
-import { CAdd } from './components/main/Add';
 import HeaderComponent from './pages/Header';
 import { CMainPostsFeed } from './pages/MainPostsFeed';
 import { CRRoute } from './helpers';
 import { CPostPage } from './pages/PostPage';
 import { CAllPosts } from './pages/AllPosts';
-import { CEditorPostPage, CEntityEditorPost } from './pages/EntityEditorPost';
+import { CEntityEditorPost } from './pages/EntityEditorPost';
+import { SettingsPage } from './pages/SettingsPage';
+import { Authorization } from './pages/Authorization';
 
 export const history = createHistory()
 
-
-const Aside = () =>
-    <div>sdfsdgsgsdg</div>
 const AppContent = ({ isToken }) =>
     <Router history={history}>
         {!isToken
@@ -36,15 +33,14 @@ const AppContent = ({ isToken }) =>
                     <Switch>
                         <Route path='/' component={CMainPostsFeed} exact />
                         <Route path='/profile/:_id' component={CProfilePage} />
-                        <Route path='/message' component={Aside} />
-                        {/* <Route path='/add' component={CAdd} /> */}
+                        {/* <Route path='/message' component={Aside} /> */}
                         <Route path='/edit/post/:_id' component={CEntityEditorPost} />
+                        <Route path='/my-settings' component={SettingsPage} />
                         <Route path='/all' component={CAllPosts} />
                         <CRRoute path='/post/:id' component={CPostPage} />
                         <Redirect from='/*' to='/' />
                         {/* <Redirect from='/*' to='/post/:id' /> */}
                     </Switch>
-                    {/*  */}
                 </Main>
             </Content >
         }

+ 55 - 2
src/App.scss

@@ -475,13 +475,14 @@ body {
     font-size: 1.2em;
     font-weight: 500;
 }
-
-.ContainEditorPost {
+.ContainerInner {
     width: 100%;
     background-color: $defaultColorW;
     padding: 15px 25px;
     box-shadow: 0 0 6px 2px rgba($defaultColorB, 0.5);
     border-radius: 5px;
+}
+.ContainEditPost {
     .title {
         width: 100%;
         text-align: center;
@@ -567,3 +568,55 @@ body {
 .ant-dropdown {
     box-shadow: 0 0 2px 0 $defaultColorB;
 }
+.avatar-uploader > .ant-upload {
+    width: 150px;
+    height: 150px;
+    border-radius: 50%;
+    position: relative;
+    .edit-icon {
+        position: absolute;
+        top: 0;
+        right: 0;
+    }
+}
+
+.EditMyData {
+    label {
+        display: flex;
+        align-items: flex-end;
+        padding-bottom: 10px;
+        flex-wrap: nowrap;
+    }
+    h4 {
+        margin: 0;
+        padding-right: 10px;
+    }
+    button {
+        display: none;
+        margin: 0 auto;
+        &.--block {
+            display: block;
+        }
+    }
+    &__lable-box {
+        span {
+            display: block;
+            text-align: center;
+        }
+        input.--error {
+            border-color: #ff4d4f;
+            max-width: 100%;
+        }
+        .EditMyData__lable-text {
+            font-size: 1.3em;
+            display: inline-block;
+            padding: 0 10px;
+            span {
+                display: inline-block;
+            }
+            svg {
+                margin-left: 10px;
+            }
+        }
+    }
+}

+ 12 - 2
src/actions/index.js

@@ -39,8 +39,10 @@ export const actionAboutMeAC = (data) => ({ type: 'ABOUTME-DATA-ADD', data })
 
 export const actionFullAboutMe = () => ({ type: 'ABOUT_ME' })
 
+export const actionFullAboutMeUpsert = (nick, login) => ({ type: 'ABOUT_ME_UPSERT', nick, login })
+
 export const actionAboutMe = (id) =>
-actionPromise('aboutMe', gql(`query userOned($myID:String!){
+    actionPromise('aboutMe', gql(`query userOned($myID:String!){
                         UserFindOne(query: $myID){
                             _id  login nick
                             avatar { _id url }
@@ -48,6 +50,14 @@ actionPromise('aboutMe', gql(`query userOned($myID:String!){
                         }
                 }`, { myID: JSON.stringify([{ _id: id }]) }))
 
+export const actionUpsertAboutMe = (myData) =>
+    actionPromise('upsertAboutMe', gql(`mutation editAboutMe($user:UserInput){
+                        UserUpsert(user:$user){
+                            _id   _id  login nick
+                            avatar { _id url }
+                            following{ _id}
+                        }
+                }`, { user: myData }))
 
 //*************** Action Posts Feed ******************//
 
@@ -347,7 +357,7 @@ export const actionGetAvatar = (id) =>
         UserFindOne(query: $myID) {
                             avatar { _id url }
         }
-    }`, { myID: JSON.stringify([{ ___owner: id }]) }))
+    }`, { myID: JSON.stringify([{ _id: id }]) }))
 
 
 //****************--- Find FOllowing/Follovwrs---*************************//

+ 6 - 25
src/components/Authorization.jsx

@@ -1,13 +1,10 @@
-import React  from 'react'
-import authBg from '../images/authBg.png'
+import React from 'react'
 import { connect } from 'react-redux'
-import { NavLink} from 'react-router-dom'
-
-import { Form, Input, Button, Row, Col, Card, Divider, Checkbox } from 'antd';
+import { Form, Input, Button, Checkbox } from 'antd';
 import { UserOutlined, LockOutlined } from '@ant-design/icons';
 import { actionFullLogIn, actionFullRegister } from '../actions';
 
-const FormInput = ({ buttonTitle, onSignIn }) => {
+const FormAuthorization = ({ buttonTitle, onSignIn }) => {
     const onFinish = ({ login, password, remember }) => {
         onSignIn(login, password, remember)
     };
@@ -65,25 +62,9 @@ const FormInput = ({ buttonTitle, onSignIn }) => {
         </Form>
     )
 }
-const CLoginForm = connect(null, { onSignIn: actionFullLogIn})(FormInput)
-const CRegisterForm = connect(null, { onSignIn: actionFullRegister})(FormInput)
+export const CLoginForm = connect(null, { onSignIn: actionFullLogIn })(FormAuthorization)
+export const CRegisterForm = connect(null, { onSignIn: actionFullRegister })(FormAuthorization)
+
 
-export const Authorization = ({ match: { params: { _id } } }) => {
-    return (
-        <div className='Authorization' style={{ backgroundImage: `url(${authBg})` }}>
-            <Row justify="end" align="middle" className='Authorization__form'>
-                <Col >
-                    <Card style={{ width: 380 }} >
-                        <NavLink activeClassName='active' to={`/auth/login`}><span>Log In</span></NavLink>
-                        <Divider type="vertical" />
-                        <NavLink activeClassName='active' to={'/auth/registration'}>Registration</NavLink>
-                        <Divider>{_id === 'login' ? 'Log in' : 'Registration'}</Divider >
-                        {_id === 'login' ? <CLoginForm buttonTitle={'Sign In'} /> : <CRegisterForm buttonTitle={'Sign up'} />}
-                    </Card>
-                </Col>
-            </Row >
-        </div>
-    )
-}
 
 

+ 2 - 2
src/components/header/Search.jsx

@@ -2,9 +2,9 @@ import { Empty, Input, Popover } from 'antd'
 import React from 'react'
 import { connect } from 'react-redux';
 import { Link } from 'react-router-dom';
-import { actionFindUsers, actionSearchUsers } from '../../actions';
-import { UserAvatar } from '../../pages/Header';
+import {  actionSearchUsers } from '../../actions';
 import { SearchOutlined } from '@ant-design/icons';
+import { UserAvatar } from './UserAvatar';
 const FindUsersResult = ({ usersRes }) =>
     <div className='Header__search-drop' >
         {

+ 18 - 0
src/components/header/UserAvatar.js

@@ -0,0 +1,18 @@
+import Avatar from "antd/lib/avatar/avatar"
+import { backURL } from "../../helpers"
+import noAva from "../../images/noAva.png"
+
+export const UserAvatar = ({ avatarSize, avatar }) => {
+    return (
+        <>
+            <Avatar style={{
+                width: avatarSize,
+                height: avatarSize
+            }}
+                src={avatar && avatar?.url
+                    ? <img src={(backURL + '/' + avatar.url)} alt='avatar' />
+                    : <img src={noAva} alt="avatar"/>
+                } />
+        </>
+    )
+}

+ 0 - 149
src/components/main/Add.js

@@ -1,149 +0,0 @@
-import { useState } from 'react';
-import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
-import { connect } from 'react-redux';
-import { Upload, message } from 'antd';
-import { backURL, gql } from '../../helpers';
-import { actionUpdateAvatar } from '../../actions';
-import { Apps } from '../uploadPhoto';
-
-const Add = ({ imageUrl, onUploadFile }) => {
-    const [loading, setLoading] = useState(false)
-    const [imageLoad, setImageLoad] = useState(false)
-    const props = {
-        name: 'photo',
-        action: `${backURL}/upload`,
-        headers: localStorage.authToken || sessionStorage.authToken ? { Authorization: 'Bearer ' + (localStorage.authToken || sessionStorage.authToken) } : {}
-    }
-
-    const handleChange = async ({ file }) => {
-
-        if (file.status === 'uploading') {
-            setLoading(true)
-        }
-        if (file.status === 'done') {
-            message.success(`${file.name} file uploaded successfully`);
-            await onUploadFile(file.response)
-            console.log(file);
-            setImageLoad(true)
-            setLoading(false)
-        } else if (file.status === 'error') {
-            message.error(`${file.name} file upload failed.`);
-        }
-    }
-
-    return (
-        <>
-            <Upload {...props}
-                listType="picture-card"
-                showUploadList={false}
-                onChange={handleChange}
-                className="avatar-uploader">
-                {imageLoad ?
-                    <img src={`${backURL + '/' + imageUrl}`} alt="avatar" style={{ width: '100%' }} /> :
-                    <div>
-                        {loading ? <LoadingOutlined /> : <PlusOutlined />}
-                        <div style={{ marginTop: 8 }}>Upload</div>
-                    </div>}
-            </Upload>
-            <hr />
-            <hr />
-            <hr />
-            <hr />
-            {/* <Apps /> */}
-        </>
-
-    )
-}
-
-export const CAdd = connect(state => ({ imageUrl: state?.myData?.avatar?.url }), { onUploadFile: actionUpdateAvatar })(Add)
-
-
-
-
-// function getBase64(file) {
-//   return new Promise((resolve, reject) => {
-//     const reader = new FileReader();
-//     reader.readAsDataURL(file);
-//     reader.onload = () => resolve(reader.result);
-//     reader.onerror = error => reject(error);
-//   });
-// }
-
-// class PicturesWall extends React.Component {
-//   state = {
-//     previewVisible: false,
-//     previewImage: '',
-//     fileList: [
-//       {
-//         uid: '-1',
-//         name: 'image.png',
-//         status: 'done',
-//         url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
-//       },
-//       {
-//         uid: '-2',
-//         name: 'image.png',
-//         status: 'done',
-//         url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
-//       },
-//       {
-//         uid: '-3',
-//         name: 'image.png',
-//         status: 'done',
-//         url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
-//       },
-//       {
-//         uid: '-4',
-//         name: 'image.png',
-//         status: 'done',
-//         url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
-//       },
-//       {
-//         uid: '-5',
-//         name: 'image.png',
-//         status: 'error',
-//       },
-//     ],
-//   };
-
-//   handleCancel = () => this.setState({ previewVisible: false });
-
-//   handlePreview = async file => {
-//     if (!file.url && !file.preview) {
-//       file.preview = await getBase64(file.originFileObj);
-//     }
-
-//     this.setState({
-//       previewImage: file.url || file.preview,
-//       previewVisible: true,
-//     });
-//   };
-
-//   handleChange = ({ fileList }) => this.setState({ fileList });
-
-//   render() {
-//     const { previewVisible, previewImage, fileList } = this.state;
-//     const uploadButton = (
-//       <div>
-//         <Icon type="plus" />
-//         <div className="ant-upload-text">Upload</div>
-//       </div>
-//     );
-//     return (
-//       <div className="clearfix">
-//         <Upload
-//           action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
-//           listType="picture-card"
-//           fileList={fileList}
-//           onPreview={this.handlePreview}
-//           onChange={this.handleChange}
-//         >
-//           {fileList.length >= 8 ? null : uploadButton}
-//         </Upload>
-//         <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
-//           <img alt="example" style={{ width: '100%' }} src={previewImage} />
-//         </Modal>
-//       </div>
-//     );
-//   }
-// }

+ 1 - 1
src/components/main/post/PostTitle.js

@@ -2,7 +2,7 @@ import { Col, Row, Button, Dropdown, Menu } from 'antd'
 import { MoreOutlined } from '@ant-design/icons'
 import { Link } from 'react-router-dom'
 import { connect } from 'react-redux'
-import { UserAvatar } from '../../../pages/Header'
+import { UserAvatar } from '../../header/UserAvatar'
 
 const MenuOverlay = ({ postId }) =>
     <Menu>

+ 35 - 0
src/components/main/profilePage/EditAvatar.js

@@ -0,0 +1,35 @@
+import { EditOutlined,} from '@ant-design/icons';
+import { connect } from 'react-redux';
+import { Upload, message, } from 'antd';
+import {  propsUploadFile } from '../../../helpers';
+import { actionUpdateAvatar } from '../../../actions';
+import ImgCrop from 'antd-img-crop';
+import { UserAvatar } from '../../header/UserAvatar';
+
+
+const EditAvatar = ({ avatar, onUploadFile }) => {
+    const handleChange = ({ file }) => {
+        if (file.status === 'done') {
+            message.success(`${file.name} file uploaded successfully`);
+            onUploadFile(file.response)
+        } else if (file.status === 'error') {
+            message.error(`${file.name} file upload failed.`);
+        }
+    }
+    return (
+        <ImgCrop rotate shape='round'>
+            <Upload {...propsUploadFile}
+                listType="picture-card"
+                showUploadList={false}
+                onChange={handleChange}
+                className="avatar-uploader">
+                <UserAvatar avatarSize={'150px'} avatar={avatar} />
+                <span className='edit-icon'>
+                    <EditOutlined style={{ fontSize: '1.4em', color: '#1890ff ' }} />
+                </span>
+            </Upload>
+        </ImgCrop>
+    )
+}
+
+export const CEditAvatar = connect(state => ({ avatar: state?.myData?.avatar }), { onUploadFile: actionUpdateAvatar })(EditAvatar)

+ 1 - 1
src/components/main/profilePage/ModalFollow.js

@@ -4,7 +4,7 @@ import { useEffect } from 'react';
 import { connect } from 'react-redux';
 import { Link } from 'react-router-dom';
 import { actionFindFollowers, actionFindFollowing, actionFindLiked } from '../../../actions';
-import { UserAvatar } from '../../../pages/Header';
+import { UserAvatar } from '../../header/UserAvatar';
 
 
 const ModalFolower = ({ id, status, statusModal, data, title, follow }) => {

+ 9 - 17
src/components/uploadPhoto/EditDescriptionPost.js

@@ -16,9 +16,8 @@ export const EditDescriptionPost = ({ description, setDescription }) => {
     useEffect(() => {
         setText(description || 'Enter descriptin')
     }, [description]);
-    
 
-    const addTaskHandler = () => {
+    const addValueHandler = () => {
         if (text.trim() !== '') {
             setDescription(text)
             setEditMode(false)
@@ -27,31 +26,24 @@ export const EditDescriptionPost = ({ description, setDescription }) => {
             setDescription('')
         }
     }
-    const textInputHandler = () => {
-        setEditMode(true)
-    }
-
-    const textInputHandlerClose = () => {
-        addTaskHandler()
-    }
 
-    const onChangeTask = (e) => {
+    const onChangeInput = (e) => {
         setText(e.currentTarget.value)
         setError(false)
     }
 
-    const onKeyPressAddTask = (e) => {
+    const onKeyPressAdd = (e) => {
         if (e.shiftKey && e.charCode === 13) {
             setText(text += `'\n'`)
         } else if (e.charCode === 13) {
-            addTaskHandler()
+            addValueHandler()
         }
     }
     return (
         <>
             <Divider orientation="left" orientationMargin="0">
                 <Title level={3}>Description
-                    <Button type="link" onClick={textInputHandler}><EditOutlined /></Button></Title>
+                    <Button type="link" onClick={() => setEditMode(true)}><EditOutlined /></Button></Title>
             </Divider>
             {error && <Text type="danger">Field must not be empty</Text>}
             {editMode
@@ -59,11 +51,11 @@ export const EditDescriptionPost = ({ description, setDescription }) => {
                     placeholder="Description"
                     autoSize={{ minRows: 3, maxRows: 5 }}
                     value={text}
-                    onChange={onChangeTask}
-                    autoFocus onBlur={textInputHandlerClose}
-                    onKeyPress={onKeyPressAddTask}
+                    onChange={onChangeInput}
+                    autoFocus onBlur={() => addValueHandler()}
+                    onKeyPress={onKeyPressAdd}
                 />
-                : <Paragraph className="description" onDoubleClick={textInputHandler}>
+                : <Paragraph className="description" onDoubleClick={() => setEditMode(true)}>
                     {text}
                 </Paragraph>
             }

+ 19 - 28
src/components/uploadPhoto/index.js

@@ -1,16 +1,14 @@
-import { DeleteOutlined, EyeOutlined, InboxOutlined, LoadingOutlined, PlusOutlined } from "@ant-design/icons";
-import { Button, message, Icon, Upload, Image, Progress } from "antd";
+import { DeleteOutlined, EyeOutlined, InboxOutlined } from "@ant-design/icons";
+import { Button, message, Image, Progress } from "antd";
 import Dragger from "antd/lib/upload/Dragger";
 import React, { useState } from "react";
-import ReactDOM from "react-dom";
-import ImgCrop from 'antd-img-crop';
 import {
     arrayMove,
     SortableContainer,
     SortableElement,
     SortableHandle
 } from "react-sortable-hoc";
-import { backURL } from "../../helpers";
+import { backURL, propsUploadFile } from "../../helpers";
 
 
 const SortableItemMask = ({ removePhotosItem, setVisible, id }) =>
@@ -45,13 +43,7 @@ const Handle = SortableHandle(({ tabIndex, value, removePhotosItem }) => {
     )
 })
 
-//     < Progress
-// strokeColor = {{
-//     '0%': '#108ee9',
-//         '100%': '#87d068',
-//       }}
-// percent = { 99.9}
-//     />
+
 const SortableItem = SortableElement(props => {
     const { value, removePhotosItem } = props
     return (
@@ -61,11 +53,6 @@ const SortableItem = SortableElement(props => {
     );
 });
 
-const props = {
-    name: 'photo',
-    action: `${backURL}/upload`,
-    headers: localStorage.authToken || sessionStorage.authToken ? { Authorization: 'Bearer ' + (localStorage.authToken || sessionStorage.authToken) } : {},
-}
 
 const SortableList = SortableContainer(({ items, ...restProps }) => {
     return (
@@ -104,10 +91,9 @@ export function EditPhotos({ photos, setPhotos }) {
 
     return (
         <div className="EditPhotos" >
-
-
             {photos.length >= 8 ? null
-                : <Dragger {...props} className="EditPhotos__box"
+                : <Dragger {...propsUploadFile}
+                    className="EditPhotos__box"
                     multiple={true}
                     listType="picture-card"
                     showUploadList={false}
@@ -115,16 +101,21 @@ export function EditPhotos({ photos, setPhotos }) {
                     <p className="ant-upload-drag-icon">
                         <InboxOutlined />
                     </p>
-                    <p className="ant-upload-text">Click or drag file to this area to upload</p>
+                    <p className="ant-upload-text">
+                        Click or drag file to this area to upload
+                    </p>
                 </Dragger>
             }
-            {loading && < Progress showInfo={false} percent={progress}
-                strokeColor={{
-                    '0%': '#10136c',
-                    '50%': '#755596',
-                    '100%': '#fdc229',
-                }}
-            />}
+            {loading &&
+                <Progress
+                    showInfo={false}
+                    percent={progress}
+                    strokeColor={{
+                        '0%': '#10136c',
+                        '50%': '#755596',
+                        '100%': '#fdc229',
+                    }}
+                />}
             <SortableList
                 shouldUseDragHandle={true}
                 useDragHandle

+ 11 - 20
src/components/uploadPhoto/EditTitlePost.js

@@ -12,11 +12,12 @@ export const EditTitlePost = ({ titleSend, setTitleSend }) => {
     const [title, setTitle] = useState(titleSend || 'Enter title')
     const [error, setError] = useState(false)
     const [editMode, setEditMode] = useState(false)
+
     useEffect(() => {
         setTitle(titleSend || 'Enter title')
     }, [titleSend]);
 
-    const addTaskHandler = () => {
+    const addValueHandler = () => {
         if (title.trim() !== '') {
             setTitleSend(title.trim())
             setEditMode(false)
@@ -25,43 +26,33 @@ export const EditTitlePost = ({ titleSend, setTitleSend }) => {
             setTitleSend('')
         }
     }
-    const titleInputHandler = () => {
-        setEditMode(true)
-    }
-
-    const titleInputHandlerClose = () => {
-        addTaskHandler()
-    }
 
-    const onChangeTask = (e) => {
+    const onChangeInput = (e) => {
         setTitle(e.currentTarget.value)
         setError(false)
     }
 
-    const onKeyPressAddTask = (e) => {
-        if (e.charCode === 13) {
-            addTaskHandler()
-        }
-    }
+    const onKeyPressAdd = (e) => e.charCode === 13 && addValueHandler()
+
+
     return (
         <>
             <Divider orientation="left" orientationMargin="0">
                 <Title level={3}>Title
-                    <Button type="link" onClick={titleInputHandler}><EditOutlined /></Button></Title>
+                    <Button type="link" onClick={() => setEditMode(true)}><EditOutlined /></Button></Title>
             </Divider>
             {error && <Text type="danger">Field must not be empty</Text>}
             {editMode
                 ? <Input
                     value={title}
                     placeholder="title"
-                    onChange={onChangeTask}
-                    autoFocus onBlur={titleInputHandlerClose}
-                    onKeyPress={onKeyPressAddTask}
+                    onChange={onChangeInput}
+                    autoFocus onBlur={() => addValueHandler()}
+                    onKeyPress={onKeyPressAdd}
                 />
-                : <Title level={5} onDoubleClick={titleInputHandler}>
+                : <Title level={5} onDoubleClick={() => setEditMode(true)}>
                     {title}
                 </Title>
             }
-   
         </>)
 }

+ 13 - 5
src/helpers/index.js

@@ -3,7 +3,13 @@ import { useEffect } from 'react';
 import { connect } from 'react-redux';
 import { Route } from 'react-router-dom';
 
+export const backURL = 'http://hipstagram.asmer.fs.a-level.com.ua'
 
+export const propsUploadFile = {
+    name: 'photo',
+    action: `${backURL}/upload`,
+    headers: localStorage.authToken || sessionStorage.authToken ? { Authorization: 'Bearer ' + (localStorage.authToken || sessionStorage.authToken) } : {}
+}
 
 export const jwtDecode = (token) => {
     try {
@@ -16,16 +22,17 @@ export const jwtDecode = (token) => {
     }
 }
 
-export const backURL = 'http://hipstagram.asmer.fs.a-level.com.ua'
-
 const getGQL = url =>
     async (query, variables = {}) => {
         let obj = await fetch(url, {
             method: 'POST',
             headers: {
                 "Content-Type": "application/json",
-                ...(localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } :
-                    sessionStorage.authToken ? { Authorization: 'Bearer ' + sessionStorage.authToken } : {})
+                ...(localStorage.authToken
+                    ? { Authorization: 'Bearer ' + localStorage.authToken }
+                    : sessionStorage.authToken
+                        ? { Authorization: 'Bearer ' + sessionStorage.authToken }
+                        : {})
             },
             body: JSON.stringify({ query, variables })
         })
@@ -42,7 +49,8 @@ const CircularGallerySvg = () =>
         <path d="M34.8 29.7V11c0-2.9-2.3-5.2-5.2-5.2H11c-2.9 0-5.2 2.3-5.2 5.2v18.7c0 2.9 2.3 5.2 5.2 5.2h18.7c2.8-.1 5.1-2.4 5.1-5.2zM39.2 15v16.1c0 4.5-3.7 8.2-8.2 8.2H14.9c-.6 0-.9.7-.5 1.1 1 1.1 2.4 1.8 4.1 1.8h13.4c5.7 0 10.3-4.6 10.3-10.3V18.5c0-1.6-.7-3.1-1.8-4.1-.5-.4-1.2 0-1.2.6z"></path>
     </svg>
 
-export const CircularGalleryIcon = props => <Icon component={CircularGallerySvg} {...props} />
+export const CircularGalleryIcon = props =>
+    <Icon component={CircularGallerySvg} {...props}/>
 
 const RRoute = ({ action, component: Component, ...routeProps }) => {
     const WrapperComponent = (componentProps) => {

+ 25 - 0
src/pages/Authorization.jsx

@@ -0,0 +1,25 @@
+import { Card, Col, Divider, Row } from "antd";
+import { NavLink } from "react-router-dom";
+import { CLoginForm, CRegisterForm } from "../components/FormAuthorization";
+import authBg from "../images/authBg.png"
+
+export const Authorization = ({ match: { params: { _id } } }) =>
+    <div className='Authorization' style={{ backgroundImage: `url(${authBg})` }}>
+        <Row justify="end" align="middle" className='Authorization__form'>
+            <Col >
+                <Card style={{ width: 380 }} >
+                    <NavLink activeClassName='active' to={`/auth/login`}><span>Log In</span></NavLink>
+                    <Divider type="vertical" />
+                    <NavLink activeClassName='active' to={'/auth/registration'}>Registration</NavLink>
+                    <Divider>
+                        {_id === 'login'
+                            ? 'Log in'
+                            : 'Registration'}
+                    </Divider >
+                    {_id === 'login'
+                        ? <CLoginForm buttonTitle={'Sign In'} />
+                        : <CRegisterForm buttonTitle={'Sign up'} />}
+                </Card>
+            </Col>
+        </Row >
+    </div>

+ 9 - 20
src/pages/EntityEditorPost.jsx

@@ -1,26 +1,20 @@
-import { Button, Divider, Input, message } from "antd"
+import { Button, Divider,  message } from "antd"
 import Title from "antd/lib/typography/Title"
 import { useEffect, useState } from "react"
 import { connect } from "react-redux"
 import { actionFindPostOne, actionFullSentPost, actionRemovePostsFeedAC } from "../actions"
-import { EditPhotos } from "../components/uploadPhoto"
+import { EditPhotos } from "../components/uploadPhoto/EditPhotos"
 import { EditDescriptionPost } from "../components/uploadPhoto/EditDescriptionPost"
 import { EditTitlePost } from "../components/uploadPhoto/EditTitlePost"
 import { Container } from "./Content"
 import { history } from '../App'
 
 
-
-
 const ContainEditorPost = ({ children }) =>
-    <div className='ContainEditorPost'>{children}</div>
-
-
-
-
-
+    <div className='ContainEditPost ContainerInner'>{children}</div>
 
 const EntityEditorPost = ({ match: { params: { _id } }, myID, entity, status, onSave, findPostOne, clearState }) => {
+
     const [photos, setPhotos] = useState(entity?.images || []);
     const [titleSend, setTitleSend] = useState(entity?.title || '')
     const [description, setDescription] = useState(entity?.text || '');
@@ -45,16 +39,13 @@ const EntityEditorPost = ({ match: { params: { _id } }, myID, entity, status, on
             history.push(`/profile/${myID}`)
         }
     }, [status])
-    const disabledBtn = photos.length && titleSend && description ? false : true
-
-    const sentPost = () => {
-        onSave(photos, titleSend, description)
 
-    }
+    const disabledBtn = photos.length && titleSend && description ? false : true
+    const sentPost = () => onSave(photos, titleSend, description)
 
     return (
-        <Container >
-            <ContainEditorPost>
+        <Container>
+            <ContainEditorPost >
                 <h1 className="title" level={1}>Create / edit Post</h1>
                 <Divider orientation="left" orientationMargin="0"><Title level={3}>Photos</Title></Divider>
                 <EditPhotos photos={photos} setPhotos={setPhotos} />
@@ -75,6 +66,4 @@ export const CEntityEditorPost = connect(state => ({
         onSave: actionFullSentPost,
         findPostOne: actionFindPostOne,
         clearState: actionRemovePostsFeedAC,
-    })(EntityEditorPost)
-
-
+    })(EntityEditorPost)

+ 3 - 19
src/pages/Header.jsx

@@ -1,35 +1,19 @@
 import React from 'react'
 import logo from '../logo.svg';
-import noAva from '../images/noAva.png'
 import { Link } from 'react-router-dom';
 import { CFieldSearch } from '../components/header/Search';
 import { connect } from 'react-redux';
 import { actionAuthLogout } from '../actions';
-import { backURL } from '../helpers';
 import Layout, { Header } from 'antd/lib/layout/layout';
-import { Avatar, Col, Menu, Popover, Row } from 'antd';
+import {  Col, Menu, Popover, Row } from 'antd';
 import { UserOutlined, CompassOutlined, SettingOutlined, HomeOutlined, ImportOutlined, MessageOutlined, PlusCircleOutlined } from '@ant-design/icons/lib/icons';
+import { UserAvatar } from '../components/header/UserAvatar';
 
 const UserNav = () =>
     <div className='UserNav'>
         <CUserNavIcon />
     </div>
 
-export const UserAvatar = ({ avatarSize, avatar }) => {
-    return (
-        <>
-            <Avatar style={{
-                width: avatarSize,
-                height: avatarSize
-            }}
-                src={avatar && avatar?.url ?
-                    <img src={(backURL + '/' + avatar.url)} alt='avatar' /> :
-                    <img src={noAva} />
-                } />
-
-        </>
-    )
-}
 
 
 const ProfileDropMenu = ({ myID, onLogOut }) =>
@@ -38,7 +22,7 @@ const ProfileDropMenu = ({ myID, onLogOut }) =>
             <Link to={`/profile/${myID}`}><UserOutlined /> My Profile</Link>
         </Menu.Item>
         <Menu.Item key={'1'}>
-            <Link to={'/my-settigs'}><SettingOutlined /> Settings</Link>
+            <Link to={'/my-settings'}><SettingOutlined /> Settings</Link>
         </Menu.Item>
         <Menu.Divider />
         <Menu.Item key={'2'}>

+ 4 - 4
src/pages/PostPage.jsx

@@ -2,17 +2,17 @@ import React, { useState } from 'react'
 import { Divider } from 'antd';
 import { connect } from 'react-redux'
 import PostImage from '../components/main/postsFeed/PostImage'
-import { PostTitle, PostDescription } from './MainPostsFeed';
+import { PostDescription } from './MainPostsFeed';
 import Text from 'antd/lib/typography/Text';
 import { CFieldCommentSend, CFieldSubCommentSend } from '../components/main/postsFeed/FieldComment';
 import { CPostUserPanel } from '../components/main/postsFeed/PostUserPanel';
 import { Comment, Tooltip } from 'antd';
 import moment from 'moment';
-import { UserAvatar } from './Header';
 import { Link } from 'react-router-dom';
 import { LikeFilled, LikeOutlined } from '@ant-design/icons';
 import { actionLikeComment, actionDelLikeComment, actionSubComment } from '../actions';
 import { CPostTitle } from '../components/main/post/PostTitle';
+import { UserAvatar } from '../components/header/UserAvatar';
 
 
 const PostPageTitle = ({ data: { owner }, postId }) =>
@@ -88,9 +88,9 @@ const CPostComment = connect(state => ({
 }
 )(PostComment)
 
-const CPostSubComment = connect(state => ({ comments: state?.postsFeed?.SubComments }, {
+const CPostSubComment = connect(state => ({ comments: state?.postsFeed?.SubComments }), {
     findSubComment: actionSubComment,
-}))(PostComment)
+})(PostComment)
 
 const PostComments = ({ comments }) => {
     return (

+ 1 - 1
src/pages/ProfilePage.jsx

@@ -3,12 +3,12 @@ import { Button, Col, Row } from 'antd'
 import { connect } from 'react-redux'
 import { Link } from 'react-router-dom'
 import { actionProfilePageData, actionRemovePostsFeedAC, actionSubscribe, actionUnSubscribe } from '../actions'
-import { UserAvatar } from './Header'
 import { CModalFollowers, CModalFollowing } from '../components/main/profilePage/ModalFollow'
 import { DateCreated } from '../components/main/DateCreated'
 import Text from 'antd/lib/typography/Text'
 import { Container } from './Content'
 import { CPosts } from '../components/main/Posts'
+import { UserAvatar } from '../components/header/UserAvatar'
 
 const ProfileFollowButton = ({ myID, userId, followers, onSubsuscribe, onUnSubsuscribe }) => {
     const followCheck = followers.find(f => f._id === myID && true)

+ 129 - 0
src/pages/SettingsPage.jsx

@@ -0,0 +1,129 @@
+import React, { useEffect, useState } from 'react';
+import { Container } from './Content';
+import { CEditAvatar } from '../components/main/profilePage/EditAvatar'
+import { Button, Col, Divider, Input, message, Row } from 'antd'
+import Title from 'antd/lib/typography/Title';
+import { connect } from 'react-redux';
+import { EditOutlined } from '@ant-design/icons';
+import Text from 'antd/lib/typography/Text';
+import { actionFullAboutMeUpsert } from '../actions';
+
+
+const ContainerSettingsPage = ({ children }) =>
+    <div className="SettingsPage ContainerInner">{children}</div>
+
+
+const EditMyDataIput = ({ title, propValue, propHandler, check }) => {
+    const [value, setValue] = useState(propValue);
+    const [editMode, setEditMode] = useState(false);
+    const [error, setError] = useState(false);
+
+    useEffect(() => {
+        setValue(propValue)
+    }, [propValue]);
+
+    const addValueHandler = () => {
+        const valid = /^[A-Z][a-z0-9_]{1,15}$/
+        if (valid.test(value)) {
+            propHandler(value)
+            setEditMode(false)
+            check(false)
+        } else {
+            setError(true)
+        }
+    }
+
+    const onChangeInput = (e) => {
+        setValue(e.currentTarget.value)
+        setError(false)
+    }
+
+    return (
+        <label onDoubleClick={() => setEditMode(true)}>
+            <Title level={4}>{title} :</Title>
+            <div className='EditMyData__lable-box'>
+                {error && <Text type='danger'> First letter is capitalized!!!</Text>}
+                {!editMode
+                    ? <Text className='EditMyData__lable-text'>{value}
+                        <EditOutlined
+                            onClick={() => setEditMode(true)}
+                            style={{ fontSize: '1.1em', color: '#1890ff ' }} />
+                    </Text>
+                    : <Input className={error && '--error'} value={value}
+                        onBlur={addValueHandler}
+                        onChange={onChangeInput}
+                        onPressEnter={addValueHandler}
+                        autoFocus />
+                }
+            </div>
+        </label>
+    )
+}
+
+const EditMyData = ({ myData, status, onUpsert }) => {
+
+    const [nick, setNick] = useState(myData?.nick || '');
+    const [login, setLogin] = useState(myData?.login || '');
+    const [checkEdit, setChekEdit] = useState(true);
+    useEffect(() => {
+        setNick(myData?.nick || '')
+        setLogin(myData?.login || '')
+    }, [myData])
+
+    useEffect(() => {
+        if (status === "RESOLVED") {
+            message.success({
+                content: 'User data updated',
+                className: 'custom-class',
+                style: {
+                    marginTop: '10vh',
+                },
+            });
+            setChekEdit(true)
+        } else if(status=== 'REJECTED'){
+            message.error({
+                content: 'Что-то не так, нужно повторить!',
+                className: 'custom-class',
+                style: {
+                    marginTop: '10vh',
+                },
+            });
+        }
+    }, [status])
+
+    const onSendEdit = () => onUpsert(nick, login)
+
+
+
+
+    return (
+        <>
+            <EditMyDataIput title='Nick' propValue={nick} propHandler={setNick} check={setChekEdit} />
+            <EditMyDataIput title='Login' propValue={login} propHandler={setLogin} check={setChekEdit} />
+            <Button type='primary'
+                disabled={nick && login ? false : true}
+                className={!checkEdit && '--block'}
+                onClick={onSendEdit}> SendEdit</Button>
+        </>
+    )
+}
+
+const CEditMyData = connect(state => ({ myData: state?.myData, status: state?.promise?.upsertAboutMe?.status }), { onUpsert: actionFullAboutMeUpsert })(EditMyData)
+
+export const SettingsPage = () => {
+    return (
+        <Container>
+            <ContainerSettingsPage>
+                <Divider><Title level={2}>Profile Settings</Title></Divider>
+                <Row >
+                    <Col flex={1}>
+                        <CEditAvatar />
+                    </Col>
+                    <Col flex={4} offset={1} className='EditMyData'>
+                        <CEditMyData />
+                    </Col>
+                </Row>
+            </ContainerSettingsPage>
+        </Container>
+    )
+};

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 20 - 3
src/redux/saga/index.js