Browse Source

finish render post, add comments, fix render and thunk added/ remove Likes Post

makstravm 3 years ago
parent
commit
af43b3bd3f
5 changed files with 171 additions and 160 deletions
  1. 13 0
      src/App.scss
  2. 41 50
      src/actions/index.js
  3. 1 1
      src/components/Authorization.jsx
  4. 94 43
      src/components/main/MainPostFeed.js
  5. 22 66
      src/redux/postFeed-reducer.js

+ 13 - 0
src/App.scss

@@ -191,4 +191,17 @@ select {
             display: block;
         }
     }
+    &__comments {
+        a {
+            font-size: 1.1em;
+            color: #000;
+            font-weight: 500;
+        }
+    }
+    &__send-comment {
+        button{
+            border: none;
+            box-shadow: none;
+        }
+    }
 }

+ 41 - 50
src/actions/index.js

@@ -1,68 +1,50 @@
-import { actionAuthLogin } from "../redux/auth-reducer";
 import { gql } from "../helpers";
+import { actionPromise } from "../redux/redux-thunk";
 
 
 
-const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
-const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
-const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
+export const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
+export const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
+export const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
 
-export const actionPromise = (name, promise) =>
-    async dispatch => {
-        dispatch(actionPending(name))
-        try {
-            let data = await promise
-            dispatch(actionResolved(name, data))
-            return data
-        }
-        catch (error) {
-            dispatch(actionRejected(name, error))
-        }
-    }
 
+export const actionAddPostsFeedAC = (addPosts, myLikes) => ({ type: 'ADD-POST-FEED', addPosts, myLikes })
+export const actionAddLikePostAC = (postId, newResult) => ({ type: 'ADD-POST-LIKE', postId, newResult })
+export const actionRemoveLikePostAC = (postId, newResult) => ({ type: 'REMOVE-POST-LIKE', postId, newResult })
+export const actionAddCommentAC = (postId, newResult) => ({ type: 'ADD-COMMENT', postId, newResult })
+
+//****************---Action Authirization ---*************************//
 
 export const actionLogin = (login, password) =>
     actionPromise('login', gql(`query login($login:String!, $password:String!){
             login(login:$login, password:$password)
         }`, { login, password }))
 
-export const actionFullLogin = (login, password, remember) =>
-    async dispatch => {
-        let token = await dispatch(actionLogin(login, password))
-        if (token) {
-            dispatch(actionAuthLogin(token, remember))
-        }
-    }
-
-const actionRegister = (login, password) =>
+export const actionRegister = (login, password) =>
     actionPromise('register', gql(`mutation rega ($login:String!, $password:String!){
                                     createUser(login: $login, password: $password){
                                         _id login
                                     }
                                 }`, { login, password }))
 
-export const actionFullRegister = (login, password, remember) =>
-    async dispatch => {
-        await actionRegister(login, password)
-        let token = await dispatch(actionLogin(login, password))
-        if (token) {
-            dispatch(actionAuthLogin(token, remember))
-        }
-    }
-
 
 export const actionProfilData = (_id) =>
     actionPromise('dataProfileAuth', gql(`query userOned($id:String!){
                         UserFindOne(query: $id){
-                            _id  login avatar{ _id url }
-                           following{_id} 
-                                } LikeFind(query:$id){
-                                _id
-                               post { _id}
+                            _id  login nick
+                            avatar { _id url }
+                            following {_id} 
                   }
                 }`, { id: JSON.stringify([{ ___owner: _id }]) }))
 
+//****************---Action Like ---*************************//
 
+export const actionRemoveLikePost = (_id) =>
+    actionPromise('removelikePost', gql(`mutation LikeRemove($like:LikeInput){
+        LikeDelete(like:$like){
+            _id
+        }
+    }`, { like: { _id } }))
 
 export const actionAddLikePost = (_id) =>
     actionPromise('likePost', gql(`mutation LikePost($like:LikeInput){
@@ -71,18 +53,27 @@ export const actionAddLikePost = (_id) =>
         }
     }`, { like: { post: { _id } } }))
 
