1
- import { Link , useParams } from 'react-router-dom' ;
1
+ import { FormEvent , useState } from 'react' ;
2
+ import { Link } from 'react-router-dom' ;
2
3
import { PlaceholdersAndVanishInput } from './ui/input-component' ;
4
+ import { topics as topicsData } from '../utils/lists' ;
3
5
4
6
type Props = {
5
7
isDark : boolean ;
6
8
handleDarkToggle : ( ) => void ;
7
9
} ;
8
10
9
11
const Navbar = ( { isDark, handleDarkToggle } : Props ) => {
10
- const placeholders = [
11
- 'Which Type to Use' ,
12
- 'Function Declaration Syntax' ,
13
- 'Named Returns' ,
14
- 'Nested Structs' ,
15
- 'Type Assertion' ,
16
- 'Formatting Strings' ,
17
- 'Pointers' ,
18
- ] ;
12
+ const [ searchTerm , setSearchTerm ] = useState ( '' ) ;
13
+ const [ searchResults , setSearchResults ] = useState <
14
+ { category : string ; topic : string } [ ]
15
+ > ( [ ] ) ;
16
+ const [ displayedResults , setDisplayedResults ] = useState <
17
+ { category : string ; topic : string } [ ]
18
+ > ( [ ] ) ;
19
+ const [ maximumSearchResult , setMaximumSearchResult ] = useState ( 8 ) ;
19
20
20
21
const handleChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
21
- console . log ( e . target . value ) ;
22
+ setSearchTerm ( e . target . value ) ;
23
+ ! searchTerm && setMaximumSearchResult ( 8 ) ;
24
+
25
+ const searchQuery = e . target . value . toLowerCase ( ) ;
26
+
27
+ // Perform search
28
+ const filteredTopics : { category : string ; topic : string } [ ] = [ ] ;
29
+
30
+ for ( const category in topicsData ) {
31
+ // @ts -expect-error
32
+ const topics = topicsData [ category ] ;
33
+ for ( const topic of topics ) {
34
+ if ( topic . toLowerCase ( ) . includes ( searchQuery ) ) {
35
+ filteredTopics . push ( { category, topic } ) ;
36
+ }
37
+ }
38
+ }
39
+
40
+ setSearchResults ( filteredTopics ) ;
41
+ setDisplayedResults ( filteredTopics . slice ( 0 , maximumSearchResult ) ) ; // Limit results to specified max search result
22
42
} ;
23
- const onSubmit = ( e : React . FormEvent < HTMLFormElement > ) => {
43
+ const onLinkClick = ( e : FormEvent ) => {
24
44
e . preventDefault ( ) ;
25
- console . log ( 'submitted' ) ;
45
+ setSearchTerm ( '' ) ;
46
+ setSearchResults ( [ ] ) ;
47
+ setMaximumSearchResult ( 8 ) ;
48
+ } ;
49
+ const handleShowMore = ( ) => {
50
+ setMaximumSearchResult ( maximumSearchResult + 5 ) ;
51
+ setDisplayedResults ( searchResults . slice ( 0 , maximumSearchResult ) ) ;
26
52
} ;
27
53
28
54
return (
@@ -54,19 +80,57 @@ const Navbar = ({ isDark, handleDarkToggle }: Props) => {
54
80
< label className = 'switch' >
55
81
< input
56
82
type = 'checkbox'
57
- onClick = { handleDarkToggle }
83
+ checked = { isDark }
84
+ onChange = { handleDarkToggle }
58
85
/>
59
86
< span className = 'slider' > </ span >
60
87
</ label >
61
88
</ div >
62
89
</ div >
63
90
</ div >
64
91
65
- < PlaceholdersAndVanishInput
66
- placeholders = { placeholders }
67
- onChange = { handleChange }
68
- onSubmit = { onSubmit }
69
- />
92
+ < div className = 'w-full relative' >
93
+ < PlaceholdersAndVanishInput
94
+ placeholders = { placeholders }
95
+ onChange = { handleChange }
96
+ onSubmit = { onLinkClick }
97
+ />
98
+ { searchTerm ? (
99
+ < div className = 'text-white absolute left-1/2 -translate-x-1/2 mt-3 py-5 px-8 tracking-wide leading-loose w-11/12 lg:w-[70%] rounded-md z-40 bg-zinc-800' >
100
+ { displayedResults . length > 0 ? (
101
+ < div >
102
+ < ul >
103
+ { displayedResults . map ( ( result ) => (
104
+ < li
105
+ key = { `${ result . category } -${ result . topic } ` }
106
+ onClick = { ( e : FormEvent ) => onLinkClick ( e ) }
107
+ >
108
+ < Link
109
+ to = { `/${ result . category . replaceAll ( '_' , '-' ) } /${
110
+ result . topic
111
+ } `}
112
+ >
113
+ < span > { result . category . replaceAll ( '_' , '-' ) } </ span > /
114
+ < span > { result . topic . replaceAll ( '-' , ' ' ) } </ span >
115
+ </ Link >
116
+ </ li >
117
+ ) ) }
118
+ </ ul >
119
+ { searchResults . length > 9 ? (
120
+ < button
121
+ className = 'mt-2 text-blue-400 underline'
122
+ onClick = { handleShowMore }
123
+ >
124
+ Show more
125
+ </ button >
126
+ ) : null }
127
+ </ div >
128
+ ) : (
129
+ < p > No matching topics found.</ p >
130
+ ) }
131
+ </ div >
132
+ ) : null }
133
+ </ div >
70
134
71
135
< div className = 'gap-8 hidden md:flex' >
72
136
< div >
@@ -89,7 +153,7 @@ const Navbar = ({ isDark, handleDarkToggle }: Props) => {
89
153
< input
90
154
type = 'checkbox'
91
155
checked = { isDark }
92
- onClick = { handleDarkToggle }
156
+ onChange = { handleDarkToggle }
93
157
/>
94
158
< span className = 'slider' > </ span >
95
159
</ label >
@@ -100,4 +164,14 @@ const Navbar = ({ isDark, handleDarkToggle }: Props) => {
100
164
) ;
101
165
} ;
102
166
167
+ export const placeholders = [
168
+ 'Which Type to Use' ,
169
+ 'Function Declaration Syntax' ,
170
+ 'Nested Structs' ,
171
+ 'Type Assertion' ,
172
+ 'Formatting Strings' ,
173
+ 'Pointers' ,
174
+ 'Mutexes' ,
175
+ ] ;
176
+
103
177
export default Navbar ;
0 commit comments