From ea2d36de1c43308d2eb601e45ee3c537d89a4913 Mon Sep 17 00:00:00 2001 From: MisbehavedNinjaRadiator <120029998+MisbehavedNinjaRadiator@users.noreply.github.com.> Date: Sat, 28 Jun 2025 16:44:48 +0200 Subject: [PATCH] Feed funktioniert, infinite scroll funktioniert nicht mehr --- code/frontend/src/components/Post.tsx | 122 ++++++++++++++------- code/frontend/src/components/feed/Feed.tsx | 56 ++++++---- code/frontend/src/components/feed/feed.css | 4 +- 3 files changed, 116 insertions(+), 66 deletions(-) diff --git a/code/frontend/src/components/Post.tsx b/code/frontend/src/components/Post.tsx index edaa81e..9e52b7e 100644 --- a/code/frontend/src/components/Post.tsx +++ b/code/frontend/src/components/Post.tsx @@ -14,57 +14,79 @@ import FavoriteIcon from '@mui/icons-material/Favorite'; import ShareIcon from '@mui/icons-material/Share'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import MoreVertIcon from '@mui/icons-material/MoreVert'; +import api from "../api/axios"; interface ExpandMoreProps extends IconButtonProps { expand: boolean; } interface PostProps { - postId: number; + postId: string; } +interface PostResponse { + description: string; + status: string; + likes: number; + tags: string[]; + user: { + id: string; + name: string; + }; + createdAt: string; + updatedAt: string; + images: { + originalName: string; + mimetype: string; + url: string; + }[]; + following: boolean; +} + const ExpandMore = styled((props: ExpandMoreProps) => { const { expand, ...other } = props; return ; -})(({ theme }) => ({ +})(({ theme, expand }) => ({ marginLeft: 'auto', transition: theme.transitions.create('transform', { duration: theme.transitions.duration.shortest, }), - variants: [ - { - props: ({ expand }) => !expand, - style: { - transform: 'rotate(0deg)', - }, - }, - { - props: ({ expand }) => !!expand, - style: { - transform: 'rotate(180deg)', - }, - }, - ], + transform: expand ? 'rotate(180deg)' : 'rotate(0deg)', })); -export default function Post({postId}: PostProps) { +export default function Post({ postId }: PostProps) { const [expanded, setExpanded] = React.useState(false); - const content = "Fetch content here"; - const expandedContent = "Fetch expanded here" - const title = "Fetch heading here"; - const createdAt = "Fetch created at here"; - const user = "Fetch user here"; - const media = "Fetch media here (path)"; + const [post, setPost] = React.useState(null); - const handleExpandClick = () => { - setExpanded(!expanded); - }; + React.useEffect(() => { + getPostbyID(); + // eslint-disable-next-line + }, [postId]); + async function getPostbyID(): Promise { + try { + const response = await api.get(`/posts/getPost/{postId}?postId=${postId}`); + //const response = await api.get(`http://localhost:3001/api/posts/getPost/{postId}?postId=${postId}`); + setPost(response.data); + } catch (error) { + console.error("Failed to fetch post:", error); + } + } + + if (!post) { + return ( + + + Loading... + + + ); + } return ( - + - {user ? user.charAt(0).toUpperCase() : 'U'} //Todo: when fetching change to user.name or sth + + {post.user.name.charAt(0).toUpperCase()} } action={ @@ -72,17 +94,32 @@ export default function Post({postId}: PostProps) { } - title={title} - subheader= {createdAt} - /> - + {post.images && post.images.length > 0 && ( + + )} - - {content} + + {post.description} + + + Status: {post.status} + + + Likes: {post.likes} + + + Tags: {post.tags.join(", ")} + + + Following: {post.following ? "Ja" : "Nein"} @@ -94,7 +131,7 @@ export default function Post({postId}: PostProps) { setExpanded(!expanded)} aria-expanded={expanded} aria-label="show more" > @@ -103,7 +140,12 @@ export default function Post({postId}: PostProps) { - {expandedContent} + + Erstellt am: {new Date(post.createdAt).toLocaleString()} + + + Zuletzt aktualisiert: {new Date(post.updatedAt).toLocaleString()} + diff --git a/code/frontend/src/components/feed/Feed.tsx b/code/frontend/src/components/feed/Feed.tsx index 6bf3dd2..a6f0ee5 100644 --- a/code/frontend/src/components/feed/Feed.tsx +++ b/code/frontend/src/components/feed/Feed.tsx @@ -1,34 +1,45 @@ import React, { useState, useEffect, useRef } from "react"; import Post from "../Post"; import "./feed.css"; +import api from "../../api/axios"; + +interface PostListItem { + id: string; + createdAt: string; + description: string; +} function Feed() { - const [posts, setPosts] = useState([]); + const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(false); const [hasMore, setHasMore] = useState(true); + const [nextCursor, setNextCursor] = useState(null); const feedRef = useRef(null); const PAGE_SIZE = 10; - // Dummy fetch function that simulates loading posts by ID - const fetchPosts = () => { - if (loading) return; + const fetchPosts = async () => { + if (loading || !hasMore) return; setLoading(true); + try { + const params: any = { limit: PAGE_SIZE }; + if (nextCursor) params.createdAt = nextCursor; + interface FeedResponse { + posts: PostListItem[]; - setTimeout(() => { - setPosts((prev) => { - const newPosts = []; - for (let i = 0; i < PAGE_SIZE; i++) { - newPosts.push(prev.length + i + 1); - } - return [...prev, ...newPosts]; - }); - setLoading(false); - - // Stop after 50 posts, just as an example - if (posts.length + PAGE_SIZE >= 50) { - setHasMore(false); + nextCursor: string | null; } - }, 800); + const response = await api.get("/feed?limit=10"); + //const response = await api.get("http://localhost:3001/api/feed?limit=10"); + console.log("Feed response:", response.data); + const { posts: newPosts, nextCursor: newCursor } = response.data; + setPosts((prev) => [...prev, ...newPosts]); + setNextCursor(newCursor); + setHasMore(!!newCursor && newPosts.length > 0); + } catch (error) { + console.error("Error fetching posts:", error); + } finally { + setLoading(false); + } }; useEffect(() => { @@ -39,24 +50,23 @@ function Feed() { const onScroll = () => { const feed = feedRef.current; if (!feed || loading || !hasMore) return; - if (feed.scrollTop + feed.clientHeight >= feed.scrollHeight - 100) { fetchPosts(); } }; - const feed = feedRef.current; feed?.addEventListener("scroll", onScroll); return () => { feed?.removeEventListener("scroll", onScroll); }; - }, [loading, hasMore]); + }, [loading, hasMore, nextCursor]); return (
- {posts.map((postId) => ( - + {posts.length === 0 && !loading &&
Keine Posts gefunden.
} + {posts.map((post) => ( + ))} {loading &&
Loading more posts...
} {!hasMore &&
No more posts
} diff --git a/code/frontend/src/components/feed/feed.css b/code/frontend/src/components/feed/feed.css index 880344d..ed98bfc 100644 --- a/code/frontend/src/components/feed/feed.css +++ b/code/frontend/src/components/feed/feed.css @@ -1,9 +1,7 @@ - .feedContainer { display: flex; flex-direction: column; - height: 100vh; - overflow: hidden; + min-height: calc(100vh - var(--Header-height)); background-color: #f9f9f9; }