From 7e3a6170e3d4a97a1670eea616b05da1c5dd1a12 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Fri, 15 Sep 2023 21:56:41 -0500 Subject: [PATCH] feat: display posts of those a user follows on following page --- .vscode/settings.json | 1 + convex/posts.ts | 71 ++++++++++++++++++++++++++++++- src/app/following/page.tsx | 12 ++++++ src/components/AllPosts.tsx | 10 +++++ src/components/FollowingPosts.tsx | 57 +++++++++++++++++++++++++ src/components/Navbar.tsx | 2 +- 6 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 src/app/following/page.tsx create mode 100644 src/components/FollowingPosts.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json index 5b7c996..c5c3a86 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "cSpell.words": [ "codemirror", "conve", + "doesn", "Keymap", "lezer", "nextjs", diff --git a/convex/posts.ts b/convex/posts.ts index c96b296..1e04167 100644 --- a/convex/posts.ts +++ b/convex/posts.ts @@ -1,4 +1,4 @@ -import { paginationOptsValidator } from 'convex/server'; +import { PaginationResult, paginationOptsValidator } from 'convex/server'; import { v } from 'convex/values'; import { PostWithUserDto } from '../src/app/types'; import { Id } from './_generated/dataModel'; @@ -203,3 +203,72 @@ export const getAllPostsWithUser = query({ return { ...posts, page: postsWithUser }; }, }); + +export const getAllPostsForFollowings = query({ + args: { paginationOpts: paginationOptsValidator }, + handler: async (ctx, args): Promise> => { + const currentUser = await ctx.auth.getUserIdentity(); + + if (currentUser === null) { + return { isDone: true, continueCursor: '', page: [] }; + } + + const user = await userQuery(ctx, currentUser.subject); + + if (user === null) { + return { isDone: true, continueCursor: '', page: [] }; + } + + const followings = await ctx.db + .query('follows') + .withIndex('by_follower', q => q.eq('follower', user._id)) + .collect(); + + const posts = await ctx.db + .query('posts') + .filter(q => + q.and( + q.or( + ...followings.map(following => + q.eq(q.field('userId'), following.following) + ) + ), + q.eq(q.field('parentPostId'), undefined) + ) + ) + .order('desc') + .paginate(args.paginationOpts); + + const postsWithUser = await Promise.all( + posts.page.map(async post => { + const user = await ctx.db.get(post.userId); + + if (user === null) { + return { + ...post, + user: { + _id: '' as Id<'users'>, + _creationTime: 0, + clerkUsername: null, + clerkImageUrl: '', + clerkUserId: '', + }, + }; + } + + return { + ...post, + user: { + _id: user._id, + _creationTime: user._creationTime, + clerkUsername: user.clerkUser.username, + clerkImageUrl: user.clerkUser.image_url, + clerkUserId: user.clerkUser.id, + }, + }; + }) + ); + + return { ...posts, page: postsWithUser }; + }, +}); diff --git a/src/app/following/page.tsx b/src/app/following/page.tsx new file mode 100644 index 0000000..7e4e86d --- /dev/null +++ b/src/app/following/page.tsx @@ -0,0 +1,12 @@ +import FollowingPosts from '@/components/FollowingPosts'; + +export default function FollowingPage() { + return ( +
+
+

Following

+ +
+
+ ); +} diff --git a/src/components/AllPosts.tsx b/src/components/AllPosts.tsx index 87ef44a..889136f 100644 --- a/src/components/AllPosts.tsx +++ b/src/components/AllPosts.tsx @@ -17,6 +17,16 @@ export default function AllPosts() { pager.loadMore(PAGE_SIZE); } + if (pager.isLoading === false && pager.results.length == 0) { + return ( +
+

+ Hmmm it doesn't look like anyone has posted. +

+
+ ); + } + return (
diff --git a/src/components/FollowingPosts.tsx b/src/components/FollowingPosts.tsx new file mode 100644 index 0000000..39985c4 --- /dev/null +++ b/src/components/FollowingPosts.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { usePaginatedQuery } from 'convex/react'; +import Link from 'next/link'; +import { api } from '../../convex/_generated/api'; +import Loader from './Loader'; +import Post from './Post'; + +export default function FollowingPosts() { + const PAGE_SIZE = 10; + const pager = usePaginatedQuery( + api.posts.getAllPostsForFollowings, + {}, + { initialNumItems: PAGE_SIZE } + ); + + function handleLoadMoreClick() { + pager.loadMore(PAGE_SIZE); + } + + if (pager.isLoading === false && pager.results.length == 0) { + return ( +
+

+ Hmmm it doesn't look like you follow anyone or anyone who has + made a post yet. +

+ + Find someone to follow + +
+ ); + } + + return ( +
+
+ {pager.results.map(post => ( +
+ +
+ ))} +
+ +
+ ); +} diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 8c49641..af9e54f 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -85,7 +85,7 @@ export default function Navbar() {
setNavOpen(false)} - href='#' + href='/following' > Following