@@ -16,73 +16,87 @@ const SearchBar = () => {
16
16
const [ searchText , setSearchText ] = useState ( "" ) ;
17
17
const [ suggestions , setSuggestions ] = useState < string [ ] > ( [ ] ) ;
18
18
const [ error , setError ] = useState < string | null > ( null ) ;
19
+ const [ loading , setLoading ] = useState ( false ) ;
19
20
20
-
21
-
22
21
const debouncedSearch = useCallback (
23
22
debounce ( async ( text : string ) => {
24
23
if ( text . length > 1 ) {
24
+ setLoading ( true ) ;
25
25
try {
26
26
const searchResponse = await axios . get ( "/api/search" , {
27
27
params : { text } ,
28
28
} ) ;
29
-
29
+
30
30
const { res : encryptedSearchResponse } = searchResponse . data ;
31
31
const decryptedSearchResponse = cryptr . decrypt ( encryptedSearchResponse ) ;
32
32
const { subjects } = JSON . parse ( decryptedSearchResponse ) ;
33
33
const suggestionList = subjects . map ( ( subjectObj : { subject : string } ) => subjectObj . subject ) ;
34
34
setSuggestions ( suggestionList ) ;
35
+ setError ( null ) ;
35
36
} catch ( error ) {
36
37
const typedError = error as AxiosError < { message ?: string } > ;
37
38
const errorMessage = typedError . response ?. data ?. message ?? "Error fetching suggestions" ;
38
39
setError ( errorMessage ) ;
40
+ } finally {
41
+ setLoading ( false ) ;
39
42
}
40
43
} else {
41
44
setSuggestions ( [ ] ) ;
42
45
}
43
- } , 1000 ) ,
44
- [ cryptr , axios ]
46
+ } , 500 ) ,
47
+ [ cryptr ]
45
48
) ;
46
49
47
50
const handleSearchChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
48
51
const text = e . target . value ;
49
52
setSearchText ( text ) ;
53
+ if ( text . length <= 1 ) {
54
+ setSuggestions ( [ ] ) ;
55
+ }
50
56
debouncedSearch ( text ) ;
51
57
} ;
52
58
53
59
const handleSelectSuggestion = async ( suggestion : string ) => {
54
60
setSearchText ( suggestion ) ;
55
61
setSuggestions ( [ ] ) ;
56
- // console.log(encodeURI(suggestion))
57
62
router . push ( `/catalogue?subject=${ encodeURIComponent ( suggestion ) } ` ) ;
58
63
} ;
59
64
60
65
return (
61
66
< div className = "flex min-h-screen items-center justify-center bg-gray-50 flex-col" >
62
67
< form className = "w-full max-w-md" >
63
68
< div className = "relative" >
64
-
65
- < input type = "text" value = { searchText } onChange = { handleSearchChange }
66
- placeholder = "Search..." className = "w-full rounded-md border border-gray-300 px-4 py-2 pr-10 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500" />
67
-
68
- < button type = "submit" className = "absolute inset-y-0 right-0 flex items-center pr-3" >
69
+ < input
70
+ type = "text"
71
+ value = { searchText }
72
+ onChange = { handleSearchChange }
73
+ placeholder = "Search..."
74
+ className = { `w-full rounded-md border border-gray-300 px-4 py-2 pr-10 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 ${ loading ? 'opacity-50' : '' } ` }
75
+ />
76
+ < button type = "submit" className = "absolute inset-y-0 right-0 flex items-center pr-3" disabled = { loading } >
69
77
< Search className = "h-5 w-5 text-gray-400" />
70
78
</ button >
71
-
72
79
</ div >
73
- { suggestions . length > 0 && (
74
- < ul className = "absolute z-10 w-full bg-white border border-gray-300 rounded-md mt-2" >
80
+ { loading && (
81
+ < div className = "absolute z-10 w-full max-w-md bg-white border border-gray-300 rounded-md mt-2 p-2 text-center text-gray-500" >
82
+ Loading suggestions...
83
+ </ div >
84
+ ) }
85
+ { suggestions . length > 0 && ! loading && (
86
+ < ul className = "absolute w-full text-center max-w-md z-10 bg-white border border-gray-300 rounded-md mt-2" >
75
87
{ suggestions . map ( ( suggestion , index ) => (
76
-
77
- < li key = { index } onClick = { ( ) => handleSelectSuggestion ( suggestion ) } className = "cursor-pointer p-2 hover:bg-gray-100" >
88
+ < li
89
+ key = { index }
90
+ onClick = { ( ) => handleSelectSuggestion ( suggestion ) }
91
+ className = "cursor-pointer p-2 hover:bg-gray-100 truncate"
92
+ style = { { width : '100%' , overflow : 'hidden' , whiteSpace : 'nowrap' , textOverflow : 'ellipsis' } }
93
+ >
78
94
{ suggestion }
79
95
</ li >
80
-
81
96
) ) }
82
97
</ ul >
83
98
) }
84
99
</ form >
85
-
86
100
{ error && < p className = "mt-4 text-red" > { error } </ p > }
87
101
</ div >
88
102
) ;
0 commit comments