-export const actionRemoveLikePost = (_id) =>
-    actionPromise('removelikePost', gql(`mutation LikeRemove($like:LikeInput){
-        LikeDelete(like:$like){
-            _id
+export const actionMyLikePost = (postId) =>
+    actionPromise('myLikes', gql(`query likeFindPost ($id:String!){
+        PostFindOne(query:$id){
+        likes { _id owner {_id}} 
         }
-    }`, { like: { _id } }))
+    }`, { id: JSON.stringify([{ _id: postId }]) }))
+
 
+//****************---Action Comment ---*************************//
 
+export const actionAddComment = (postId, text) =>
+    actionPromise('addcomment', gql(`mutation addcomment($comment: CommentInput ){
+        CommentUpsert(comment:$comment){
+            _id text
+        }
+    }`, { comment: { post: { _id: postId }, text } }))
+
+export const actionFindComment = (postId) =>
+    actionPromise('findCommentPost', gql(`query commentFindPost ($id:String!){
+        PostFindOne(query:$id){
+         comments{_id text owner{_id nick login} likes{_id}}
+        }
+    }`, { id: JSON.stringify([{ _id: postId }]) }))
 
-export const actionLikeUpdatePost = (id) =>
-    actionPromise('likeUpdatePost', gql(`query userOned($id: String!) {
-                                        PostFindOne(query: $id) {
-                                            likes {_id}
-                                        }
-}`, { id: JSON.stringify([{ _id: id }]) }))

+ 1 - 1
src/components/Authorization.jsx

@@ -2,10 +2,10 @@ import React  from 'react'
 import authBg from '../images/authBg.png'
 import { connect } from 'react-redux'
 import { NavLink} from 'react-router-dom'
-import { actionFullLogin, actionFullRegister } from '../actions'
 
 import { Form, Input, Button, Row, Col, Card, Divider, Checkbox } from 'antd';
 import { UserOutlined, LockOutlined } from '@ant-design/icons';
+import { actionFullLogin, actionFullRegister } from '../redux/redux-thunk';
 
 const FormInput = ({ buttonTitle, onSignIn }) => {
     const onFinish = ({ login, password, remember }) => {

+ 94 - 43
src/components/main/MainPostFeed.js

@@ -1,14 +1,15 @@
 import { Card, Col, Row, Carousel, Empty, Button } from 'antd'
-import Meta from 'antd/lib/card/Meta'
 import React, { createRef, useEffect, useState } from 'react'
 import { connect } from 'react-redux'
 import { Link } from 'react-router-dom'
-import { actionAddLikePost, actionLikeUpdatePost, actionMyFolowingPosts, actionMyLikes, actionOwnerId, actionRemoveLikePost, myFolowingPosts } from '../../actions'
 import { backURL } from '../../helpers'
 import { UserAvatar } from '../header/Header'
 import nodata from '../../images/nodata.png'
-import { CheckCircleTwoTone, HeartFilled, HeartOutlined, HeartTwoTone, LeftCircleOutlined, RightCircleOutlined, SmileTwoTone } from '@ant-design/icons'
-import { actionAddPostsFeed, actionFullAddLikePost, actionFullRemoveLikePost, actionRemoveLikePosts } from '../../redux/postFeed-reducer'
+import { HeartFilled, HeartOutlined, LeftCircleOutlined, RightCircleOutlined, SendOutlined, } from '@ant-design/icons'
+import Paragraph from 'antd/lib/typography/Paragraph'
+import Text from 'antd/lib/typography/Text'
+import TextArea from 'antd/lib/input/TextArea'
+import { actionAddPostsFeed, actionFullAddComment, actionFullAddLikePost, actionFullRemoveLikePost } from '../../redux/redux-thunk'
 
 const PostTitle = ({ owner }) =>
     <Link to={`/${owner?._id}`} className='owner'>
@@ -77,37 +78,32 @@ class PostImage extends React.Component {
     }
 }
 
-const HeartLike = ({ styleLike, likeStatus, changeLike }) =>
+const HeartLike = ({ styleFontSize, likeStatus, changeLike }) =>
     <Button
         onClick={() => changeLike()}
         type="none"
         shape="circle"
         icon={
             likeStatus ?
-                <HeartFilled style={styleLike} /> :
-                <HeartOutlined style={styleLike} />}
+                <HeartFilled style={{ color: '#ff6969', fontSize: `${styleFontSize}` }} /> :
+                <HeartOutlined style={{ color: '#1890ff', fontSize: `${styleFontSize}` }} />}
     />
 
