@@ -3,50 +3,65 @@ import { useEffect, useState } from "react";
33import { useSearchParams } from "react-router-dom" ;
44
55function App ( ) {
6- const [ totalDocuments , setTotalDocuments ] = useState < number > ( 0 ) ;
6+ const [ totalDocuments , setTotalDocuments ] = useState ( 0 ) ;
77 const [ searchDocuments , setSearchDocuments ] = useState < TurSNSiteSearchDocument [ ] > ( [ ] ) ;
8+ const [ loading , setLoading ] = useState ( false ) ;
9+ const [ error , setError ] = useState < string | null > ( null ) ;
810 const [ searchParams ] = useSearchParams ( ) ;
9- const query = searchParams . get ( 'q' ) || '*' ;
11+ const query = searchParams . get ( "q" ) || "*" ;
12+
1013 useEffect ( ( ) => {
11- const searchService = new TurSNSiteSearchService ( import . meta. env . VITE_API_URL ) ;
12- try {
13- searchService . search ( import . meta. env . VITE_SN_SITE , {
14- q : query ,
15- rows : 10 ,
16- currentPage : 1 ,
17- localeRequest : import . meta. env . VITE_LOCALE ,
18- } ) . then ( res => {
14+ const fetchDocuments = async ( ) => {
15+ setLoading ( true ) ;
16+ setError ( null ) ;
17+ try {
18+ const searchService = new TurSNSiteSearchService ( import . meta. env . VITE_API_URL ) ;
19+ const res = await searchService . search ( import . meta. env . VITE_SN_SITE , {
20+ q : query ,
21+ rows : 10 ,
22+ currentPage : 1 ,
23+ localeRequest : import . meta. env . VITE_LOCALE ,
24+ } ) ;
1925 setSearchDocuments ( res . results ?. document || [ ] ) ;
2026 setTotalDocuments ( res . queryContext ?. count || 0 ) ;
21- } ) ;
22- } catch ( error : Error | any ) {
23- console . error ( 'Search failed:' , error . message ) ;
24- }
25- } , [ ] )
27+ } catch ( err : any ) {
28+ setError ( "Search failed: " + ( err ?. message || "Unknown error" ) ) ;
29+ } finally {
30+ setLoading ( false ) ;
31+ }
32+ } ;
33+ fetchDocuments ( ) ;
34+ } , [ query ] ) ;
2635
2736 return (
2837 < div className = "flex min-h-svh flex-col items-center justify-center" >
29- < div className = "mb-4 text-lg font-semibold" > Total Documents: { totalDocuments } </ div >
38+ < div className = "mb-4 text-lg font-semibold" >
39+ Total Documents: { totalDocuments }
40+ </ div >
41+ { loading && < div className = "mb-4 text-gray-500" > Loading...</ div > }
42+ { error && < div className = "mb-4 text-red-500" > { error } </ div > }
3043 < ul className = "w-full max-w-md divide-y divide-gray-200 rounded-md border border-gray-300 bg-white shadow" >
31- { searchDocuments && searchDocuments . map ( ( doc , index ) => (
32- < li key = { index } className = "p-4" >
44+ { searchDocuments . map ( ( doc , index ) => (
45+ < li key = { doc . fields ?. url || index } className = "p-4" >
3346 < h3
3447 className = "text-base font-medium"
35- dangerouslySetInnerHTML = { { __html : doc . fields ?. title } }
48+ dangerouslySetInnerHTML = { { __html : doc . fields ?. title || "" } }
3649 />
37-
38- < a
39- href = { doc . fields ?. url }
40- target = "_blank"
41- rel = "noopener noreferrer"
42- >
43- { doc . fields ?. url }
44- </ a >
50+ { doc . fields ?. url && (
51+ < a
52+ href = { doc . fields . url }
53+ target = "_blank"
54+ rel = "noopener noreferrer"
55+ className = "text-blue-600 underline break-all"
56+ >
57+ { doc . fields . url }
58+ </ a >
59+ ) }
4560 </ li >
4661 ) ) }
4762 </ ul >
4863 </ div >
49- )
64+ ) ;
5065}
5166
52- export default App
67+ export default App ;
0 commit comments