@@ -4,8 +4,9 @@ import { Button } from '@/app/(public)/_components/button';
44import { ArrowUpAZ , Code } from 'lucide-react' ;
55import Link from 'next/link' ;
66import languages from '@/assets/languages.json' ;
7- import { usePathname , useSearchParams } from 'next/navigation' ;
7+ import { usePathname } from 'next/navigation' ;
88import { sortByName } from '@/lib/utils' ;
9+ import { useQueryStates , useQueryState } from 'nuqs' ;
910
1011const { mainLanguages } = languages ;
1112
@@ -23,88 +24,74 @@ enum SortTypes {
2324type Pathname = '/repos' | `/repos/${string } `;
2425
2526export function Sorter ( ) {
26- const searchParams = useSearchParams ( ) ;
2727 const pathname = usePathname ( ) as Pathname ;
28+ const [ sortField ] = useQueryState ( 's' , { defaultValue : '' } ) ;
29+ const [ sortOrder ] = useQueryState ( 'o' , { defaultValue : 'desc' } ) ;
30+ const [ languages_ ] = useQueryState ( 'l' , { parse : ( value : string ) => value . split ( ',' ) . filter ( Boolean ) , serialize : ( value : string [ ] ) => value . join ( ',' ) } ) ;
2831
2932 const navigationItems = [
3033 {
3134 name : 'Best match' ,
32- onSelect ( sp : URLSearchParams ) {
33- sp . delete ( 'o' ) ;
34- sp . delete ( 's' ) ;
35- return sp ;
35+ onSelect ( ) : { s : string | null ; o : string | null } {
36+ return { s : null , o : null } ;
3637 }
3738 } ,
3839 {
3940 name : 'Most stars' ,
40- onSelect ( sp : URLSearchParams ) {
41- sp . set ( 's' , 'stars' ) ;
42- sp . set ( 'o' , 'desc' ) ;
43- return sp ;
41+ onSelect ( ) {
42+ return { s : 'stars' , o : 'desc' } ;
4443 }
4544 } ,
4645 {
4746 name : 'Fewest stars' ,
48- onSelect ( sp : URLSearchParams ) {
49- sp . set ( 's' , 'stars' ) ;
50- sp . set ( 'o' , 'asc' ) ;
51- return sp ;
47+ onSelect ( ) {
48+ return { s : 'stars' , o : 'asc' } ;
5249 }
5350 } ,
5451 {
5552 name : 'Most forks' ,
56- onSelect ( sp : URLSearchParams ) {
57- sp . set ( 's' , 'forks' ) ;
58- sp . set ( 'o' , 'desc' ) ;
59- return sp ;
53+ onSelect ( ) {
54+ return { s : 'forks' , o : 'desc' } ;
6055 }
6156 } ,
6257 {
6358 name : 'Fewest forks' ,
64- onSelect ( sp : URLSearchParams ) {
65- sp . set ( 's' , 'forks' ) ;
66- sp . set ( 'o' , 'asc' ) ;
67- return sp ;
59+ onSelect ( ) {
60+ return { s : 'forks' , o : 'asc' } ;
6861 }
6962 } ,
7063 {
7164 name : 'Most help wanted issues' ,
72- onSelect ( sp : URLSearchParams ) {
73- sp . set ( 's' , 'help-wanted-issues' ) ;
74- sp . set ( 'o' , 'desc' ) ;
75- return sp ;
65+ onSelect ( ) {
66+ return { s : 'help-wanted-issues' , o : 'desc' } ;
7667 }
7768 } ,
7869 {
7970 name : 'Recently updated' ,
80- onSelect ( sp : URLSearchParams ) {
81- sp . set ( 's' , 'updated' ) ;
82- sp . set ( 'o' , 'desc' ) ;
83- return sp ;
71+ onSelect ( ) {
72+ return { s : 'updated' , o : 'desc' } ;
8473 }
8574 } ,
8675 {
8776 name : 'Least recently updated' ,
88- onSelect ( sp : URLSearchParams ) {
89- sp . set ( 's' , 'updated' ) ;
90- sp . set ( 'o' , 'asc' ) ;
91- return sp ;
77+ onSelect ( ) {
78+ return { s : 'updated' , o : 'asc' } ;
9279 }
9380 }
9481 ] ;
9582
9683 function selectedSort ( ) : SortTypes {
97- if ( searchParams . get ( 'o' ) === 'asc' ) {
98- if ( searchParams . get ( 's' ) === 'stars' ) return SortTypes . FewestStars ;
99- if ( searchParams . get ( 's' ) === 'forks' ) return SortTypes . FewestForks ;
100- if ( searchParams . get ( 's' ) === 'updated' )
84+ if ( sortOrder === 'asc' ) {
85+ if ( sortField === 'stars' ) return SortTypes . FewestStars ;
86+ if ( sortField === 'forks' ) return SortTypes . FewestForks ;
87+ if ( sortField === 'updated' )
10188 return SortTypes . LeastRecentlyUpdated ;
10289 return SortTypes . BestMatch ;
103- } else if ( searchParams . get ( 'o' ) === 'desc' ) {
104- if ( searchParams . get ( 's' ) === 'stars' ) return SortTypes . MostStars ;
105- if ( searchParams . get ( 's' ) === 'forks' ) return SortTypes . MostForks ;
106- if ( searchParams . get ( 's' ) === 'updated' ) return SortTypes . RecentlyUpdated ;
107- if ( searchParams . get ( 's' ) === 'help-wanted-issues' )
90+ } else if ( sortOrder === 'desc' ) {
91+ if ( sortField === 'stars' ) return SortTypes . MostStars ;
92+ if ( sortField === 'forks' ) return SortTypes . MostForks ;
93+ if ( sortField === 'updated' ) return SortTypes . RecentlyUpdated ;
94+ if ( sortField === 'help-wanted-issues' )
10895 return SortTypes . MostHelpWantedIssues ;
10996 return SortTypes . BestMatch ;
11097 } else {
@@ -127,12 +114,17 @@ export function Sorter() {
127114 < div className = "z-[9999] h-64 p-2 overflow-y-auto shadow-lg dropdown-content hidden group-hover:block bg-white/95 backdrop-blur-sm rounded-xl w-60 border border-gray-200/50" >
128115 < ul tabIndex = { 0 } className = "menu menu-vertical" >
129116 { mainLanguages . sort ( sortByName ) . map ( language => {
130- const sp = new URLSearchParams ( searchParams ) ;
131- sp . delete ( 'p' ) ;
117+ const languageParams = `l=${ language . toLowerCase ( ) } ` ;
118+ const currentParams = new URLSearchParams ( ) ;
119+ if ( sortField ) currentParams . set ( 's' , sortField ) ;
120+ if ( sortOrder ) currentParams . set ( 'o' , sortOrder ) ;
121+ const queryString = currentParams . toString ( ) ;
122+ const fullQuery = queryString ? `${ languageParams } &${ queryString } ` : languageParams ;
123+
132124 return (
133125 < li key = { language } onClick = { handleClick } >
134126 < Link
135- href = { `/repos/${ language . toLowerCase ( ) } ?${ sp . toString ( ) } ` }
127+ href = { `/repos/${ language . toLowerCase ( ) } ?${ fullQuery } ` }
136128 className = "text-gray-700 hover:text-white hover:bg-hacktoberfest-light-blue rounded-lg transition-colors duration-200 px-3 py-2"
137129 >
138130 { language }
@@ -151,16 +143,19 @@ export function Sorter() {
151143 < div className = "z-[9999] h-64 p-2 overflow-y-auto shadow-lg dropdown-content hidden group-hover:block -ml-16 bg-white/95 backdrop-blur-sm rounded-xl w-60 border border-gray-200/50" >
152144 < ul tabIndex = { 0 } className = "menu menu-vertical" >
153145 { navigationItems . map ( ( item , index ) => {
154- const sp = item . onSelect ( new URLSearchParams ( searchParams ) ) ;
155- sp . delete ( 'p' ) ;
156- if ( item . name === SortTypes . BestMatch ) {
157- sp . delete ( 'o' ) ;
158- sp . delete ( 's' ) ;
146+ const { s, o } = item . onSelect ( ) ;
147+ const currentParams = new URLSearchParams ( ) ;
148+ if ( s ) currentParams . set ( 's' , s ) ;
149+ if ( o ) currentParams . set ( 'o' , o ) ;
150+ if ( languages_ && languages_ . length > 0 ) {
151+ currentParams . set ( 'l' , languages_ . join ( ',' ) ) ;
159152 }
153+ const queryString = currentParams . toString ( ) ;
154+
160155 return (
161156 < li key = { index } onClick = { handleClick } >
162157 < Link
163- href = { `${ pathname } ?${ sp . toString ( ) } ` }
158+ href = { `${ pathname } ?${ queryString } ` }
164159 className = "text-gray-700 hover:text-white hover:bg-hacktoberfest-light-blue rounded-lg transition-colors duration-200 px-3 py-2"
165160 >
166161 { item . name }
0 commit comments