Bladeren bron

added feed

Mitrofanova Natali 2 jaren geleden
bovenliggende
commit
05deaa5b64

+ 5 - 0
.idea/.gitignore

@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/

+ 12 - 0
.idea/hipstagram.iml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/temp" />
+      <excludeFolder url="file://$MODULE_DIR$/.tmp" />
+      <excludeFolder url="file://$MODULE_DIR$/tmp" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/hipstagram.iml" filepath="$PROJECT_DIR$/.idea/hipstagram.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 2 - 0
src/App.js

@@ -4,6 +4,7 @@ import React from "react";
 import Auth from "./components/Auth";
 import {BrowserRouter, Routes, Route} from "react-router-dom";
 import Profile from "./components/Profile";
+import Feed from "./components/Feed";
 
 function App(props) {
     return (
@@ -13,6 +14,7 @@ function App(props) {
                     <Route path="/" element={<Navigate to="/auth"/>}/>
                     <Route path="/auth" element={<Auth/>}/>
                     <Route path="/profile" element={<Profile/>}/>
+                    <Route path="/feed" element={<Feed/>}/>
                 </Routes>
             </BrowserRouter>
         </div>

BIN
src/assets/img/Images.webp


BIN
src/assets/img/avatarGolub.jpg


BIN
src/assets/img/avatarGolubi.jpg


BIN
src/assets/img/brokenPicture.png


+ 2 - 2
src/components/AvaLoginBlock.js

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

+ 2 - 1
src/components/Comment.js

@@ -7,9 +7,10 @@ const AnswerWrap = styled.div`
 
 
  const Comment = ({commentData}) => {
+console.log(commentData.owner.avatar)
     return (
         <>
-            <AvaLoginBlock name={commentData.owner.login} urlAva={commentData.owner.avatar?.url}
+            <AvaLoginBlock name={commentData.owner.login} urlAva={commentData.owner.avatar}
                            styled={{height: "30px"}}/>
             <p>{commentData.text}</p>
             <TimeOfCreation createdTime={commentData.createdAt}/>

+ 29 - 0
src/components/CommentMessageBlock.js

@@ -0,0 +1,29 @@
+import {useState} from "react";
+import styled from "styled-components";
+import {gqlSendComment} from "../shared/services&utilits/gqlRequest";
+
+
+const MessageWrapper = styled.div`
+`
+
+function CommentMessageBlock({postId,updatePostData}){
+    const [textMessage, setTextMessage ] = useState("");
+
+    function inputHandler(e){
+        setTextMessage(e.target.value)
+    }
+    async function sendMessage(){
+      await  gqlSendComment(postId,textMessage);
+        setTextMessage("");
+        updatePostData();
+
+    }
+    return(
+        <MessageWrapper>
+            <input onChange={inputHandler} value={textMessage}/>
+            <button onClick={sendMessage}>Send</button>
+        </MessageWrapper>
+
+    )
+}
+export default CommentMessageBlock;

+ 73 - 0
src/components/Feed.js

@@ -0,0 +1,73 @@
+import OwnerHeader from "./OwnerHeader";
+import {useEffect, useState} from "react";
+import styled from "styled-components";
+import {gqlPostsFeed} from "../shared/services&utilits/gqlRequest";
+import PostFeed from "./PostFeed";
+
+const FeedContainer = styled.div`
+  margin-top: 30px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+`
+const FeedPostWrapper = styled.div`
+  margin-bottom: 20px;
+  width: 400px;
+  box-shadow: rgba(67, 71, 85, 0.27) 0px 0px 0.25em, rgba(90, 125, 188, 0.05) 0px 0.25em 1em;
+
+`
+
+function Feed() {
+    const [listIdPosts, setListIdPosts] = useState([]);
+    const [shouldLoadMore, setShoulLoadMore] = useState(false);
+    useEffect(() => {
+        getData();
+        window.addEventListener('scroll', scrollHandler);
+        return () => {
+            window.removeEventListener('scroll', scrollHandler);
+        };
+    }, [])
+
+    useEffect(()=>{
+        if  (shouldLoadMore){
+            getData();
+            setShoulLoadMore(false)
+        }
+    })
+
+
+
+    function getData() {
+        gqlPostsFeed(listIdPosts.length).then((res)=>res.json()).then((response) => {
+            setListIdPosts([...listIdPosts, ...response.data.PostFind])
+        })
+
+    }
+
+    function scrollHandler() {
+        const documentHeight = document.body.offsetHeight;
+        const screenHeight = window.innerHeight;
+        const scroll = window.scrollY;
+        const currentScrollPosition = screenHeight + scroll;
+        if (currentScrollPosition >= documentHeight - 200) {
+            setShoulLoadMore(true)
+        }
+    }
+
+
+    return (<>
+            <OwnerHeader/>
+            <FeedContainer>
+                <button onClick={()=>getData()}>click</button>
+                {listIdPosts && listIdPosts.map((post, index) =>
+                    <FeedPostWrapper key={index}>
+                        <PostFeed post={post} key={index}/>
+                    </FeedPostWrapper>
+                )}
+            </FeedContainer>
+        </>
+
+    )
+}
+
+export default Feed;

+ 29 - 0
src/components/ImgBlock.js

@@ -0,0 +1,29 @@
+import picture from "../assets/img/brokenPicture.png";
+import Carousel from "react-material-ui-carousel";
+
+
+
+const ImgBlock = ({images}) => {
+    return (
+        <>
+            {!images && <img src={picture} alt={"pic"}/>}
+            {images && images.length === 1 && <img src={images[0].url || picture } alt={"pic"} style={{width: "100%", maxHeight: "300px"}}/>}
+            {images && images.length > 1 && <div style={{width: "100%"}}>
+                <Carousel autoPlay={false} navButtonsAlwaysVisible={true}>{
+                    images.map((item, i) => <div key={i}
+                                                 style={{width: "100%",
+                                                     height: "300px",
+                                                     background: item.url ? `url(${item.url})` : picture,
+                                                     backgroundPosition: "center" ,
+                                                     backgroundSize: "contain",
+                                                     backgroundRepeat: "no-repeat"}}
+
+                    />)
+                }
+                </Carousel>
+            </div>}
+        </>
+    )
+};
+
+export default ImgBlock;

+ 11 - 1
src/components/OwnerHeader.js

@@ -33,12 +33,22 @@ const OwnerHeader = (props) => {
 
     }
 
+    const feedHandler=()=>{
+        navigate("/feed")
+    }
+    const clickHandler=()=>{
+        navigate("/profile")
+        props.setUserDataAsync(props.id, true)
+
+    }
     return (
         <HeaderWrapper>
             <button onClick={logout}>Logout</button>
             <p>HIPSTARGAM</p>
+            <button onClick={feedHandler}>Feed</button>
+
             <p>Hello</p>
-            <Avatar  src={props.ownerData && props.ownerData.avatar ? props.ownerData.avatar.url : avatar} alt={"avatar"} sx={{border:"1px solid grey"}}/>
+            <Avatar onClick={clickHandler} src={props.ownerData && props.ownerData.avatar ? props.ownerData.avatar.url : avatar} alt={"avatar"} sx={{border:"1px solid grey"}}/>
         </HeaderWrapper>
     )
 };

+ 45 - 52
src/components/Post.js

@@ -1,6 +1,5 @@
 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";
@@ -8,6 +7,8 @@ import CommentsBlock from "./CommentsBlock";
 import styled from "styled-components";
 import LikeBlock from "./LikeBlock";
 import {gqlOnePost} from "../shared/services&utilits/gqlRequest";
+import CommentMessageBlock from "./CommentMessageBlock";
+import ImgBlock from "./ImgBlock";
 
 
 const PostWrapper = styled.div`
@@ -55,19 +56,21 @@ const Title = styled.p`
 const Text = styled.p`
 `
 
-function Post({postId}){
+
+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))
+                .then(data => setPostData(data["data"].PostFindOne))
         }
     }, [])
 
-    function updatePostData(){
+    function updatePostData() {
         gqlOnePost(postId).then(res => res.json())
-            .then(data =>setPostData(data["data"].PostFindOne))
+            .then(data => setPostData(data["data"].PostFindOne))
     }
 
 
@@ -75,60 +78,50 @@ function Post({postId}){
         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>
+            {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}/>
+                        }
+
+                        <CommentMessageBlock postId={postId} updatePostData={updatePostData}/>
+
+                    </InfoBlockInModalWrapper>
+                </ModalWindow>
+                }
+            </PostWrapper>
             }
-        </PostWrapper>
-        }
         </>
     )
-};
+}
 
 export default Post;

+ 66 - 0
src/components/PostFeed.js

@@ -0,0 +1,66 @@
+import {useEffect, useState} from "react";
+import {gqlOnePost} from "../shared/services&utilits/gqlRequest";
+import ImgBlock from "./ImgBlock";
+import AvaLoginBlock from "./AvaLoginBlock";
+import styled from "styled-components";
+import LikeBlock from "./LikeBlock";
+import TimeOfCreation from "./TimeOfCreation";
+
+const Title = styled.p`
+`
+const Text = styled.p`
+`
+const ImgWrapper = styled.div`
+  width: 100%;
+  max-height: 350px;
+  display: flex;
+  align-items: center;
+`
+const LikeWrapper = styled.div`
+  display: flex;
+  justify-content: space-between;
+`
+
+function PostFeed({post}) {
+    const [postFeedData, setPostFeedData] = useState(null);
+    useEffect(() => {
+        if (!postFeedData) {
+            gqlOnePost(post._id).then(res => res.json())
+                .then(data => setPostFeedData(data["data"].PostFindOne))
+        }
+    }, [])
+
+    function updPostData() {
+        gqlOnePost(post._id).then(res => res.json())
+            .then(data => setPostFeedData(data["data"].PostFindOne))
+    }
+
+    function handler() {
+        // console.log(postFeedData.comments)
+    }
+
+    // console.log(postFeedData)
+    return (<>
+            {post && postFeedData && <>
+                <AvaLoginBlock name={postFeedData.owner && postFeedData.owner.login || "Anon"} urlAva={postFeedData.owner && postFeedData.owner.avatar || null}/>
+
+                <ImgWrapper>
+                    <ImgBlock images={post.images}/>
+                </ImgWrapper>
+                <LikeWrapper>
+                    <LikeBlock likes={postFeedData.likes} postId={postFeedData._id} updatePostData={updPostData}/>
+                    <TimeOfCreation createdTime={postFeedData.createdAt}/>
+                </LikeWrapper>
+                <Title>{postFeedData.title}</Title>
+                <Text>{postFeedData.text}</Text>
+                <button onClick={handler}>Show all comments
+                    ({postFeedData.comments && postFeedData.comments.length || 0})
+                </button>
+            </>
+            }
+        </>
+    )
+};
+
+
+export default PostFeed;

+ 30 - 16
src/shared/services&utilits/gqlRequest.js

@@ -120,10 +120,10 @@ export const gqlAddLike = (postId) => gql(
             },
         },
     },
-    )
+)
 
 
-export const gqlDeleteLike =(likeId, postId)=>    gql(
+export const gqlDeleteLike = (likeId, postId) => gql(
     `mutation DeleteLike($like:LikeInput){
           LikeDelete(like: $like)
           {
@@ -139,18 +139,32 @@ export const gqlDeleteLike =(likeId, postId)=>    gql(
         },
     },
 )
-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){
+export const gqlSendComment = (postId, text) => gql(
+    `mutation AddComment($comment:CommentInput){
+          CommentUpsert(comment:$comment)
+          {
             _id
-        }
-    }`, { like: { comment: { _id } } })
+            text 
+            createdAt
+          }
+        }`,
+    {
+        comment: {
+            post: {
+                _id: postId,
+            },
+            text
+        },
+    },
+)
+export const gqlPostsFeed=(skip)=> gql(` query allPosts($id:String!){
+                PostFind(query:$id){
+                    _id   images{url _id originalFileName}
+                }
+            }`, {
+    id: JSON.stringify([{}, {
+        sort: [{ _id: -1 }],
+        skip: [skip || 0],
+        limit: [10]
+    }])
+})