Jelajahi Sumber

added postFeed reducer, add change like

makstravm 3 tahun lalu
induk
melakukan
a028f7e359

+ 20 - 6
src/App.scss

@@ -96,7 +96,7 @@ select {
             width: 75%;
         }
     }
-    .ant-divider{
+    .ant-divider {
         margin-bottom: 0;
     }
 }
@@ -163,18 +163,32 @@ select {
             height: 30px;
             transition: 0.4s;
         }
-
     }
     &__prev {
-        left: -50px;
+        left: 0px;
+        opacity: 0;
         &.--active {
-            left: 1px;
+            opacity: 1;
         }
     }
     &__next {
-        right: -50px;
+        right: 0px;
+        opacity: 0;
         &.--active {
-            right: 1px;
+            opacity: 1;
+        }
+    }
+    &__heart {
+        button {
+            min-width: auto;
+            width: 30px;
+            height: 30px;
+            border: none;
+            padding: 0;
+            box-shadow: none;
+        }
+        strong {
+            display: block;
         }
     }
 }

+ 29 - 20
src/actions/index.js

@@ -55,25 +55,34 @@ export const actionProfilData = (_id) =>
     actionPromise('dataProfileAuth', gql(`query userOned($id:String!){
                         UserFindOne(query: $id){
                             _id  login avatar{ _id url }
-    }
-}`, { id: JSON.stringify([{ _id }]) }))
-
-export const myFolowingPosts = () =>
-    actionPromise('followingPosts', gql(`query allposts($query: String!){
-        PostFind(query: $query){
-            _id, text, title,
-            owner{_id, nick, login, avatar {url}
-            }, 
-            images{url _id},
-            comments{text},
-            createdAt
+                           following{_id} 
+                                } LikeFind(query:$id){
+                                _id
+                               post { _id}
+                  }
+                }`, { id: JSON.stringify([{ ___owner: _id }]) }))
+
+
+
+export const actionAddLikePost = (_id) =>
+    actionPromise('likePost', gql(`mutation LikePost($like:LikeInput){
+        LikeUpsert(like:$like){
+            _id
         }
-    }`, {
-        query: JSON.stringify([{},
-        {
-            sort: [{ _id: -1 }],
-            skip: [19],
-            limit: [3],
+    }`, { like: { post: { _id } } }))
+
+export const actionRemoveLikePost = (_id) =>
+    actionPromise('removelikePost', gql(`mutation LikeRemove($like:LikeInput){
+        LikeDelete(like:$like){
+            _id
         }
-        ])
-    }))
+    }`, { like: { _id } }))
+
+
+
+export const actionLikeUpdatePost = (id) =>
+    actionPromise('likeUpdatePost', gql(`query userOned($id: String!) {
+                                        PostFindOne(query: $id) {
+                                            likes {_id}
+                                        }
+}`, { id: JSON.stringify([{ _id: id }]) }))

+ 92 - 12
src/components/main/MainPostFeed.js

@@ -1,14 +1,14 @@
-import { Card, Col, Row, Carousel, Empty } from 'antd'
+import { Card, Col, Row, Carousel, Empty, Button } from 'antd'
 import Meta from 'antd/lib/card/Meta'
-import React, { createRef, useEffect } from 'react'
+import React, { createRef, useEffect, useState } from 'react'
 import { connect } from 'react-redux'
 import { Link } from 'react-router-dom'
-import { myFolowingPosts } from '../../actions'
+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 { LeftCircleOutlined, RightCircleOutlined } from '@ant-design/icons'
-
+import { CheckCircleTwoTone, HeartFilled, HeartOutlined, HeartTwoTone, LeftCircleOutlined, RightCircleOutlined, SmileTwoTone } from '@ant-design/icons'
+import { actionAddPostsFeed, actionFullAddLikePost, actionFullRemoveLikePost, actionRemoveLikePosts } from '../../redux/postFeed-reducer'
 
 const PostTitle = ({ owner }) =>
     <Link to={`/${owner?._id}`} className='owner'>
@@ -22,8 +22,6 @@ const PostTitle = ({ owner }) =>
         </Row>
     </Link >
 
-
-
 class PostImage extends React.Component {
     constructor(props) {
         super(props);
@@ -79,22 +77,100 @@ class PostImage extends React.Component {
     }
 }
 
-const Post = ({ postData: { text, title, owner, images, createdAt, comments } }) => {
-    const date = new Date(createdAt * 1)
-    const resultDate = new Intl.DateTimeFormat('default').format(date)
+const HeartLike = ({ styleLike, likeStatus, changeLike }) =>
+    <Button
+        onClick={() => changeLike()}
+        type="none"
+        shape="circle"
+        icon={
+            likeStatus ?
+                <HeartFilled style={styleLike} /> :
+                <HeartOutlined style={styleLike} />}
+    />
+
+
 
+const PostUserPanel = ({ myLikes, postId, likes, addLikePost, removeLikePost }) => {
+
+    let likeStatus;
+    let likePOstId
+
+    myLikes.find(l => {
+        if (l.post._id === postId) {
+            likeStatus = true
+            likePOstId = l._id
+        } else {
+            likeStatus = false
+        }
+    })
+    let changeLike = () => likeStatus ? removeLikePost(likePOstId, postId) : addLikePost(postId)
+    const styleLikeBtn = {
+        fontSize: '1.7em',
+        color: '#1890ff'
+    }
+    return (
+        <>
+            <Row className="Post__panel-btn">
+                <Col className='Post__heart'>
+                    <HeartLike
+                        changeLike={changeLike}
+                        likeStatus={likeStatus}
+                        styleLike={styleLikeBtn} />
+                </Col>
+                <Col>
+                </Col>
+                <div >
+
+                </div>
+
+            </Row>
+            {!!likes.length && <strong>Likes: {likes.length}</strong>}
+        </>
+    )
+}
+
+const CPostUserPanel = connect(state => ({
+    myLikes: state?.promise?.myLikes?.payload || [],
+}), {
+    addLikePost: actionFullAddLikePost,
+    removeLikePost: actionFullRemoveLikePost,
+})(PostUserPanel)
+
+
+const PostDescription = () => {
+    
+
+    return(
+        <>
+
+        
+        </>
+    )
+}
+
+
+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)
     return (
         <div className='Post'>
             <Card
                 title={<PostTitle owner={owner} />}
                 cover={<PostImage images={images} />}
             >
-                <Meta title="Europe Street beat" description="www.instagram.com" />
+                <CPostUserPanel postId={_id} likes={likes} />
+                <PostDescription />
+                {/* <Meta title="Europe Street beat" description="www.instagram.com" /> */}
             </Card>
         </div>
     )
 }
 
+
+
+
+
+
 const MainPostFeed = ({ posts, postsFollowing }) => {
     useEffect(() => {
         postsFollowing()
@@ -106,4 +182,8 @@ const MainPostFeed = ({ posts, postsFollowing }) => {
     )
 }
 
-export const CMainPostFeed = connect(state => ({ posts: state.promise?.followingPosts?.payload || [] }), { postsFollowing: myFolowingPosts })(MainPostFeed)
+export const CMainPostFeed = connect(state => ({
+    posts: state?.postsFeed?.posts || []
+}), {
+    postsFollowing: actionAddPostsFeed,
+})(MainPostFeed)

+ 112 - 0
src/redux/postFeed-reducer.js

@@ -0,0 +1,112 @@
+import React from 'react'
+import { actionPromise } from '../actions'
+import { gql } from '../helpers'
+
+export const postFeedReducer = (state = {}, { type, addPosts, myLikes, postId, likeId }) => {
+    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]
+            }
+        },
+        '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]
+            }
+        },
+    }
+    if (type in types) {
+        return types[type]()
+    }
+    return state
+}
+
+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) =>
+    actionPromise('followingPosts',
+        gql(`query allposts($query: String!){
+        PostFind(query:$query){
+            _id, text, title
+            owner{_id, nick, login, avatar {url}}
+            likes { _id }   
+            images{url _id}
+            comments{text}
+            createdAt
+        }
+    }`, {
+            query: JSON.stringify([{},
+            {
+                sort: [{ _id: -1 }],
+                skip: [+skip],
+                limit: [3],
+            }])
+        }))

+ 2 - 0
src/redux/redux-store.js

@@ -1,10 +1,12 @@
 import { createStore, combineReducers, applyMiddleware } from 'redux';
 import thunk from 'redux-thunk';
 import { authReducer } from './auth-reducer';
+import { postFeedReducer } from './postFeed-reducer';
 import { promiseReducer } from './promise-reducer';
 
 export const store = createStore(combineReducers({
     promise: promiseReducer,
     auth: authReducer,
+    postsFeed: postFeedReducer
 }),
     applyMiddleware(thunk))