-
-
-const PostUserPanel = ({ myLikes, postId, likes, addLikePost, removeLikePost }) => {
-
-    let likeStatus;
-    let likePOstId
-
-    myLikes.find(l => {
-        if (l.post._id === postId) {
+const PostUserPanel = ({ myID, myLikes, postId, likes, addLikePost, removeLikePost }) => {
+    let likeStatus
+    let likeId
+    likes.find(l => {
+        if (l.owner._id === myID) {
             likeStatus = true
-            likePOstId = l._id
+            likeId = l._id
         } else {
             likeStatus = false
         }
     })
-    let changeLike = () => likeStatus ? removeLikePost(likePOstId, postId) : addLikePost(postId)
-    const styleLikeBtn = {
-        fontSize: '1.7em',
-        color: '#1890ff'
-    }
+
+    const changeLike = () => likeStatus ? removeLikePost(likeId, postId) : addLikePost(postId)
+    const styleFontSize = '1.7em'
+
     return (
         <>
             <Row className="Post__panel-btn">
@@ -115,14 +111,10 @@ const PostUserPanel = ({ myLikes, postId, likes, addLikePost, removeLikePost })
                     <HeartLike
                         changeLike={changeLike}
                         likeStatus={likeStatus}
-                        styleLike={styleLikeBtn} />
+                        styleFontSize={styleFontSize} />
                 </Col>
                 <Col>
                 </Col>
-                <div >
-
-                </div>
-
             </Row>
             {!!likes.length && <strong>Likes: {likes.length}</strong>}
         </>
@@ -130,47 +122,106 @@ const PostUserPanel = ({ myLikes, postId, likes, addLikePost, removeLikePost })
 }
 
 const CPostUserPanel = connect(state => ({
+    myID: state.auth.payload.sub.id || '',
     myLikes: state?.promise?.myLikes?.payload || [],
 }), {
     addLikePost: actionFullAddLikePost,
     removeLikePost: actionFullRemoveLikePost,
 })(PostUserPanel)
 
-
-const PostDescription = () => {
-    
-
-    return(
+const PostDescription = ({ title, description, date }) =>
+    <>
+        <Row justify='space-between'>
+            <Col >
+                {!!title && <Text level={3} strong>{title}</Text>}
+            </Col>
+            <Col >
+                <Text type='secondary'>{date}</Text>
+            </Col>
+        </Row>
+        <Paragraph ellipsis={true ? { rows: 1, expandable: true, symbol: 'more' } : false}>
+            {description}
+        </Paragraph>
+    </>
+
+const Comments = ({ comments }) =>
+    <>
+        {comments && comments.length > 2 &&
+            <Link to={`/#`}>
+                <Text type={'secondary'} level={3}>{`Посмотреть все ${comments.length} комментария`}</Text>
+            </Link>}
+        {comments && <div>
+            <div className='Post__comments'>
+                <Link to={`/#`}>{comments[comments?.length - 2]?.owner?.nick || comments[comments?.length - 2]?.owner?.login}: </Link>
+                <span>{comments[comments?.length - 2]?.text}</span>
+            </div>
+            <div className='Post__comments'>
+                <Link to={`/#`}>{comments[comments?.length - 1]?.owner?.login || comments[comments?.length - 1]?.owner?.login}: </Link>
+                <span>{comments[comments?.length - 1]?.text}</span>
+            </div>
+        </div>}
+    </>
+
+
+const FieldCommentSend = ({ postId, sentComment }) => {
+    const [commentValue, setCommentValue] = useState('')
+    const [error, setError] = useState(false)
+
+    const changeComentTextarea = (e) => {
+        setCommentValue(e.currentTarget.value)
+        setError(false)
+    }
+    const sendCommentValid = (value) => {
+        if (value.trim() !== '') {
+            sentComment(postId, value.trim())
+            setCommentValue('')
+        } else {
+            setError(true)
+        }
+    }
+    return (
         <>
-
-        
+            {error && <Text type='danger'>Field is required</Text>}
+            <Row align='middle' className='Post__send-comment'>
+                <Col flex='auto' offset={1}>
+                    <TextArea value={commentValue}
+                        placeholder="Add a comment ..."
+                        autoSize={{ minRows: 1, maxRows: 2 }}
+                        onChange={changeComentTextarea}
+                        bordered={false}
+                    />
+                </Col>
+                <Col span={2}>
+                    <Button
+                        onClick={() => sendCommentValid(commentValue)}
+                        icon={< SendOutlined
+                            style={{ fontSize: '1.2em', opacity: .6 }} />} />
+                </Col>
+            </Row>
         </>
     )
 }
 
+const CFieldCommentSend = connect(null, { sentComment: actionFullAddComment })(FieldCommentSend)
 
 const Post = ({ postData: { _id, text, title, owner, images, createdAt, comments, likes } }) => {
-    // const date = new Date(createdAt * 1)
-    // const resultDate = new Intl.DateTimeFormat('default').format(date)
+    const date = new Date(createdAt * 1)
+    const resultDate = new Intl.DateTimeFormat('default').format(date)
     return (
         <div className='Post'>
             <Card
                 title={<PostTitle owner={owner} />}
                 cover={<PostImage images={images} />}
+                actions={[<CFieldCommentSend postId={_id} />]}
             >
                 <CPostUserPanel postId={_id} likes={likes} />
-                <PostDescription />
-                {/* <Meta title="Europe Street beat" description="www.instagram.com" /> */}
+                <PostDescription title={title} description={text} date={resultDate} />
+                <Comments comments={comments} />
             </Card>
         </div>
     )
 }
 
-
-
-
-
-
 const MainPostFeed = ({ posts, postsFollowing }) => {
     useEffect(() => {
         postsFollowing()

+ 22 - 66
src/redux/postFeed-reducer.js

@@ -1,105 +1,61 @@
 import React from 'react'
-import { actionPromise } from '../actions'
+import { actionAddCommentAC } from '../actions'
 import { gql } from '../helpers'
+import { actionPromise } from './redux-thunk'
 
-export const postFeedReducer = (state = {}, { type, addPosts, myLikes, postId, likeId }) => {
+export const postFeedReducer = (state = {}, { type, addPosts, newLike, postId, likeId, newResult }) => {
     const { posts } = state
     const types = {
         'ADD-POST-FEED': () => {
             return {
                 ...state,
                 posts: !!state.addPosts ? [...state.addPosts, ...addPosts] : [...addPosts],
-                myLikes: [...myLikes]
             }
         },
         'ADD-POST-LIKE': () => {
             return {
                 ...state,
-                posts: posts.map(p => p._id === postId ? p = { ...p, likes: [...p.likes, likeId] } : p),
-                myLikes: [...myLikes]
+                posts: posts.map(p => p._id === postId ? p = { ...p, likes: [...newResult] } : p),
             }
         },
         'REMOVE-POST-LIKE': () => {
             return {
                 ...state,
-                posts: posts.map(p => p._id === postId ?
-                    p = {
-                        ...p, likes: [...p.likes].filter(pl => pl._id !== likeId && pl)
-                    } : p),                myLikes: [...myLikes]
+                posts: posts.map(p => p._id === postId ? p = { ...p, likes: [...newResult] } : p),
+
             }
         },
+        'ADD-COMMENT': () => {
+            return {
+                ...state,
+                posts: posts.map(p => p._id === postId ? { ...p, comments: [...newResult] } : p)
+            }
+        }
     }
     if (type in types) {
         return types[type]()
     }
     return state
 }
+// export const actionRemoveComment = (_id) =>
+//     actionPromise('removeComment', gql(`mutation CommentRemove($comment: CommentInput ){
+//         CommentDelete(comment:$comment){
+//             _id, text
+//         }
+//     }`, { comment: { _id } }))
 
-const actionAddPostsFeedAC = (addPosts, myLikes) => ({ type: 'ADD-POST-FEED', addPosts, myLikes })
-const actionAddLikePostAC = (postId, myLikes, likeId) => ({ type: 'ADD-POST-LIKE', postId, myLikes, likeId })
-const actionRemoveLikePostAC = (myLikes, likeId, postId) => ({ type: 'REMOVE-POST-LIKE', myLikes, likeId, postId })
-
-
-export const actionRemoveLikePost = (_id) =>
-    actionPromise('removelikePost', gql(`mutation LikeRemove($like:LikeInput){
-        LikeDelete(like:$like){
-            _id
-        }
-    }`, { like: { _id } }))
-
-export const actionFullRemoveLikePost = (_id, postId) =>
-    async (dispatch, getState) => {
-        const { auth: { payload: { sub: { id } } } } = getState()
-        await actionRemoveLikePost(_id)
-        let myLikes = await dispatch(actionMyLikes(id))
-        if (myLikes) {
-            dispatch(actionRemoveLikePostAC(myLikes, _id, postId))
-        }
-    }
 
-export const actionAddLikePost = (_id) =>
-    actionPromise('likePost', gql(`mutation LikePost($like:LikeInput){
-        LikeUpsert(like:$like){
-            _id
-        }
-    }`, { like: { post: { _id } } }))
 
-export const actionFullAddLikePost = (postId) =>
-    async (dispatch, getState) => {
-        const { auth: { payload: { sub: { id } } } } = getState()
-        let likeId = await dispatch(actionAddLikePost(postId))
-        let myLikes = await dispatch(actionMyLikes(id))
-        if (myLikes && likeId) {
-            dispatch(actionAddLikePostAC(postId, myLikes, likeId))
-        }
-    }
-    
-export const actionAddPostsFeed = (skip) =>
-    async (dispatch, getState) => {
-        const { auth: { payload: { sub: { id } } } } = getState()
-        let posts = await dispatch(actionMyFolowisgPosts(skip))
-        let myLikes = await dispatch(actionMyLikes(id))
-        if (posts && myLikes) {
-            dispatch(actionAddPostsFeedAC(posts, myLikes))
-        }
-    }
-export const actionMyLikes = (id) =>
-    actionPromise('myLikes', gql(`query myLikes($qq:String!){
-                            LikeFind(query:$qq){
-                                _id
-                               post { _id}
-                            }
-}`, { qq: JSON.stringify([{ ___owner: id }]) }))
 
-export const actionMyFolowisgPosts = (skip = 19) =>
+export const actionMyFolowisgPosts = (skip = 738) =>
     actionPromise('followingPosts',
         gql(`query allposts($query: String!){
         PostFind(query:$query){
             _id, text, title
             owner{_id, nick, login, avatar {url}}
-            likes { _id }   
+            likes { _id owner {_id}}   
             images{url _id}
-            comments{text}
+            comments{_id text owner{_id nick login} likes{_id}}
             createdAt
         }
     }`, {
@@ -107,6 +63,6 @@ export const actionMyFolowisgPosts = (skip = 19) =>
             {
                 sort: [{ _id: -1 }],
                 skip: [+skip],
-                limit: [3],
+                limit: [1]
             }])
         }))