feat: finish search feature

This commit is contained in:
Stevan Freeborn
2023-09-16 11:28:55 -05:00
parent e2161e62c3
commit 9ad0b51b29
6 changed files with 87 additions and 20 deletions
-1
View File
@@ -201,7 +201,6 @@ export const getPostsBySearchTerm = query({
.withSearchIndex('search_by_content', q =>
q.search('contentText', args.term)
)
.filter(q => q.eq(q.field('parentPostId'), undefined))
.paginate(args.paginationOpts);
const postsWithUser = await getPostsWithUsers({ ctx, posts: posts.page });
+1 -1
View File
@@ -11,7 +11,7 @@ export default function Loader({
}) {
if (isLoading) {
return (
<div className='flex w-full items-center justify-center gap-2 p-5 border-t border-gray-600 text-sm'>
<div className='flex w-full items-center justify-center gap-2 p-5 text-sm'>
<SpinningLoader className='animate-spin w-5 h-5' />
Loading...
</div>
+3 -2
View File
@@ -6,7 +6,7 @@ import Link from 'next/link';
import { useEffect, useState } from 'react';
import { AiFillHome } from 'react-icons/ai';
import { BiLogIn, BiPlus } from 'react-icons/bi';
import { BsPersonPlusFill } from 'react-icons/bs';
import { BsPersonPlusFill, BsSearch } from 'react-icons/bs';
import { ImProfile } from 'react-icons/im';
import {
RiMenuFoldLine,
@@ -75,10 +75,11 @@ export default function Navbar() {
className='w-full md:w-[unset] py-1 px-2 rounded-md border border-gray-600 dark:bg-primary-gray dark:border-0'
/>
<button
className='flex items-center justify-center absolute right-0 top-1/2 transform -translate-x-1/2 -translate-y-1/2'
disabled={!term || !term.trim()}
type='submit'
>
Search
<BsSearch />
</button>
</form>
</li>
+81 -14
View File
@@ -1,13 +1,15 @@
'use client';
import { PostWithUserDto, UserDto } from '@/app/types';
import { UsePaginatedQueryReturnType, usePaginatedQuery } from 'convex/react';
import { FunctionReference } from 'convex/server';
import { useState } from 'react';
import { api } from '../../convex/_generated/api';
import { Id } from '../../convex/_generated/dataModel';
import Loader from './Loader';
import Post from './Post';
import UserProfile from './UserProfile';
type UserSearchResultsPager = UsePaginatedQueryReturnType<
type Pager<T> = UsePaginatedQueryReturnType<
FunctionReference<
'query',
'public',
@@ -20,29 +22,84 @@ type UserSearchResultsPager = UsePaginatedQueryReturnType<
};
},
{
page: {
_id: Id<'users'>;
_creationTime: number;
clerkUsername: string | null;
clerkImageUrl: string;
clerkUserId: string;
}[];
page: T[];
isDone: boolean;
continueCursor: string;
}
>
>;
function UserSearchResults({ pager }: { pager: UserSearchResultsPager }) {
function NoResults() {
return (
<div className='flex flex-col justify-center items-center gap-2'>
<h2 className='text-xl'>
Hmmm it doesn&apos;t look like we could find anything.
</h2>
</div>
);
}
function UserSearchResults({
pager,
pageSize,
}: {
pager: Pager<UserDto>;
pageSize: number;
}) {
const { status, results, isLoading, loadMore } = pager;
if (isLoading === false && results.length == 0) {
return <NoResults />;
}
return (
<div>
<div>
{pager.results.map(user => (
<div className='flex flex-col gap-2'>
{results.map(user => (
<div key={user._id}>
<UserProfile user={user} />
</div>
))}
</div>
<Loader
isLoading={isLoading}
status={status}
loadButtonClickHandler={() => loadMore(pageSize)}
/>
</div>
);
}
function PostSearchResults({
pager,
pageSize,
}: {
pager: Pager<PostWithUserDto>;
pageSize: number;
}) {
const { status, results, isLoading, loadMore } = pager;
if (isLoading === false && results.length == 0) {
return <NoResults />;
}
return (
<div className='flex flex-col items-center w-full'>
<div className='flex flex-col items-center w-full'>
{results.map(post => (
<div
key={post._id}
className='w-full border border-t-0 border-gray-600 first:border-t last:rounded-b-md p-1 last:mb-4'
>
<Post post={post} />
</div>
))}
</div>
<Loader
isLoading={isLoading}
status={status}
loadButtonClickHandler={() => loadMore(pageSize)}
/>
</div>
);
}
@@ -63,7 +120,7 @@ export default function SearchResults({ term }: { term: string }) {
);
return (
<div>
<div className='flex flex-col gap-4'>
<div className='flex gap-2 border-b border-gray-600'>
<button
onClick={() => setCurrent('posts')}
@@ -83,7 +140,17 @@ export default function SearchResults({ term }: { term: string }) {
</button>
</div>
{current === 'posts' ? 'Posts' : <UserSearchResults pager={usersPager} />}
{current === 'posts' ? (
<PostSearchResults
pager={postsPager}
pageSize={PAGE_SIZE}
/>
) : (
<UserSearchResults
pager={usersPager}
pageSize={PAGE_SIZE}
/>
)}
</div>
);
}
+1 -1
View File
@@ -47,7 +47,7 @@ export default function UserPosts({ user }: { user: UserDto }) {
{postsWithUser.map(post => (
<div
key={post._id}
className='w-full border border-t-0 border-gray-600 first:border-t last:rounded-b-md p-1 last:mb-4'
className='w-full border border-t-0 border-gray-600 last:rounded-b-md p-1 last:mb-4'
>
<Post post={post} />
</div>
+1 -1
View File
@@ -90,7 +90,7 @@ export default function UserProfile({ user }: { user: UserDto }) {
</div>
</div>
</div>
<div className='flex flex-1 bg-white dark:bg-primary-gray pl-5 border border-gray-600 border-b-0'>
<div className='flex flex-1 bg-white dark:bg-primary-gray pl-5 border border-gray-600'>
<div className='flex flex-col min-h-[25px] items-start gap-1 py-1 pl-[116px] md:flex-row md:items-center md:gap-4'>
{countDataLoaded ? (
<>