11'use client' ;
22
33import { useRouter } from 'next/navigation' ;
4+ import { useMemo , useState } from 'react' ;
45
56import { Search } from 'lucide-react' ;
6- import { LanguageButton } from './language-button' ;
77import { Button } from './button' ;
8- import Link from 'next/link' ;
98
109import { sortByName } from '@/lib/utils' ;
1110import languages from '@/assets/languages.json' ;
@@ -17,11 +16,34 @@ const { main: mainLanguages, others: otherLanguages } = languages;
1716export function Hero ( ) {
1817 const router = useRouter ( ) ;
1918
19+ // Track selected languages as a string array
20+ const [ selected , setSelected ] = useState < string [ ] > ( [ ] ) ;
21+
22+ const toggleLanguage = ( language : string ) => {
23+ setSelected ( prev =>
24+ prev . includes ( language ) ? prev . filter ( l => l !== language ) : [ ...prev , language ]
25+ ) ;
26+ } ;
27+
28+ const sortedOthers = useMemo ( ( ) => [ ...otherLanguages ] . sort ( sortByName ) , [ ] ) ;
29+
2030 function handleSearch ( e : React . FormEvent ) {
31+ e . preventDefault ( ) ;
2132 const formData = new FormData ( e . target as HTMLFormElement ) ;
22- const lang = formData . get ( 'search' ) as string ;
23- if ( lang . trim ( ) === '' ) return ;
24- router . push ( `/repos/${ lang } ` ) ;
33+ let chosen = selected ;
34+
35+ // Fallback: if no checkbox selected, use the single input value
36+ if ( chosen . length === 0 ) {
37+ const typed = String ( formData . get ( 'search' ) || '' ) . trim ( ) ;
38+ if ( typed ) {
39+ chosen = [ typed ] ;
40+ }
41+ }
42+
43+ if ( chosen . length === 0 ) return ; // nothing to search
44+
45+ const csv = chosen . map ( l => l . toLowerCase ( ) ) . join ( ',' ) ;
46+ router . push ( `/repos?l=${ encodeURIComponent ( csv ) } ` ) ;
2547 }
2648
2749 return (
@@ -39,7 +61,7 @@ export function Hero() {
3961 < div className = "relative flex w-full" >
4062 < input
4163 type = "text"
42- placeholder = "Search for your language"
64+ placeholder = "Type a language (optional) "
4365 className = "w-full max-w-xs bg-transparent rounded-tr-none rounded-br-none input input-bordered text-hacktoberfest-light border-hacktoberfest-light
4466 focus:border-hacktoberfest-light focus:!outline-none focus-visible:!outline-none placeholder:text-hacktoberfest-light text-sm sm:text-base"
4567 name = "search"
@@ -54,33 +76,56 @@ export function Hero() {
5476 </ div >
5577 </ form >
5678 < p className = "font-medium uppercase text-hacktoberfest-light text-sm sm:text-base" >
57- Or select the programming language you would like to find
79+ Or select the programming languages you would like to find
5880 repositories for.
5981 </ p >
82+
6083 < div className = "flex flex-wrap gap-4 sm:gap-6 items-center justify-center" >
61- { mainLanguages . map ( language => (
62- < LanguageButton key = { language } language = { language } />
63- ) ) }
84+ { mainLanguages . map ( language => {
85+ const id = `lang-${ language } ` ;
86+ const checked = selected . includes ( language ) ;
87+ return (
88+ < label key = { language } htmlFor = { id } className = "flex items-center gap-2 cursor-pointer select-none" >
89+ < input
90+ id = { id }
91+ type = "checkbox"
92+ className = "checkbox checkbox-primary"
93+ checked = { checked }
94+ onChange = { ( ) => toggleLanguage ( language ) }
95+ />
96+ < span className = "text-hacktoberfest-light text-sm sm:text-base" > { language } </ span >
97+ </ label >
98+ ) ;
99+ } ) }
64100 </ div >
101+
65102 < div className = "dropdown dropdown-top" >
66103 < Button tabIndex = { 0 } className = "umami--click--otherlangs-button text-sm sm:text-base" >
67104 Other languages
68105 </ Button >
69106
70107 < ul
71108 tabIndex = { 0 }
72- className = "h-64 p-2 overflow-y-auto shadow-lg menu dropdown-content bg-white/95 backdrop-blur-sm rounded-xl w-60 border border-gray-200/50 z-[9999]"
109+ className = "h-64 p-2 overflow-y-auto shadow-lg menu dropdown-content bg-white/95 backdrop-blur-sm rounded-xl w-72 border border-gray-200/50 z-[9999]"
73110 >
74- { otherLanguages . sort ( sortByName ) . map ( language => (
75- < li key = { language } >
76- < Link
77- href = { `/repos/${ language . toLowerCase ( ) } ` }
78- className = "text-gray-700 hover:text-white hover:bg-hacktoberfest-blue rounded-lg transition-colors duration-200 px-3 py-2 text-sm"
79- >
80- { language }
81- </ Link >
82- </ li >
83- ) ) }
111+ { sortedOthers . map ( language => {
112+ const id = `other-${ language } ` ;
113+ const checked = selected . includes ( language ) ;
114+ return (
115+ < li key = { language } className = "px-1" >
116+ < label htmlFor = { id } className = "flex items-center gap-3 rounded-lg px-3 py-2 hover:bg-hacktoberfest-blue/80 hover:text-white cursor-pointer" >
117+ < input
118+ id = { id }
119+ type = "checkbox"
120+ className = "checkbox checkbox-primary"
121+ checked = { checked }
122+ onChange = { ( ) => toggleLanguage ( language ) }
123+ />
124+ < span className = "text-sm text-gray-800" > { language } </ span >
125+ </ label >
126+ </ li >
127+ ) ;
128+ } ) }
84129 </ ul >
85130 </ div >
86131 </ div >
0 commit comments