From 0a79f9f7a823c4f5997bf82e0641075fab5f65ce Mon Sep 17 00:00:00 2001 From: Bakhtiyor Ganijon Date: Tue, 7 Nov 2023 09:23:16 +0900 Subject: [PATCH 1/2] Update feed components and navbar --- app/(Main)/feed/page.tsx | 12 +-- components/feed/get-feed.ts | 6 +- components/feed/get-foryou.ts | 11 +- components/feed/navbar/navbar.tsx | 9 +- lib/prisma/feed.ts | 165 +++++++++++++++++++----------- 5 files changed, 125 insertions(+), 78 deletions(-) diff --git a/app/(Main)/feed/page.tsx b/app/(Main)/feed/page.tsx index cb8ce352..952b3e0d 100644 --- a/app/(Main)/feed/page.tsx +++ b/app/(Main)/feed/page.tsx @@ -12,7 +12,6 @@ import { redirect } from 'next/navigation'; import { fetchFollowingTags } from '@/components/get-following-tags'; import { getSession } from 'next-auth/react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { fetchForYou } from '@/components/feed/get-foryou'; import { getBookmarks } from '@/lib/prisma/session'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { dateFormat } from '@/lib/format-date'; @@ -25,15 +24,14 @@ export default async function Feed({ searchParams: { [key: string]: string | string[] | undefined } }) { - const tag = typeof searchParams.tag === 'string' ? searchParams.tag : undefined - const feed = await fetchFeed({ page: 0, tag }); + const tab = typeof searchParams.tab === 'string' ? searchParams.tab : undefined + const feed = await fetchFeed({ page: 0, tab }); const session = await getSessionUser(); const topData = await fetchUsers({ id: session?.id }) const topUsers = topData?.topUsers; const popularTags = await fetchTags(); - console.log(topData) if (!session) { return redirect('/') } @@ -42,14 +40,12 @@ export default async function Feed({ const { bookmarks, bookmarksCount } = await getBookmarks({ id: session?.id }) - const recommendedPosts = await fetchForYou({ page: 0 }) - return ( <>
- {userFollowings.length !== 0 && } +
{!feed || feed.length === 0 ? (
@@ -59,7 +55,7 @@ export default async function Feed({
) : ( - + )}
diff --git a/components/feed/get-feed.ts b/components/feed/get-feed.ts index 925e08d3..083e4b7c 100644 --- a/components/feed/get-feed.ts +++ b/components/feed/get-feed.ts @@ -1,7 +1,7 @@ import { getFeed } from "@/lib/prisma/feed"; -export const fetchFeed = async ({ page = 0, tag }: { page?: number, tag?: string | undefined }) => { - const result = await getFeed({ page, tag }); - +export const fetchFeed = async ({ page = 0, tab }: { page?: number, tab?: string | undefined }) => { + const result = await getFeed({ page, tab }); + console.log(result, 'result') return result?.feed; } \ No newline at end of file diff --git a/components/feed/get-foryou.ts b/components/feed/get-foryou.ts index 7dba1f6f..574a3032 100644 --- a/components/feed/get-foryou.ts +++ b/components/feed/get-foryou.ts @@ -1,5 +1,8 @@ -export const fetchForYou = async ({ page = 0 }: { page?: number }) => { - // const result = await getForYou({ page, tag }); +// import { getForYou } from "@/lib/prisma/feed"; + +// export const fetchForYou = async ({ page = 0 }: { page?: number }) => { +// const result = await getForYou({ page }); - // return result?.feed; -} \ No newline at end of file +// return result?.feed; +// } + diff --git a/components/feed/navbar/navbar.tsx b/components/feed/navbar/navbar.tsx index 740b961b..d4091a8b 100644 --- a/components/feed/navbar/navbar.tsx +++ b/components/feed/navbar/navbar.tsx @@ -5,7 +5,7 @@ import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; import { useInView } from "react-intersection-observer"; -export default function FeedTabs({ tabs, activeTab = 'following', children }: { tabs: any, activeTab?: string, children?: React.ReactNode }) { +export default function FeedTabs({ tabs, activeTab = 'foryou', children }: { tabs: any, activeTab?: string, children?: React.ReactNode }) { const [firstTab, inFView] = useInView(); const [lastTab, inLView] = useInView(); @@ -26,13 +26,18 @@ export default function FeedTabs({ tabs, activeTab = 'following', children }: { + + For You + + + Following {tabs?.map((item: any, index: number) => ( - + {item.tag.name.replace(/-/g, " ")} diff --git a/lib/prisma/feed.ts b/lib/prisma/feed.ts index 68076ecd..7d1f0927 100644 --- a/lib/prisma/feed.ts +++ b/lib/prisma/feed.ts @@ -1,5 +1,75 @@ import { getSessionUser } from "@/components/get-session-user"; import postgres from "../postgres"; +import { getBookmarks, getHistory, getLikes } from "./session"; +import { Like } from "@prisma/client"; + +export const getForYou = async ({ page = 0 }: { page?: number }) => { + const user = await getSessionUser(); + if (!user) { + return null; + } + const { id } = user; + + //get user's interests + const { likes: userLikes } = await getLikes({id}); + const { bookmarks: userBookmarks } = await getBookmarks({id}); + const { history: userHistory } = await getHistory({id}); + + // Fetch the tags of the posts in parallel +const tags = await postgres.postTag.findMany({ + where: { + OR: [ + { postId: { in: userLikes.map((like: Like) => like.postId) } }, + { postId: { in: userBookmarks.map((bookmark: any) => bookmark.postId) } }, + { postId: { in: userHistory.map((history: any) => history.postId) } }, + ] + }, + select: { + tagId: true, + }, +}); +console.log(tags.length, 'tags') + +const baseQuery = { + orderBy: { createdAt: "desc" }, + take: 5, + skip: page * 5, + include: { + author: true, + savedUsers: true, + _count: { + select: { + likes: true, + savedUsers: true, + }, + }, + tags: { + take: 1, + include: { + tag: true, + }, + }, + }, +}; + +// Count the occurrences of each tag +const tagCounts = tags.reduce((counts, tag) => { + counts[tag.tagId] = (counts[tag.tagId] || 0) + 1; + return counts; +}, {} as Record); + +// Sort the tags by their count in descending order +const sortedTagIds = Object.entries(tagCounts).sort((a, b) => b[1] - a[1]).map(([tagId]) => Number(tagId)); + +// Fetch the posts that have the tags of the user's main interests +console.log(sortedTagIds, 'sortedTagIds') +const posts = await postgres.post.findMany({ + where: { tags: { some: { tagId: { in: sortedTagIds.slice(0, 5) } } } }, + select: { id: true }, +}); +console.log(posts.length, 'for you posts') +return posts +}; const fetchFeed = async (query: any) => { try { @@ -10,13 +80,15 @@ const fetchFeed = async (query: any) => { } }; -export const getFeed = async ({ page = 0, tag }: { page?: number; tag?: string | undefined }) => { +export const getFeed = async ({ page = 0, tab }: { page?: number; tab?: string | undefined }) => { const user = await getSessionUser(); if (!user) { return null; } const { id } = user; + console.log(tab, 'tab') + const baseQuery = { orderBy: { createdAt: "desc" }, take: 5, @@ -38,72 +110,43 @@ export const getFeed = async ({ page = 0, tag }: { page?: number; tag?: string | }, }, }; + if (tab === undefined) { + const posts = await getForYou({ page }); + return fetchFeed({ + where: { id: { in: posts?.map((post) => post.id) }, visibility: "public" }, + ...baseQuery, + }); + } - if (tag) { + if (tab) { + if (tab == "following") { + const following = await postgres.follow.findMany({ + select: { followingId: true }, + where: { followerId: id }, + }); + const followingIds = following.map((user) => user.followingId); + return fetchFeed({ + ...baseQuery, + where: { authorId: { in: followingIds }, visibility: "public" }, + include: { + ...baseQuery.include, + author: { + include: { + Followers: true, + Followings: true, + }, + }, + }, + }); + } const postTags = await postgres.postTag.findMany({ select: { postId: true }, - where: { tag: { name: { equals: tag } } }, + where: { tag: { name: { equals: tab } } }, }); const postIds = postTags.map((postTag) => postTag.postId); return fetchFeed({ ...baseQuery, where: { id: { in: postIds }, visibility: "public" }, }); - } else { - const following = await postgres.follow.findMany({ - select: { followingId: true }, - where: { followerId: id }, - }); - const followingIds = following.map((user) => user.followingId); - return fetchFeed({ - ...baseQuery, - where: { authorId: { in: followingIds }, visibility: "public" }, - include: { - ...baseQuery.include, - author: { - include: { - Followers: true, - Followings: true, - }, - }, - }, - }); - } -}; - -//fetch recommended posts according to user's interests (likes, bookmarks, reading history) -// export const getForYou = async ({ page = 0, tag }: { page?: number; tag?: string | undefined }) => { -// const user = await getSessionUser(); -// if (!user) { -// return null; -// } -// const { id } = user; - -// const baseQuery = { -// orderBy: { createdAt: "desc" }, -// take: 5, -// skip: page * 5, -// include: { -// author: true, -// _count: { -// select: { -// likes: true, -// savedUsers: true, -// }, -// }, -// tags: { -// take: 1, -// include: { -// tag: true, -// }, -// }, -// }, -// }; - -// //get user's interests -// const userLikes = await getLikes({id}); -// const userBookmarks = await getBookmarks({id}); -// const userHistory = await getHistory({id}); - - -// } \ No newline at end of file + } +}; \ No newline at end of file From 3f2415c2a4b7caabab868354decf64fd5955da58 Mon Sep 17 00:00:00 2001 From: Bakhtiyor Ganijon Date: Tue, 7 Nov 2023 09:24:49 +0900 Subject: [PATCH 2/2] Fix getForYou import and update fetchForYou function. --- components/feed/get-foryou.ts | 10 +++++----- lib/prisma/feed.ts | 13 ++++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/components/feed/get-foryou.ts b/components/feed/get-foryou.ts index 574a3032..1a14b10e 100644 --- a/components/feed/get-foryou.ts +++ b/components/feed/get-foryou.ts @@ -1,8 +1,8 @@ -// import { getForYou } from "@/lib/prisma/feed"; +import { getForYou } from "@/lib/prisma/feed"; -// export const fetchForYou = async ({ page = 0 }: { page?: number }) => { -// const result = await getForYou({ page }); +export const fetchForYou = async ({ page = 0 }: { page?: number }) => { + const result = await getForYou({ page }); -// return result?.feed; -// } + return result?.feed; +} diff --git a/lib/prisma/feed.ts b/lib/prisma/feed.ts index 7d1f0927..7cc3561e 100644 --- a/lib/prisma/feed.ts +++ b/lib/prisma/feed.ts @@ -68,7 +68,10 @@ const posts = await postgres.post.findMany({ select: { id: true }, }); console.log(posts.length, 'for you posts') -return posts +return fetchFeed({ + where: { id: { in: posts.map((post) => post.id) }, visibility: "public" }, + ...baseQuery, +}); }; const fetchFeed = async (query: any) => { @@ -110,12 +113,8 @@ export const getFeed = async ({ page = 0, tab }: { page?: number; tab?: string | }, }, }; - if (tab === undefined) { - const posts = await getForYou({ page }); - return fetchFeed({ - where: { id: { in: posts?.map((post) => post.id) }, visibility: "public" }, - ...baseQuery, - }); + if (!tab) { + return await getForYou({ page }); } if (tab) {