diff --git a/app/(Main)/feed/page.tsx b/app/(Main)/feed/page.tsx index 67a0bcdf..7c18c839 100644 --- a/app/(Main)/feed/page.tsx +++ b/app/(Main)/feed/page.tsx @@ -1,7 +1,7 @@ "use client"; import { getSessionUser } from '@/components/get-session-user'; import { useSession } from 'next-auth/react'; -import { useState, useEffect, useRef, Key, Suspense } from 'react' +import { useState, useEffect, useRef, Key, Suspense, useCallback } from 'react' import { Icons } from '@/components/icon'; import PopularPosts from '@/components/feed/popular-posts'; import { usePathname, useRouter } from 'next/navigation'; @@ -10,6 +10,7 @@ import { Skeleton } from '@/components/ui/skeleton'; import FeedComponent from '@/components/feed/feed'; import UserExplore from '@/components/explore/user/details'; import ExploreTabs from '@/components/explore/navbar/navbar'; +import { revalidatePath } from 'next/cache'; export default function Feed() { const { status, data: session } = useSession() @@ -26,45 +27,85 @@ export default function Feed() { const pathname = usePathname() - useEffect(() => { - async function fetchFeed() { - if (status !== "unauthenticated") { - const user = (await sessionUser)?.id - try { - const response = await fetch(`/api/feed?user=${user}&page=${page}`); - if (!response.ok) { - throw new Error(`Fetch failed with status: ${response.status}`); - } - const topUsers = await fetch(`/api/users/top?user=${user}`, { - method: "GET", - }).then((res) => res.json()); - const data = await response.json(); + const fetchFeed = useCallback(async () => { + if (status !== "unauthenticated") { + const user = (await sessionUser)?.id + try { + const response = await fetch(`/api/feed?user=${user}&page=${page}`, { next: { revalidate: 3600 } }); + if (!response.ok) { + throw new Error(`Fetch failed with status: ${response.status}`); + } + const data = await response.json(); + + setFeed((prevFeed: any) => [...prevFeed, ...data.feed]); + setFeedLength(data.feedLength); + setFetching(false); + setLoading(false); + } catch (error) { + console.error('Error fetching feed:', error); + setLoading(false); + setFetching(false); + } + } else { + setFetching(false) + route.push('/') + } + }, [page]) - setFeed((prevFeed: any) => [...prevFeed, ...data.feed]); - setPopularPosts(data.popular); - setTopUsers(topUsers.topUsers); - setFeedLength(data.feedLength); - setFetching(false); - setLoading(false); - } catch (error) { - console.error('Error fetching feed:', error); - setLoading(false); - setFetching(false); + const fetchPopularPosts = useCallback(async () => { + if(status === "authenticated") { + try { + const response = await fetch(`/api/posts/popular`, { next: { revalidate: 3600 } }); + if (!response.ok) { + throw new Error(`Fetch failed with status: ${response.status}`); } - } else { - setFetching(false) - route.push('/') + const data = await response.json(); + setPopularPosts(data.popular); + } catch (error) { + console.error('Error fetching popular posts:', error); } } + }, [status]) - fetchFeed() + const fetchTopUsers = useCallback(async () => { + if(status === "authenticated") { + try { + const response = await fetch(`/api/users/top?user=${(await sessionUser).id}`, { + method: "GET", + next: { revalidate: 3600 } + }); + if (!response.ok) { + throw new Error(`Fetch failed with status: ${response.status}`); + } + const data = await response.json(); + setTopUsers(data.topUsers); + } catch (error) { + console.error('Error fetching top users:', error); + } + } + }, [status]) + + useEffect(() => { + if(status === "authenticated") { + fetchPopularPosts() + fetchTopUsers() + } + }, [status]) + + useEffect(() => { + console.log('Feed length:', feedLength, 'Feed:', feed.length) + if (feedLength >= 0){ + if (feed.length <= feedLength) { + fetchFeed() + } + } }, [page]) useEffect(() => { - if (feedLength !== 0 && feed.length !== feedLength) { + if (feed.length < feedLength) { const observer = new IntersectionObserver( entries => { - if (entries[0].isIntersecting && !loading) { + if (entries[0].isIntersecting && !loading && feed.length < feedLength) { setPage(prevPage => prevPage + 1) } }, diff --git a/app/api/feed/route.ts b/app/api/feed/route.ts index eacf9e68..e443bd49 100644 --- a/app/api/feed/route.ts +++ b/app/api/feed/route.ts @@ -5,14 +5,9 @@ export async function GET(req: NextRequest, res: NextResponse) { try { const user_id = Number(req.nextUrl.searchParams.get('user')) let page = parseInt(req.nextUrl.searchParams.get('page')!) - let limit = 10 + let limit = 5 let offset = 0 - if (page > 0) { - limit = 5 - offset = (page + 1) * limit - } - const userFollowings = await postgres.follow.findMany({ select: { followingId: true, @@ -31,9 +26,14 @@ export async function GET(req: NextRequest, res: NextResponse) { createdAt: 'desc', }, take: limit, - skip: offset, + skip: page * limit, include: { - author: true, + author: { + include: { + Followers: true, + Followings: true, + } + }, _count: { select: { likes: true, @@ -54,25 +54,7 @@ export async function GET(req: NextRequest, res: NextResponse) { }, }) - const popular = await postgres.post.findMany({ - orderBy: { - views: 'desc', - }, - take: 5, - include: { - author: true, - _count: { - select: { - likes: true, - comments: true, - savedUsers: true, - }, - }, - tags: true, - } - }) - - return NextResponse.json({ feed, feedLength, popular }) + return NextResponse.json({ feed, feedLength }, { status: 200 }) } catch (error) { console.error(error) diff --git a/app/api/posts/popular/route.ts b/app/api/posts/popular/route.ts new file mode 100644 index 00000000..4a4d0f90 --- /dev/null +++ b/app/api/posts/popular/route.ts @@ -0,0 +1,30 @@ +import postgres from "@/lib/postgres"; +import { NextRequest, NextResponse } from "next/server"; + +export async function GET(req: NextRequest) { + try { + const popular = await postgres.post.findMany({ + orderBy: { + views: 'desc', + }, + take: 5, + include: { + author: true, + _count: { + select: { + likes: true, + comments: true, + savedUsers: true, + }, + }, + tags: true, + } + }) + + return NextResponse.json({ popular }, { status: 200 }); + } + catch (error) { + console.error(error); + return NextResponse.error(); + } +} \ No newline at end of file diff --git a/components/explore/navbar/items.ts b/components/explore/navbar/items.ts index a30b0812..e0a54ce3 100644 --- a/components/explore/navbar/items.ts +++ b/components/explore/navbar/items.ts @@ -1,4 +1,4 @@ -import { Compass, Hash, Home, Zap } from "lucide-react"; +import { Compass, GalleryVerticalEnd, Hash, Zap } from "lucide-react"; type Item = { label: string; icon: React.ElementType; @@ -8,7 +8,7 @@ type Item = { export const items = [ { label: "Feed", - icon: Home, + icon: GalleryVerticalEnd, path: "/feed", }, { diff --git a/components/feed/feed.tsx b/components/feed/feed.tsx index 39a64d8f..12570f43 100644 --- a/components/feed/feed.tsx +++ b/components/feed/feed.tsx @@ -42,12 +42,6 @@ export default function FeedComponent({ feed, children, isLoaded }: { feed: any; {children} - {feed.length !== 0 && ( -