diff --git a/src/app/(public)/repos/_components/pagination.tsx b/src/app/(public)/repos/_components/pagination.tsx index 5d105a0..07f3faa 100644 --- a/src/app/(public)/repos/_components/pagination.tsx +++ b/src/app/(public)/repos/_components/pagination.tsx @@ -2,33 +2,30 @@ import { Button } from '@/app/(public)/_components/button'; import { ArrowLeft, ArrowRight, Loader2 } from 'lucide-react'; -import { useRouter } from 'next/navigation'; import { useTransition } from 'react'; -import type { SearchParams } from '@/types'; +import { useQueryState } from 'nuqs'; const MAX_PER_PAGE = 21; interface PaginationProps { page: number; totalCount: number; - searchParams: SearchParams; } export function Pagination({ page, - totalCount, - searchParams + totalCount }: PaginationProps) { - const router = useRouter(); + const [, setPageParam] = useQueryState('p', { + defaultValue: '1', + parse: (value: string) => value, + serialize: (value: string) => value + }); const [isPending, startTransition] = useTransition(); function changePage(delta: number) { - const params = new URLSearchParams( - Object.entries(searchParams).map(([k, v]) => [k, String(v)]) - ); - params.set('p', String(page + delta)); - + const newPage = page + delta; startTransition(() => { - router.push(`?${params.toString()}`); + void setPageParam(String(newPage)); }); } diff --git a/src/app/(public)/repos/_components/sorter.tsx b/src/app/(public)/repos/_components/sorter.tsx index 545c35c..31f4718 100644 --- a/src/app/(public)/repos/_components/sorter.tsx +++ b/src/app/(public)/repos/_components/sorter.tsx @@ -4,8 +4,9 @@ import { Button } from '@/app/(public)/_components/button'; import { ArrowUpAZ, Code } from 'lucide-react'; import Link from 'next/link'; import languages from '@/assets/languages.json'; -import { usePathname, useSearchParams } from 'next/navigation'; +import { usePathname } from 'next/navigation'; import { sortByName } from '@/lib/utils'; +import { useQueryStates, useQueryState } from 'nuqs'; const { mainLanguages } = languages; @@ -23,88 +24,74 @@ enum SortTypes { type Pathname = '/repos' | `/repos/${string}`; export function Sorter() { - const searchParams = useSearchParams(); const pathname = usePathname() as Pathname; + const [sortField] = useQueryState('s', { defaultValue: '' }); + const [sortOrder] = useQueryState('o', { defaultValue: 'desc' }); + const [languages_] = useQueryState('l', { parse: (value: string) => value.split(',').filter(Boolean), serialize: (value: string[]) => value.join(',') }); const navigationItems = [ { name: 'Best match', - onSelect(sp: URLSearchParams) { - sp.delete('o'); - sp.delete('s'); - return sp; + onSelect(): { s: string | null; o: string | null } { + return { s: null, o: null }; } }, { name: 'Most stars', - onSelect(sp: URLSearchParams) { - sp.set('s', 'stars'); - sp.set('o', 'desc'); - return sp; + onSelect() { + return { s: 'stars', o: 'desc' }; } }, { name: 'Fewest stars', - onSelect(sp: URLSearchParams) { - sp.set('s', 'stars'); - sp.set('o', 'asc'); - return sp; + onSelect() { + return { s: 'stars', o: 'asc' }; } }, { name: 'Most forks', - onSelect(sp: URLSearchParams) { - sp.set('s', 'forks'); - sp.set('o', 'desc'); - return sp; + onSelect() { + return { s: 'forks', o: 'desc' }; } }, { name: 'Fewest forks', - onSelect(sp: URLSearchParams) { - sp.set('s', 'forks'); - sp.set('o', 'asc'); - return sp; + onSelect() { + return { s: 'forks', o: 'asc' }; } }, { name: 'Most help wanted issues', - onSelect(sp: URLSearchParams) { - sp.set('s', 'help-wanted-issues'); - sp.set('o', 'desc'); - return sp; + onSelect() { + return { s: 'help-wanted-issues', o: 'desc' }; } }, { name: 'Recently updated', - onSelect(sp: URLSearchParams) { - sp.set('s', 'updated'); - sp.set('o', 'desc'); - return sp; + onSelect() { + return { s: 'updated', o: 'desc' }; } }, { name: 'Least recently updated', - onSelect(sp: URLSearchParams) { - sp.set('s', 'updated'); - sp.set('o', 'asc'); - return sp; + onSelect() { + return { s: 'updated', o: 'asc' }; } } ]; function selectedSort(): SortTypes { - if (searchParams.get('o') === 'asc') { - if (searchParams.get('s') === 'stars') return SortTypes.FewestStars; - if (searchParams.get('s') === 'forks') return SortTypes.FewestForks; - if (searchParams.get('s') === 'updated') + if (sortOrder === 'asc') { + if (sortField === 'stars') return SortTypes.FewestStars; + if (sortField === 'forks') return SortTypes.FewestForks; + if (sortField === 'updated') return SortTypes.LeastRecentlyUpdated; return SortTypes.BestMatch; - } else if (searchParams.get('o') === 'desc') { - if (searchParams.get('s') === 'stars') return SortTypes.MostStars; - if (searchParams.get('s') === 'forks') return SortTypes.MostForks; - if (searchParams.get('s') === 'updated') return SortTypes.RecentlyUpdated; - if (searchParams.get('s') === 'help-wanted-issues') + } else if (sortOrder === 'desc') { + if (sortField === 'stars') return SortTypes.MostStars; + if (sortField === 'forks') return SortTypes.MostForks; + if (sortField === 'updated') return SortTypes.RecentlyUpdated; + if (sortField === 'help-wanted-issues') return SortTypes.MostHelpWantedIssues; return SortTypes.BestMatch; } else { @@ -127,12 +114,17 @@ export function Sorter() {