feat: begin building out search results component

This commit is contained in:
Stevan Freeborn
2023-09-15 23:43:36 -05:00
parent 2162f87cfb
commit 18cb4fe0d9
7 changed files with 191 additions and 116 deletions
+19 -2
View File
@@ -1,5 +1,6 @@
'use client';
import { useRouter } from '@/hooks';
import { SignedIn, SignedOut, useUser } from '@clerk/nextjs';
import Link from 'next/link';
import { useEffect, useState } from 'react';
@@ -16,8 +17,10 @@ import ThemeButton from './ThemeButton';
import UserButton from './UserButton';
export default function Navbar() {
const [term, setTerm] = useState('');
const { user } = useUser();
const [navOpen, setNavOpen] = useState(false);
const router = useRouter();
useEffect(() => {
function handler() {
@@ -57,13 +60,27 @@ export default function Navbar() {
<ul className='flex flex-col w-full items-start gap-4 md:flex-row md:items-center md:max-w-min'>
<SignedIn>
<li className='flex w-full'>
<div className='flex w-full'>
<form
onSubmit={e => {
e.preventDefault();
router.push(`/search/${term}`);
}}
className='flex w-full relative'
>
<input
onChange={e => setTerm(e.target.value)}
value={term}
type='text'
placeholder='Search'
className='w-full md:w-[unset] py-1 px-2 rounded-md border border-gray-600 dark:bg-primary-gray dark:border-0'
/>
</div>
<button
disabled={!term || !term.trim()}
type='submit'
>
Search
</button>
</form>
</li>
<li>
<div className='flex items-center gap-2'>
+89
View File
@@ -0,0 +1,89 @@
'use client';
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 UserProfile from './UserProfile';
type UserSearchResultsPager = UsePaginatedQueryReturnType<
FunctionReference<
'query',
'public',
{
term: string;
paginationOpts: {
id?: number | undefined;
numItems: number;
cursor: string | null;
};
},
{
page: {
_id: Id<'users'>;
_creationTime: number;
clerkUsername: string | null;
clerkImageUrl: string;
clerkUserId: string;
}[];
isDone: boolean;
continueCursor: string;
}
>
>;
function UserSearchResults({ pager }: { pager: UserSearchResultsPager }) {
return (
<div>
<div>
{pager.results.map(user => (
<div key={user._id}>
<UserProfile user={user} />
</div>
))}
</div>
</div>
);
}
export default function SearchResults({ term }: { term: string }) {
const PAGE_SIZE = 10;
const [current, setCurrent] = useState<'posts' | 'users'>('posts');
const postsPager = usePaginatedQuery(
api.posts.getPostsBySearchTerm,
{ term },
{ initialNumItems: PAGE_SIZE }
);
const usersPager = usePaginatedQuery(
api.users.getUsersBySearchTerm,
{ term },
{ initialNumItems: PAGE_SIZE }
);
return (
<div>
<div className='flex gap-2 border-b border-gray-600'>
<button
onClick={() => setCurrent('posts')}
disabled={current === 'posts'}
type='button'
className='py-1 px-2 border-b-4 border-transparent disabled:border-primary-accent'
>
Posts
</button>
<button
onClick={() => setCurrent('users')}
disabled={current === 'users'}
type='button'
className='py-1 px-2 border-b-4 border-transparent disabled:border-primary-accent'
>
Users
</button>
</div>
{current === 'posts' ? 'Posts' : <UserSearchResults pager={usersPager} />}
</div>
);
}