-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Konstantin/rka 26 create pagination (#11)
* rka-26: add filters * rka-26: add pagination * rka-26: add use callback to a function in Pagination
- Loading branch information
1 parent
a720974
commit 2fa9706
Showing
8 changed files
with
236 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
'use client' | ||
|
||
import type { GetJobsFilter } from '@/lib/db/queries' | ||
import { Button, Flex, Reset } from '@radix-ui/themes' | ||
import Link from 'next/link' | ||
import { usePathname, useSearchParams } from 'next/navigation' | ||
import { useCallback } from 'react' | ||
|
||
const FilterButton = ({ | ||
searchParams, | ||
title, | ||
active = false, | ||
}: { searchParams: string; title: string; active?: boolean }) => { | ||
const pathname = usePathname() | ||
|
||
return ( | ||
<Link href={`${pathname}?${searchParams}`}> | ||
<Button variant={active ? 'solid' : 'outline'}>{title}</Button> | ||
</Link> | ||
) | ||
} | ||
|
||
export const FilterPanel = () => { | ||
const searchParams = useSearchParams() | ||
|
||
const createSearchParams = useCallback( | ||
(filter: GetJobsFilter, shouldReset = filter === 'all') => { | ||
const newSearchParams = new URLSearchParams(searchParams) | ||
|
||
const shouldRemove = newSearchParams | ||
.getAll('filter') | ||
.some(existingFilter => existingFilter === filter) | ||
|
||
if (!newSearchParams.has('filter')) { | ||
newSearchParams.set('filter', 'new') | ||
} | ||
|
||
if (shouldRemove) { | ||
newSearchParams.delete('filter', filter) | ||
} else if (shouldReset) { | ||
newSearchParams.set('filter', filter) | ||
} else { | ||
newSearchParams.delete('filter', 'all') | ||
newSearchParams.append('filter', filter) | ||
} | ||
|
||
return newSearchParams.toString() | ||
}, | ||
[searchParams], | ||
) | ||
|
||
return ( | ||
<Flex gap="3" asChild> | ||
<Reset> | ||
<ul> | ||
<li> | ||
<FilterButton | ||
title="New / Unseen" | ||
searchParams={createSearchParams('new')} | ||
active={ | ||
searchParams.getAll('filter').includes('new') || | ||
!searchParams.has('filter') | ||
} | ||
/> | ||
</li> | ||
<li> | ||
<FilterButton | ||
title="Top Choice" | ||
searchParams={createSearchParams('topChoice')} | ||
active={searchParams.getAll('filter').includes('topChoice')} | ||
/> | ||
</li> | ||
<li> | ||
<FilterButton | ||
title="Seen" | ||
searchParams={createSearchParams('seen')} | ||
active={searchParams.getAll('filter').includes('seen')} | ||
/> | ||
</li> | ||
<li> | ||
<FilterButton | ||
title="Hidden" | ||
searchParams={createSearchParams('hidden')} | ||
active={searchParams.getAll('filter').includes('hidden')} | ||
/> | ||
</li> | ||
<li> | ||
<FilterButton | ||
title="All" | ||
searchParams={createSearchParams('all')} | ||
active={searchParams.getAll('filter').includes('all')} | ||
/> | ||
</li> | ||
</ul> | ||
</Reset> | ||
</Flex> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,38 @@ | ||
import { queryGetJobs } from '@/lib/db/queries' | ||
import { type GetJobsFilter, queryGetJobs } from '@/lib/db/queries' | ||
import { JobCard } from './job-card' | ||
|
||
import type { PageSearchParams } from '@/app/types' | ||
import { Flex, Reset } from '@radix-ui/themes' | ||
import { FilterPanel } from './filter-panel' | ||
import { Pagination } from './pagination' | ||
|
||
export const JobList = async () => { | ||
const jobs = await queryGetJobs() | ||
type JobListProps = { | ||
searchParams: PageSearchParams<GetJobsFilter> | ||
} | ||
|
||
export const JobList = async ({ searchParams }: JobListProps) => { | ||
// TODO: error handling | ||
const result = await queryGetJobs( | ||
searchParams.filter ? [searchParams.filter].flat() : ['new'], | ||
searchParams.page ? Number(searchParams.page) : 1, | ||
) | ||
|
||
return ( | ||
<Flex asChild direction="column" gap="3"> | ||
<Reset> | ||
{/* biome-ignore lint/a11y/noRedundantRoles: safari 👀 */} | ||
<ul role="list"> | ||
{jobs.map(job => ( | ||
<li key={job.id}> | ||
<JobCard job={job} /> | ||
</li> | ||
))} | ||
</ul> | ||
</Reset> | ||
<Flex direction="column" gap="3"> | ||
<FilterPanel /> | ||
<Flex asChild direction="column" gap="3"> | ||
<Reset> | ||
{/* biome-ignore lint/a11y/noRedundantRoles: safari 👀 */} | ||
<ul role="list"> | ||
{result.data.map(job => ( | ||
<li key={job.id}> | ||
<JobCard job={job} /> | ||
</li> | ||
))} | ||
</ul> | ||
</Reset> | ||
</Flex> | ||
<Pagination total={result.total} /> | ||
</Flex> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
'use client' | ||
import { TriangleLeftIcon, TriangleRightIcon } from '@radix-ui/react-icons' | ||
import { Flex, IconButton } from '@radix-ui/themes' | ||
import { usePathname, useRouter, useSearchParams } from 'next/navigation' | ||
import { useCallback } from 'react' | ||
|
||
type PaginationProps = { | ||
total: number | ||
} | ||
|
||
export const Pagination = ({ total }: PaginationProps) => { | ||
const router = useRouter() | ||
const pathname = usePathname() | ||
const searchParams = useSearchParams() | ||
const page = Number(searchParams.get('page') || 1) | ||
const isLastPage = total <= page * 10 | ||
|
||
const createSearchParams = useCallback( | ||
(page: number) => { | ||
const newSearchParams = new URLSearchParams(searchParams) | ||
|
||
newSearchParams.set('page', String(page)) | ||
|
||
return newSearchParams.toString() | ||
}, | ||
[searchParams], | ||
) | ||
|
||
const clickHandler = (page: number) => { | ||
router.push(`${pathname}?${createSearchParams(page)}`) | ||
} | ||
|
||
return ( | ||
<Flex gap="3" justify="center"> | ||
<IconButton | ||
onClick={() => clickHandler(page - 1)} | ||
disabled={page === 1} | ||
variant="surface" | ||
> | ||
<TriangleLeftIcon /> | ||
</IconButton> | ||
<IconButton | ||
onClick={() => clickHandler(page + 1)} | ||
disabled={isLastPage} | ||
variant="surface" | ||
> | ||
<TriangleRightIcon /> | ||
</IconButton> | ||
</Flex> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export type PageSearchParams<T extends string = string> = { | ||
[key: string]: T | T[] | undefined | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters