瀏覽代碼

added comment block

Mitrofanova Natali 2 年之前
父節點
當前提交
e96866f879

+ 0 - 18
src/App.js

@@ -1,28 +1,10 @@
 import './App.css';
-import {connect} from "react-redux";
 import {Navigate} from "react-router-dom"
 import React from "react";
 import Auth from "./components/Auth";
 import {BrowserRouter, Routes, Route} from "react-router-dom";
 import Profile from "./components/Profile";
 
-
-// const ProtectedRout = ({roles=[],fallback="/login",component, auth, ...routProps})=>{
-//     const WrapperComponent= ( renderProps)=>{
-//         const C = component
-//         return<C {...renderProps}/>
-//     }
-//     return <Route{...routProps} component ={wrapperComponent}/>
-// }
-// const CProtectedRout = connect(state=> state.auth)(ProtectedRout)
-
-// <CProtectedRout roles={["anon"]} fallback="/dashboard" path="/register" component={Auth}/>
-// <CProtectedRout roles={["admin"]} path="/admin" component={CPageAdmin}/>
-// <CProtectedRout roles={["admin", "user"]} path="/" />
-//
-
-
-
 function App(props) {
     return (
         <div>

+ 3 - 21
src/components/Auth.js

@@ -27,14 +27,11 @@ const StyledButtonSignUp = styled(Button)`
 
 
 const Auth = (props) => {
-    // console.log(props)
     const [authType, setAuthType] = useState("signIn")
     const [login, setLogin] = useState("")
     const [password, setPassword] = useState("")
     const navigate = useNavigate();
 
-
-
     const btnHandler = (type) => {
         setAuthType(type)
     }
@@ -64,8 +61,9 @@ const Auth = (props) => {
             <TextField id="outlined-login" label="login" variant="outlined" onChange={inputLoginHandler}/>
             <TextField id="outlined-password" label="password" type="password" variant="outlined"
                        onChange={inputPasswordHandler}/>
-
-            <Button disabled={!login || !password} onClick={authBtnHandler} variant="outlined">{authType === "signIn" ? "SIGN IN" : "SIGN UP"}</Button>
+            <Button disabled={!login || !password} onClick={authBtnHandler} variant="outlined">
+                {authType === "signIn" ? "SIGN IN" : "SIGN UP"}
+            </Button>
         </LogRegistrBlock>
     )
 }
@@ -85,19 +83,3 @@ const mapDispatchToProps = (dispatch) => {
 }
 
 export default connect(mapStateToProps, mapDispatchToProps)(Auth);
-
-
-// const StyledInput = styled.input`
-//   font-size: 20px;
-//   border: 1px solid darkgray;
-//   border-radius: 10px;
-//   padding: 5px 20px;
-//   ::placeholder {
-//     color: darkgray;
-//     font-size: 0.8em;
-//   }
-// `
-
-// const StyledInputPassword = styled(StyledInput)`
-//
-// `

+ 2 - 2
src/components/AvaLoginBlock.js

@@ -12,10 +12,10 @@ const Nick = styled.div`
 const AvatarNickWrapper = styled.div`
   display: flex`
 
-function AvaLoginBlock({name, urlAva}) {
+function AvaLoginBlock({name, ava}) {
     return <>
         <AvatarNickWrapper>
-            <Avatar src={urlAva ? urlAva : avatar} alt={"avatar"} sx={{border: "1px solid grey"}}/>
+            <Avatar src={ava ? ava.url : avatar} alt={"avatar"} sx={{border: "1px solid grey"}}/>
             <Nick>{name}</Nick>
         </AvatarNickWrapper>
     </>

+ 26 - 0
src/components/Comment.js

@@ -0,0 +1,26 @@
+import AvaLoginBlock from "./AvaLoginBlock";
+import TimeOfCreation from "./TimeOfCreation";
+import styled from "styled-components";
+
+const AnswerWrap = styled.div`
+  margin-left: 30px`
+
+
+ const Comment = ({commentData}) => {
+    return (
+        <>
+            <AvaLoginBlock name={commentData.owner.login} urlAva={commentData.owner.avatar?.url}
+                           styled={{height: "30px"}}/>
+            <p>{commentData.text}</p>
+            <TimeOfCreation createdTime={commentData.createdAt}/>
+            {commentData.answers &&
+            <AnswerWrap>
+                <p>OTVET</p>
+                {commentData.answers.map((item, i) => <Comment commentData={item} key={i}/>)}
+            </AnswerWrap>
+            }
+        </>
+    )
+}
+
+export default Comment;

+ 5 - 37
src/components/CommentsBlock.js

@@ -1,52 +1,20 @@
-import {useEffect, useState} from "react";
-import {gqlOnePost} from "../shared/services&utilits/gqlRequest";
-import AvaLoginBlock from "./AvaLoginBlock";
-import TimeOfCreation from "./TimeOfCreation";
 import styled from 'styled-components';
+import Comment from "./Comment";
 
 const CommentsBlockStyled = styled.div`
   width: 100%;
   overflow: auto;
   height: 60%;
+  box-shadow: rgba(17, 17, 26, 0.1) 0px 1px 0px;
 `
-const AnswerWrap = styled.div`
-  margin-left: 30px`
 
-function CommentsBlock(props) {
-    // console.log(props.id)
-    const [postData, setPostData] = useState(null);
 
-    useEffect(() => {
-        if (!postData) {
-            gqlOnePost(props.id).then(res => res.json())
-                .then(data =>{
-                    // !props.isLikesRendered && props.setLikes(data["data"].PostFindOne.likes)
-                    setPostData(data["data"].PostFindOne);
-                })
-        }
-    }, [])
-    const Comment = ({commentData}) => {
-        // console.log(commentData)
-
-        return <>
-            <AvaLoginBlock name={commentData.owner.login} urlAva={commentData.owner.avatar?.url}
-                           styled={{height: "30px"}}/>
-            <p>{commentData.text}</p>
-            <TimeOfCreation createdTime={commentData.createdAt}/>
-            {commentData.answers &&
-            <AnswerWrap>
-                <p>OTVET</p>
-                {commentData.answers.map((item, i) => <Comment commentData={item} key={i}/>)}
-            </AnswerWrap>
-            }
-        </>
-    }
-    console.log(postData)
+function CommentsBlock({post}) {
     return (<CommentsBlockStyled>
             <div>комент</div>
-            {postData && postData?.comments &&
+            {post && post.comments &&
             <>
-                {postData.comments.map((item, i) => <Comment commentData={item} key={i}/>)}
+                {post.comments.map((item, i) => <Comment commentData={item} key={i}/>)}
             </>}
         </CommentsBlockStyled>
     )

+ 54 - 2
src/components/LikeBlock.js

@@ -1,3 +1,55 @@
-function LikeBlock(){
+import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
+import FavoriteIcon from '@mui/icons-material/Favorite';
+import {useEffect, useState} from "react";
+import {connect} from "react-redux";
+import styled from 'styled-components';
+import {gqlAddLike, gqlDeleteLike} from "../shared/services&utilits/gqlRequest";
 
-}
+const LikesWrapper = styled.div`
+  display: flex;
+  align-items: center;
+`
+const TextStyled = styled.p`
+  margin-left: 10px`
+
+function LikeBlock({likes, ownerId, postId, updatePostData}) {
+
+    const [isLiked, setIsLiked] = useState(false)
+
+    useEffect(() => {
+        if (likes && likes.length && likes.find((item) => item.owner._id === ownerId)) {
+            if (!isLiked) {
+                setIsLiked(true)
+            }
+        }
+    }, [])
+
+
+    const addLikeHandler = async () => {
+        await gqlAddLike(postId);
+        setIsLiked(true)
+        updatePostData();
+    }
+    const deleteLike = async () => {
+        const myLike = likes.find((item) => item.owner._id === ownerId);
+        myLike && await gqlDeleteLike(myLike._id, postId);
+        setIsLiked(false)
+        updatePostData();
+    }
+
+    return (<LikesWrapper>
+        {isLiked ? <FavoriteIcon onClick={deleteLike} style={{color: "red"}}/> :
+            <FavoriteBorderIcon onClick={addLikeHandler}/>}
+        <TextStyled>{likes && likes.length || "0"} likes</TextStyled>
+
+    </LikesWrapper>)
+};
+
+const mapStateToProps = (state) => {
+    return {
+        ownerId: state.auth.user.sub.id,
+
+    }
+}
+
+export default connect(mapStateToProps)(LikeBlock);

+ 3 - 6
src/components/OwnerHeader.js

@@ -13,7 +13,9 @@ const HeaderWrapper = styled.div`
 `
 
 const OwnerHeader = (props) => {
+
     const navigate = useNavigate();
+
     useEffect(() => {
         if (!props.ownerData) {
             props.setUserDataAsync(props.id, true)
@@ -21,11 +23,6 @@ const OwnerHeader = (props) => {
 
     })
 
-    const Logo = () => {
-        return (
-            <p>HIPSTARGAM</p>
-        )
-    }
     const logout = () => {
         localStorage.authToken = "";
         props.changeAuthData({
@@ -39,7 +36,7 @@ const OwnerHeader = (props) => {
     return (
         <HeaderWrapper>
             <button onClick={logout}>Logout</button>
-            <Logo/>
+            <p>HIPSTARGAM</p>
             <p>Hello</p>
             <Avatar  src={props.ownerData && props.ownerData.avatar ? props.ownerData.avatar.url : avatar} alt={"avatar"} sx={{border:"1px solid grey"}}/>
         </HeaderWrapper>

+ 134 - 0
src/components/Post.js

@@ -0,0 +1,134 @@
+import {useEffect, useState} from "react";
+import picture from "../assets/img/brokenPicture.png";
+import Carousel from "react-material-ui-carousel";
+import AutoAwesomeMotionIcon from "@mui/icons-material/AutoAwesomeMotion";
+import ModalWindow from "./ModalWindow";
+import AvaLoginBlock from "./AvaLoginBlock";
+import CommentsBlock from "./CommentsBlock";
+import styled from "styled-components";
+import LikeBlock from "./LikeBlock";
+import {gqlOnePost} from "../shared/services&utilits/gqlRequest";
+
+
+const PostWrapper = styled.div`
+  position: relative;
+  display: flex;
+  min-width: 300px;
+  max-width: 300px;
+  margin: 15px;
+  box-shadow: rgba(0, 0, 0, 0.25) 0px 0.0625em 0.0625em, rgba(0, 0, 0, 0.25) 0px 0.125em 0.5em, rgba(255, 255, 255, 0.1) 0px 0px 0px 1px inset;
+`
+const LogoManyImg = styled.div`
+  position: absolute;
+  z-index: 2;
+  right: 0;
+  width: 25px;
+  height: 35px;
+  transform: scaleX(-1);
+`
+const PicsInModalWrapper = styled.div`
+  width: 50%;
+  max-height: 100%;
+  margin: 30px;
+  overflow: hidden;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: rgba(0, 0, 0, 0.25) 0px 0.0625em 0.0625em, rgba(0, 0, 0, 0.25) 0px 0.125em 0.5em, rgba(255, 255, 255, 0.1) 0px 0px 0px 1px inset;
+`
+const AvaLoginWrap = styled.div`
+  display: flex;
+  margin-top: 30px;
+  width: 80%;
+
+`
+const DescriptionPostWrapper = styled.div`
+  height: fit-content;
+  width: 100%;
+  box-shadow: rgba(17, 17, 26, 0.1) 0px 1px 0px;
+`
+const InfoBlockInModalWrapper = styled.div`
+  width: 50%;
+`
+const Title = styled.p`
+`
+const Text = styled.p`
+`
+
+function Post({postId}){
+    const [isModal, setModal] = useState(false);
+    const [postData, setPostData] = useState(null);
+    useEffect(() => {
+        if (!postData) {
+            gqlOnePost(postId).then(res => res.json())
+                .then(data =>setPostData(data["data"].PostFindOne))
+        }
+    }, [])
+
+    function updatePostData(){
+        gqlOnePost(postId).then(res => res.json())
+            .then(data =>setPostData(data["data"].PostFindOne))
+    }
+
+
+    function toggleModalWindow() {
+        setModal(!isModal)
+    }
+
+    console.log(postData)
+    const ImgBlock = ({images}) => {
+        return (
+            <>
+                {!images && <img src={picture} alt={"pic"}/>}
+                {images && images.length === 1 && <img src={images[0].url} alt={"pic"} style={{width: "100%"}}/>}
+                {images && images.length > 1 && <div style={{width: "100%"}}>
+                    <Carousel autoPlay={false} navButtonsAlwaysVisible={true}>{
+                        images.map((item, i) => <img src={item.url} key={i} style={{width: "100%"}}
+                                                     alt={"picture"}/>)
+                    }
+                    </Carousel>
+                </div>}
+            </>
+        )
+    };
+
+    // console.log(post)
+    return (
+        <>
+        {postData &&
+        <PostWrapper onClick={() => toggleModalWindow()}>
+            <img src={postData.images ? postData.images[0].url : picture} alt="post" style={{width: "100%"}}/>
+            {
+                postData.images?.length > 1 && <LogoManyImg>
+                    <AutoAwesomeMotionIcon/>
+                </LogoManyImg>
+            }
+            {isModal &&
+            <ModalWindow closeModal={toggleModalWindow}>
+                <PicsInModalWrapper>
+                    <ImgBlock images={postData.images}/>
+                </PicsInModalWrapper>
+                <InfoBlockInModalWrapper>
+
+                    <AvaLoginWrap>
+                        <AvaLoginBlock urlAva={postData.owner.avatar} name={postData.owner.login}/>
+                    </AvaLoginWrap>
+                    <DescriptionPostWrapper>
+                        <Title>Title:{postData.title}</Title>
+                        <Text>{postData.text}</Text>
+                    </DescriptionPostWrapper>
+
+                    <CommentsBlock post={postData}/>
+                    {postData.likes &&
+                    <LikeBlock likes={postData.likes} postId={postData._id} updatePostData={updatePostData}/>
+                    }
+                </InfoBlockInModalWrapper>
+            </ModalWindow>
+            }
+        </PostWrapper>
+        }
+        </>
+    )
+};
+
+export default Post;

+ 2 - 3
src/components/Profile.js

@@ -6,9 +6,8 @@ import UserContent from "./UserContent";
 const Profile =()=>{
     return(
         <>
-        <OwnerHeader/>
-        <UserContent/>
-
+            <OwnerHeader/>
+            <UserContent/>
         </>
     )
 }

+ 8 - 128
src/components/UserContent.js

@@ -1,14 +1,11 @@
 import {connect} from "react-redux";
 import styled from 'styled-components';
-import {useEffect, useState} from "react";
+import {useEffect} from "react";
 import {setActiveUserAllPostsAsync, setUserDataAsync} from "../store/actionCreators/ActionCreators";
 import avatar from "../assets/img/avatarGolub.jpg";
-import picture from "../assets/img/brokenPicture.png";
-import ModalWindow from "./ModalWindow";
-import AutoAwesomeMotionIcon from '@mui/icons-material/AutoAwesomeMotion';
-import Carousel from 'react-material-ui-carousel'
-import CommentsBlock from "./CommentsBlock"
-import AvaLoginBlock from "./AvaLoginBlock";
+import Post from "./Post";
+import UserInfoBlock from "./UserInfoBlock";
+
 
 const UserContentWrapper = styled.div`
   margin-top: 30px;
@@ -42,13 +39,6 @@ const UserInfoBlockWrapper = styled.div`
   display: flex;
   justify-content: flex-start;
 `
-const UserInfoBlockStyled = styled.div`
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  margin: 0 40px;
-  flex-direction: column;
-`
 const AvatarWrapper = styled.div`
   width: 100px;
   height: 100px;
@@ -58,132 +48,23 @@ const AvatarWrapper = styled.div`
   display: flex;
   align-items: center;
 `
-const PostWrapper = styled.div`
-  position: relative;
-  display: flex;
-  min-width: 300px;
-  max-width: 300px;
-  margin: 15px;
-  box-shadow: rgba(0, 0, 0, 0.25) 0px 0.0625em 0.0625em, rgba(0, 0, 0, 0.25) 0px 0.125em 0.5em, rgba(255, 255, 255, 0.1) 0px 0px 0px 1px inset;
-`
-const LogoManyImg = styled.div`
-  position: absolute;
-  z-index: 2;
-  right: 0;
-  width: 25px;
-  height: 35px;
-  transform: scaleX(-1);
-`
-const PicsInModalWrapper = styled.div`
-  width: 50%;
-  max-height: 100%;
-  margin: 30px;
-  overflow: hidden;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  box-shadow: rgba(0, 0, 0, 0.25) 0px 0.0625em 0.0625em, rgba(0, 0, 0, 0.25) 0px 0.125em 0.5em, rgba(255, 255, 255, 0.1) 0px 0px 0px 1px inset;
-`
-const AvaLoginWrap = styled.div`
-  display: flex;
-  margin-top: 30px;
-  width: 80%;
 
-`
-const DescriptionPostWrapper = styled.div`
-  height: fit-content;
-  width: 100%;
-  box-shadow: rgba(17, 17, 26, 0.1) 0px 1px 0px;
-`
-const InfoBlockInModalWrapper = styled.div`
-  width: 50%;
-`
-const Title = styled.p``
-const Text = styled.p``
 const tempUser = "62c1cc5e4535fc62e2a185ad"; // test - should be deleted
 
 
 function UserContent(props) {
 
-    const [likes, setLikes] = useState(null);
-
     useEffect(() => {
         if (!props.activeUser) {
             props.setUserDataAsync(props.id)
         }
         if (props.activeUser && !props.activeUserPosts.length) {
 
-            // props.setActiveUserAllPostsAsync(tempUser);
-            props.setActiveUserAllPostsAsync(props.activeUser._id)
+            props.setActiveUserAllPostsAsync(tempUser);
+            // props.setActiveUserAllPostsAsync(props.activeUser._id)
         }
     })
-
-    const UserInfoBlock = ({count, description}) => {
-        return (<UserInfoBlockStyled>
-            <p>{count ? count : 0}</p>
-            <p>{description}</p>
-        </UserInfoBlockStyled>)
-    }
-    const Post = ({post}) => {
-        const [isModal, setModal] = useState(false)
-        console.log(post)
-        function toggleModalWindow() {
-            setModal(!isModal)
-        }
-
-        const ImgBlock = ({images}) => {
-            return (
-                <>
-                    {!images && <img src={picture} alt={"pic"}/>}
-                    {images && images.length === 1 && <img src={images[0].url} alt={"pic"} style={{width: "100%"}}/>}
-                    {images && images.length > 1 && <div style={{width: "100%"}}>
-                        <Carousel autoPlay={false} navButtonsAlwaysVisible={true}>{
-                            images.map((item, i) => <img src={item.url} key={i} style={{width: "100%"}}
-                                                         alt={"picture"}/>)
-                        }
-                        </Carousel>
-                    </div>}
-                </>
-                // (images?.length && images.length > 1) && console.log("many pics") || (images && images.length === 1) &&
-                //  <img src={images[0].url} alt={"pic"} style={{width:"100%"}}/> || <img src={picture} alt={"pic"}/>
-                // <img src={images[0].url} alt={"pic"}/>
-            )
-        };
-
-        console.log(post)
-        return (
-            <PostWrapper onClick={() => toggleModalWindow()}>
-                <img src={post.images ? post.images[0].url : picture} alt="post" style={{width: "100%"}}/>
-                {
-                    post.images?.length > 1 && <LogoManyImg>
-                        <AutoAwesomeMotionIcon/>
-                    </LogoManyImg>
-                }
-                {isModal &&
-                <ModalWindow closeModal={toggleModalWindow}>
-                    <PicsInModalWrapper>
-                        <ImgBlock images={post.images}/>
-                    </PicsInModalWrapper>
-                    <InfoBlockInModalWrapper>
-
-                        <AvaLoginWrap>
-                            <AvaLoginBlock urlAva={props.activeUser.avatar.url} name={props.activeUser.login}/>
-
-                        </AvaLoginWrap>
-                        <DescriptionPostWrapper>
-                            <Title>Title:{post.title}</Title>
-                            <Text>{post.text}</Text>
-                        </DescriptionPostWrapper>
-
-                        <CommentsBlock id={post._id} setLikes={setLikes} isLikesRendered={likes !== null}/>
-                        {/*<LikeBlock/>*/}
-
-                    </InfoBlockInModalWrapper>
-                </ModalWindow>
-                }
-            </PostWrapper>
-        )
-    }
+    console.log(props.activeUserPosts)
     return (
         <>
             {props.activeUser && <UserContentWrapper>
@@ -205,7 +86,7 @@ function UserContent(props) {
 
                 {props.activeUserPosts &&
                 <PostsContainer>
-                    {props.activeUserPosts.map((post, index) => <Post post={post} key={index}/>)}
+                    {props.activeUserPosts.map((post, index) => <Post activeUser={props.activeUser} postId={post._id} key={index}/>)}
                 </PostsContainer>}
             </UserContentWrapper>
             }
@@ -213,7 +94,6 @@ function UserContent(props) {
     )
 }
 
-;
 
 const mapStateToProps = (state) => {
     return {

+ 17 - 0
src/components/UserInfoBlock.js

@@ -0,0 +1,17 @@
+import styled from "styled-components";
+
+const UserInfoBlockStyled = styled.div`
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 0 40px;
+  flex-direction: column;
+`
+
+const UserInfoBlock = ({count, description}) => {
+    return (<UserInfoBlockStyled>
+        <p>{count ? count : 0}</p>
+        <p>{description}</p>
+    </UserInfoBlockStyled>)
+}
+export default UserInfoBlock;

+ 82 - 35
src/shared/services&utilits/gqlRequest.js

@@ -1,30 +1,29 @@
-
-const getGQL = (url) => (query, variables) =>{
+const getGQL = (url) => (query, variables) => {
     return fetch(url, {
         method: "POST",
         // mode: 'no-cors',
         headers: {
             "Content-Type": "application/json",
             ...(localStorage.authToken
-                ? { Authorization: "Bearer " + localStorage.authToken }
+                ? {Authorization: "Bearer " + localStorage.authToken}
                 : {}),
             'Access-Control-Allow-Origin': "*"
         },
-        body: JSON.stringify({ query, variables }),
+        body: JSON.stringify({query, variables}),
     })
         .then((res) => {
             // console.log(res)
             // return res.json()
             return res;
         })
-        // .then((data) => {
-        //     console.log(data)
-        //     if (data.data) {
-        //         console.log(data.data) //token
-        //
-        //         return Object.values(data.data)[0];
-        //     } else throw new Error(JSON.stringify(data.errors));
-        // });
+    // .then((data) => {
+    //     console.log(data)
+    //     if (data.data) {
+    //         console.log(data.data) //token
+    //
+    //         return Object.values(data.data)[0];
+    //     } else throw new Error(JSON.stringify(data.errors));
+    // });
 }
 
 // const backendURL = 'http://hipstagram.asmer.fs.a-level.com.ua'
@@ -33,14 +32,14 @@ const getGQL = (url) => (query, variables) =>{
 export const gql = getGQL("/graphql");
 
 
-export const gqlRegistration=(login,password)=>gql(`mutation register($login: String!, $password: String!){
+export const gqlRegistration = (login, password) => gql(`mutation register($login: String!, $password: String!){
                 createUser(login: $login, password: $password) {
                     _id login
                 }
             }`, {login: String(login), password: String(password)}
 )
 
-export const gqlAboutUser = (_id) =>gql(`query AboutMe($userId:String){
+export const gqlAboutUser = (_id) => gql(`query AboutMe($userId:String){
             UserFindOne(query:$userId)
             {
               _id createdAt login nick avatar{_id url} 
@@ -48,38 +47,37 @@ export const gqlAboutUser = (_id) =>gql(`query AboutMe($userId:String){
               following{_id login nick avatar{_id url}}
             }
           }`,
-            {
-                userId: JSON.stringify([{ _id }]),
-            },
-    )
+    {
+        userId: JSON.stringify([{_id}]),
+    },
+)
 
-export const gqlLogin=(login,password)=>gql(
+export const gqlLogin = (login, password) => gql(
     `query login($login: String!, $password: String!){
         login(login: $login, password: $password)
         }`,
-        {login: String(login), password: String(password)}
+    {login: String(login), password: String(password)}
 )
 
-export const gqlAllPosts = (userId) =>gql(
-            `query allPosts($userId:String!){
+export const gqlAllPosts = (userId) => gql(
+    `query allPosts($userId:String!){
   PostFind(query:$userId){
            owner{_id} _id title text images{_id url} createdAt
     }
 }`,
+    {
+        userId: JSON.stringify([
+            {___owner: userId},
             {
-                userId: JSON.stringify([
-                    { ___owner: userId },
-                    {
-                        sort: [{ _id: -1 }],
-                        skip: [0],
-                        limit: [100],
-                    },
-                ]),
+                sort: [{_id: -1}],
+                skip: [0],
+                limit: [100],
             },
+        ]),
+    },
+)
 
-    )
-
-export const gqlOnePost = (_id)=>gql(
+export const gqlOnePost = (_id) => gql(
     `query OneFind($post:String){
         PostFindOne(query:$post){
        _id title text images{_id url}
@@ -104,6 +102,55 @@ export const gqlOnePost = (_id)=>gql(
 
       `,
     {
-        post: JSON.stringify([{ _id }]),
+        post: JSON.stringify([{_id}]),
+    },
+)
+
+export const gqlAddLike = (postId) => gql(
+    `mutation AddLike($like:LikeInput){
+          LikeUpsert(like:$like)
+          {
+            _id
+          }
+        }`,
+    {
+        like: {
+            post: {
+                _id: postId,
+            },
+        },
     },
-)
+    )
+
+
+export const gqlDeleteLike =(likeId, postId)=>    gql(
+    `mutation DeleteLike($like:LikeInput){
+          LikeDelete(like: $like)
+          {
+            _id
+          }
+        }`,
+    {
+        like: {
+            _id: likeId,
+            post: {
+                _id: postId,
+            },
+        },
+    },
+)
+export const gqlCommentsLikes = (commentId)=>  gql(`query findLikeComment ($id:String!){
+        CommentFindOne(query:$id){
+        likes { _id owner {_id}}
+        }
+    }`, { id: JSON.stringify([{ _id: commentId }]) })
+
+export const gqlDeleteLikeComment=(_id)=> gql(`mutation LikeRemove($like:LikeInput){
+            LikeDelete(like:$like){_id}
+        }`, { like: { _id } })
+
+export const gqlAddLikeComment=(_id)=>  gql(`mutation LikePost($like:LikeInput){
+        LikeUpsert(like:$like){
+            _id
+        }
+    }`, { like: { comment: { _id } } })

+ 26 - 20
src/store/actionCreators/ActionCreators.js

@@ -1,15 +1,7 @@
 import {gqlAboutUser, gqlLogin, gqlRegistration, gqlAllPosts} from "../../shared/services&utilits/gqlRequest";
 import {jwtDecode} from "../../shared/services&utilits/utilits";
 
-export const changeAuthData = authData => ({
-    type: "CHANGE_AUTH_DATA",
-    payload: authData
-})
-
-export const setError = error => ({
-    type: "SET_ERROR",
-    payload: error
-})
+// async actions
 
 export const changeAuthDataAsync = ({login, password, authType, navigateCallback}) => {
      return async (dispatch) => {
@@ -73,22 +65,14 @@ export const setUserDataAsync = (id, isOwner) => {
         }
 };
 
-export const setActiveUserData =(data)=>({
-    type: "SET_ACTIVE_USER_DATA",
-    payload: data,
-} )
-export const setOwnerData =(data)=>({
-    type: "SET_OWNER_DATA",
-    payload: data,
-} )
 export const setActiveUserAllPostsAsync = (id)=>{
     return async(dispatch)=>{
         let response = ""
         response = await gqlAllPosts(id)
 
-        // if (!response.ok) {
-        //     dispatch(setError("No user data received"))
-        // }
+        if (!response.ok) {
+            dispatch(setError("No user data received"))
+        }
 
         const responseData = await response.json();
         dispatch(setActiveUserAllPosts(responseData.data.PostFind))
@@ -96,6 +80,28 @@ export const setActiveUserAllPostsAsync = (id)=>{
     }
 }
 
+
+// sync actions
+
+export const changeAuthData = authData => ({
+    type: "CHANGE_AUTH_DATA",
+    payload: authData
+})
+
+export const setError = error => ({
+    type: "SET_ERROR",
+    payload: error
+})
+
+export const setActiveUserData =(data)=>({
+    type: "SET_ACTIVE_USER_DATA",
+    payload: data,
+} )
+export const setOwnerData =(data)=>({
+    type: "SET_OWNER_DATA",
+    payload: data,
+} )
+
 export const setActiveUserAllPosts =(data)=>({
     type: "SET_ACTIVE_USER_ALL_POSTS",
     payload: data,