fix: when getting user don't return entire user to client, fix: pass user to post component as part of post

This commit is contained in:
Stevan Freeborn
2023-09-11 13:44:51 -05:00
parent 4b74f47e75
commit e29b46cdb1
5 changed files with 76 additions and 50 deletions
+7 -9
View File
@@ -16,20 +16,18 @@ export async function userQuery(ctx: QueryCtx, clerkUserId: string) {
export const getUserByClerkId = query({ export const getUserByClerkId = query({
args: { clerkUserId: v.string() }, args: { clerkUserId: v.string() },
async handler(ctx, args) { async handler(ctx, args) {
return await userQuery(ctx, args.clerkUserId); const user = await userQuery(ctx, args.clerkUserId);
},
});
export const getUserById = query({
args: { id: v.id('users') },
async handler(ctx, args) {
const user = await ctx.db.get(args.id);
if (user === null) { if (user === null) {
return 'USER_NOT_FOUND'; return 'USER_NOT_FOUND';
} }
return user; return {
_id: user._id,
_creationTime: user._creationTime,
clerkUsername: user.clerkUser.username,
clerkImageUrl: user.clerkUser.image_url,
};
}, },
}); });
+1 -1
View File
@@ -13,7 +13,7 @@ export default async function UserProfilePage({
clerkUserId: params.id, clerkUserId: params.id,
}); });
if (user === null) { if (user === 'USER_NOT_FOUND') {
// TODO: Show real not found component // TODO: Show real not found component
return <div>Not Found</div>; return <div>Not Found</div>;
} }
+15 -21
View File
@@ -1,27 +1,21 @@
import { Text } from '@codemirror/state'; import { Text } from '@codemirror/state';
import { useQuery } from 'convex/react';
import Image from 'next/image'; import Image from 'next/image';
import { api } from '../../convex/_generated/api'; import { Doc, Id } from '../../convex/_generated/dataModel';
import { Doc } from '../../convex/_generated/dataModel';
import PostContent from './PostContent'; import PostContent from './PostContent';
import SpinningLoader from './SpinningLoader';
export default function Post({ post }: { post: Doc<'posts'> }) { export default function Post({
const user = useQuery(api.users.getUserById, { id: post.userId }); post,
}: {
if (user === undefined) { post: Doc<'posts'> & {
return ( user: {
<div> _id: Id<'users'>;
<SpinningLoader className='animate-spin w-5 h-5' /> _creationTime: number;
</div> clerkUsername: string | null;
); clerkImageUrl: string;
} };
};
if (user === 'USER_NOT_FOUND') { }) {
return <div>User for post not found</div>; const username = post.user.clerkUsername ?? post.user._id;
}
const username = user.clerkUser.username ?? user._id;
const createdPostDate = new Date(post._creationTime); const createdPostDate = new Date(post._creationTime);
const postYear = createdPostDate.getFullYear(); const postYear = createdPostDate.getFullYear();
const postMonth = createdPostDate.toLocaleString(undefined, { const postMonth = createdPostDate.toLocaleString(undefined, {
@@ -34,7 +28,7 @@ export default function Post({ post }: { post: Doc<'posts'> }) {
<div> <div>
<Image <Image
alt='user profile image' alt='user profile image'
src={user.clerkUser.image_url} src={post.user.clerkImageUrl}
width={40} width={40}
height={40} height={40}
className='rounded-full object-cover border-4 border-primary-accent' className='rounded-full object-cover border-4 border-primary-accent'
+40 -15
View File
@@ -2,37 +2,62 @@
import { usePaginatedQuery } from 'convex/react'; import { usePaginatedQuery } from 'convex/react';
import { api } from '../../convex/_generated/api'; import { api } from '../../convex/_generated/api';
import { Doc } from '../../convex/_generated/dataModel'; import { Id } from '../../convex/_generated/dataModel';
import Post from './Post'; import Post from './Post';
import SpinningLoader from './SpinningLoader';
export default function UserPosts({ user }: { user: Doc<'users'> }) { export default function UserPosts({
const PAGE_SIZE = 10; user,
}: {
user: {
_id: Id<'users'>;
_creationTime: number;
clerkUsername: string | null;
clerkImageUrl: string;
};
}) {
const PAGE_SIZE = 1;
const pager = usePaginatedQuery( const pager = usePaginatedQuery(
api.posts.getUsersPostById, api.posts.getUsersPostById,
{ {
userId: user._id, userId: user._id,
}, },
{ initialNumItems: 10 } { initialNumItems: PAGE_SIZE }
); );
const postsWithUser = pager.results.map(post => ({ ...post, user }));
return ( return (
<div className='flex flex-col w-full h-full'> <div className='flex flex-col items-center w-full h-full'>
{pager.results.map(post => ( {postsWithUser.map(post => (
<Post <Post
key={post._id} key={post._id}
post={post} post={post}
/> />
))} ))}
{pager.isLoading ? ( {pager.isLoading ? (
<div>Loading...</div> <div className='flex items-center gap-2 p-5'>
) : ( <SpinningLoader className='animate-spin w-5 h-5' />
<button Loading...
onClick={() => pager.loadMore(10)} </div>
disabled={pager.status !== 'CanLoadMore'} ) : pager.status === 'CanLoadMore' ? (
> <div className='flex items-center p-5'>
Load More <button
</button> className='bg-primary-accent px-3 py-1 rounded-full'
)} onClick={() => pager.loadMore(PAGE_SIZE)}
disabled={pager.status !== 'CanLoadMore'}
>
{pager.isLoading ? (
<>
<SpinningLoader className='animate-spin w-5 h-5' />
Loading...
</>
) : (
'Load More'
)}
</button>
</div>
) : null}
</div> </div>
); );
} }
+13 -4
View File
@@ -1,9 +1,18 @@
import Image from 'next/image'; import Image from 'next/image';
import { AiFillCalendar } from 'react-icons/ai'; import { AiFillCalendar } from 'react-icons/ai';
import { Doc } from '../../convex/_generated/dataModel'; import { Doc, Id } from '../../convex/_generated/dataModel';
export default function UserProfile({ user }: { user: Doc<'users'> }) { export default function UserProfile({
const username = user.clerkUser.username ?? user._id; user,
}: {
user: {
_id: Id<'users'>;
_creationTime: number;
clerkUsername: string | null;
clerkImageUrl: string;
};
}) {
const username = user.clerkUsername ?? user._id;
const userCreatedDate = new Date(user._creationTime); const userCreatedDate = new Date(user._creationTime);
const monthJoined = userCreatedDate.toLocaleString(undefined, { const monthJoined = userCreatedDate.toLocaleString(undefined, {
month: 'short', month: 'short',
@@ -17,7 +26,7 @@ export default function UserProfile({ user }: { user: Doc<'users'> }) {
<div> <div>
<Image <Image
alt='user profile image' alt='user profile image'
src={user.clerkUser.image_url} src={user.clerkImageUrl}
width={100} width={100}
height={100} height={100}
className='rounded-full object-cover border-4 border-primary-accent' className='rounded-full object-cover border-4 border-primary-accent'