diff --git a/.vscode/settings.json b/.vscode/settings.json
index c5c3a86..3737ea8 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,6 +4,7 @@
"codemirror",
"conve",
"doesn",
+ "Dtos",
"Keymap",
"lezer",
"nextjs",
diff --git a/convex/posts.ts b/convex/posts.ts
index 581dfe6..c9331fa 100644
--- a/convex/posts.ts
+++ b/convex/posts.ts
@@ -1,9 +1,9 @@
import { paginationOptsValidator } from 'convex/server';
import { v } from 'convex/values';
import { PostWithUserDto } from '../src/app/types';
-import { Id } from './_generated/dataModel';
-import { mutation, query } from './_generated/server';
-import { userQuery } from './users';
+import { Doc } from './_generated/dataModel.d';
+import { QueryCtx, mutation, query } from './_generated/server';
+import { createUserDto, userQuery } from './users';
export const createOrUpdatePost = mutation({
args: {
@@ -82,13 +82,7 @@ export const getPostById = query({
return {
...post,
- user: {
- _id: user._id,
- _creationTime: user._creationTime,
- clerkUsername: user.clerkUser.username,
- clerkImageUrl: user.clerkUser.image_url,
- clerkUserId: user.clerkUser.id,
- },
+ user: createUserDto(user),
};
},
});
@@ -102,36 +96,10 @@ export const getRepliesByParentId = query({
.order('desc')
.paginate(args.paginationOpts);
- const repliesWithUserData = await Promise.all(
- replies.page.map(async reply => {
- const user = await ctx.db.get(reply.userId);
-
- if (user === null) {
- return {
- ...reply,
- user: {
- _id: '' as Id<'users'>,
- _creationTime: 0,
- clerkUsername: null,
- clerkImageUrl: '',
- clerkUserId: '',
- },
- };
- }
-
- return {
- ...reply,
- user: {
- _id: user._id,
- _creationTime: user._creationTime,
- clerkUsername: user.clerkUser.username,
- clerkImageUrl: user.clerkUser.image_url,
- clerkUserId: user.clerkUser.id,
- },
- };
- })
- );
-
+ const repliesWithUserData = await getPostsWithUsers({
+ ctx,
+ posts: replies.page,
+ });
return { ...replies, page: repliesWithUserData };
},
});
@@ -170,35 +138,7 @@ export const getAllPostsWithUser = query({
.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,
- },
- };
- })
- );
+ const postsWithUser = await getPostsWithUsers({ ctx, posts: posts.page });
return { ...posts, page: postsWithUser };
},
@@ -239,35 +179,7 @@ export const getAllPostsForFollowings = query({
.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,
- },
- };
- })
- );
+ const postsWithUser = await getPostsWithUsers({ ctx, posts: posts.page });
return { ...posts, page: postsWithUser };
},
@@ -276,11 +188,41 @@ export const getAllPostsForFollowings = query({
export const getPostsBySearchTerm = query({
args: { term: v.string(), paginationOpts: paginationOptsValidator },
handler: async (ctx, args) => {
- return await ctx.db
+ const posts = await ctx.db
.query('posts')
.withSearchIndex('search_by_content', q =>
q.search('content', args.term).eq('parentPostId', undefined)
)
.paginate(args.paginationOpts);
+
+ const postsWithUser = await getPostsWithUsers({ ctx, posts: posts.page });
+
+ return { ...posts, page: postsWithUser };
},
});
+
+async function getPostsWithUsers({
+ ctx,
+ posts,
+}: {
+ ctx: QueryCtx;
+ posts: Doc<'posts'>[];
+}) {
+ return await Promise.all(
+ posts.map(async post => {
+ const user = await ctx.db.get(post.userId);
+
+ if (user === null) {
+ return {
+ ...post,
+ user: createUserDto(user),
+ };
+ }
+
+ return {
+ ...post,
+ user: createUserDto(user),
+ };
+ })
+ );
+}
diff --git a/convex/schema.ts b/convex/schema.ts
index 3784e03..bb58827 100644
--- a/convex/schema.ts
+++ b/convex/schema.ts
@@ -38,6 +38,7 @@ export default defineSchema(
.index('by_clerk_id', ['clerkUser.id'])
.searchIndex('search_by_username', {
searchField: 'clerkUser.username',
+ filterFields: [],
}),
posts: defineTable({
parentPostId: v.optional(v.id('posts')),
diff --git a/convex/users.ts b/convex/users.ts
index 8dbb8d6..cc8bf7f 100644
--- a/convex/users.ts
+++ b/convex/users.ts
@@ -1,6 +1,7 @@
import { paginationOptsValidator } from 'convex/server';
import { v } from 'convex/values';
import { UserDto } from './../src/app/types/index';
+import { Doc, Id } from './_generated/dataModel';
import {
QueryCtx,
internalMutation,
@@ -24,13 +25,7 @@ export const getUserByClerkId = query({
return 'USER_NOT_FOUND';
}
- return {
- _id: user._id,
- _creationTime: user._creationTime,
- clerkUsername: user.clerkUser.username,
- clerkImageUrl: user.clerkUser.image_url,
- clerkUserId: user.clerkUser.id,
- };
+ return createUserDto(user);
},
});
@@ -43,13 +38,7 @@ export const getUserById = query({
return 'USER_NOT_FOUND';
}
- return {
- _id: user._id,
- _creationTime: user._creationTime,
- clerkUsername: user.clerkUser.username,
- clerkImageUrl: user.clerkUser.image_url,
- clerkUserId: user.clerkUser.id,
- };
+ return createUserDto(user);
},
});
@@ -126,11 +115,35 @@ export const deleteUser = internalMutation({
export const getUsersBySearchTerm = query({
args: { term: v.string(), paginationOpts: paginationOptsValidator },
handler: async (ctx, args) => {
- return await ctx.db
+ const users = await ctx.db
.query('users')
.withSearchIndex('search_by_username', q =>
q.search('clerkUser.username', args.term)
)
.paginate(args.paginationOpts);
+
+ const userDtos = users.page.map(createUserDto);
+
+ return { ...users, page: userDtos };
},
});
+
+export function createUserDto(user: Doc<'users'> | null) {
+ if (user === null) {
+ return {
+ _id: '' as Id<'users'>,
+ _creationTime: 0,
+ clerkUsername: null,
+ clerkImageUrl: '',
+ clerkUserId: '',
+ };
+ }
+
+ return {
+ _id: user._id,
+ _creationTime: user._creationTime,
+ clerkUsername: user.clerkUser.username,
+ clerkImageUrl: user.clerkUser.image_url,
+ clerkUserId: user.clerkUser.id,
+ };
+}
diff --git a/src/app/search/[term]/page.tsx b/src/app/search/[term]/page.tsx
new file mode 100644
index 0000000..7a04868
--- /dev/null
+++ b/src/app/search/[term]/page.tsx
@@ -0,0 +1,12 @@
+import SearchResults from '@/components/SearchResults';
+
+export default function SearchPage({ params }: { params: { term: string } }) {
+ return (
+ Here's what we found
+