@@ -2,7 +2,8 @@ import Button from '@/components/Button/Button';
22import { Input } from '@/components/ui/input' ;
33import { Label } from '@/components/ui/label' ;
44import useKnowledgeBaseSearchInterface from '@/pages/automation/knowledge-base/components/hooks/useKnowledgeBaseSearchInterface' ;
5- import { Search } from 'lucide-react' ;
5+ import { SearchIcon } from 'lucide-react' ;
6+ import { useMemo } from 'react' ;
67
78interface KnowledgeBaseSearchInterfaceProps {
89 knowledgeBaseId : string ;
@@ -22,39 +23,111 @@ const KnowledgeBaseSearchInterface = ({knowledgeBaseId}: KnowledgeBaseSearchInte
2223 setQuery,
2324 } = useKnowledgeBaseSearchInterface ( { knowledgeBaseId} ) ;
2425
25- return (
26- < div className = "space-y-4" >
27- < form className = "space-y-4 rounded-lg border border-gray-200 bg-white p-4" onSubmit = { handleSearch } >
28- < div className = "space-y-2" >
29- < Label htmlFor = "query" > Search Query</ Label >
26+ const resultsWithChunkIndex = useMemo ( ( ) => {
27+ const documentChunkCounts : Record < string , number > = { } ;
3028
31- < div className = "flex space-x-2" >
32- < Input
33- id = "query"
34- onChange = { ( e ) => setQuery ( e . target . value ) }
35- placeholder = "Enter your search query..."
36- value = { query }
37- />
29+ return results . map ( ( result , index ) => {
30+ const documentName = String ( ( result . metadata as Record < string , unknown > ) ?. file_name ?? 'Unknown' ) ;
3831
39- < Button disabled = { isLoading || ! canSearch } type = "submit" >
40- < Search className = "mr-2 size-4" />
32+ documentChunkCounts [ documentName ] = ( documentChunkCounts [ documentName ] ?? 0 ) + 1 ;
4133
42- { isLoading ? 'Searching...' : 'Search' }
43- </ Button >
44- </ div >
34+ return {
35+ chunkIndex : documentChunkCounts [ documentName ] ,
36+ documentName,
37+ index,
38+ result,
39+ } ;
40+ } ) ;
41+ } , [ results ] ) ;
42+
43+ const renderSearchResults = ( ) => {
44+ if ( results . length === 0 ) {
45+ return (
46+ < div className = "rounded-lg border border-gray-200 bg-gray-50 p-8 text-center" >
47+ < p className = "text-gray-500" > No results found for your query.</ p >
4548 </ div >
49+ ) ;
50+ }
4651
47- < div className = "space-y-2" >
48- < Label htmlFor = "filters" > Metadata Filters (JSON, optional)</ Label >
52+ return resultsWithChunkIndex . map ( ( { chunkIndex, documentName, index, result} ) => (
53+ < div
54+ className = "rounded-lg border border-gray-200 bg-white p-4 transition-shadow hover:shadow-md"
55+ key = { result . id }
56+ >
57+ < div className = "mb-2 flex items-center justify-between" >
58+ < div className = "flex items-center space-x-2 text-sm text-gray-500" >
59+ < span className = "font-medium" > Result { index + 1 } </ span >
4960
50- < Input
51- id = "filters"
52- onChange = { ( e ) => setMetadataFilters ( e . target . value ) }
53- placeholder = '{"category": "documentation"}'
54- value = { metadataFilters }
55- />
61+ < span > •</ span >
62+
63+ < span className = "font-medium" > { documentName } </ span >
64+
65+ < span > •</ span >
66+
67+ < span > Chunk { chunkIndex } </ span >
68+
69+ { result . score != null && (
70+ < >
71+ < span > •</ span >
72+
73+ < span className = "font-medium text-blue-600" >
74+ Score: { ( result . score * 100 ) . toFixed ( 1 ) } %
75+ </ span >
76+ </ >
77+ ) }
78+ </ div >
5679 </ div >
5780
81+ < p className = "text-sm leading-relaxed text-gray-700" > { result . content } </ p >
82+
83+ { result . metadata && (
84+ < div className = "mt-3 rounded-md bg-gray-50 p-2 text-xs text-gray-600" >
85+ < span className = "font-medium" > Metadata: </ span >
86+
87+ < pre className = "mt-1 overflow-x-auto" >
88+ < code > { JSON . stringify ( result . metadata , null , 2 ) } </ code >
89+ </ pre >
90+ </ div >
91+ ) }
92+ </ div >
93+ ) ) ;
94+ } ;
95+
96+ return (
97+ < div className = "space-y-4" >
98+ < form className = "space-y-4 rounded-lg border border-gray-200 bg-white p-4" onSubmit = { handleSearch } >
99+ < fieldset className = "space-y-4 border-0" >
100+ < div className = "space-y-2" >
101+ < Label htmlFor = "query" > Search Query</ Label >
102+
103+ < div className = "flex space-x-2" >
104+ < Input
105+ id = "query"
106+ onChange = { ( event ) => setQuery ( event . target . value ) }
107+ placeholder = "Enter your search query..."
108+ value = { query }
109+ />
110+
111+ < Button disabled = { isLoading || ! canSearch } type = "submit" >
112+ < SearchIcon className = "mr-2 size-4" />
113+
114+ { isLoading ? 'Searching...' : 'Search' }
115+ </ Button >
116+ </ div >
117+ </ div >
118+
119+ < div className = "space-y-2" >
120+ < Label htmlFor = "filters" > Metadata Filters (JSON, optional)</ Label >
121+
122+ < Input
123+ id = "filters"
124+ onChange = { ( event ) => setMetadataFilters ( event . target . value ) }
125+ placeholder = '{"category": "documentation"}'
126+ value = { metadataFilters }
127+ />
128+ </ div >
129+ </ fieldset >
130+
58131 { searchQuery && (
59132 < div className = "flex items-center justify-between border-t border-gray-200 pt-4" >
60133 < p className = "text-sm text-gray-500" >
@@ -68,71 +141,7 @@ const KnowledgeBaseSearchInterface = ({knowledgeBaseId}: KnowledgeBaseSearchInte
68141 ) }
69142 </ form >
70143
71- { searchQuery && (
72- < div className = "space-y-2" >
73- { results . length === 0 ? (
74- < div className = "rounded-lg border border-gray-200 bg-gray-50 p-8 text-center" >
75- < p className = "text-gray-500" > No results found for your query.</ p >
76- </ div >
77- ) : (
78- ( ( ) => {
79- const documentChunkCounts : Record < string , number > = { } ;
80-
81- return results . map ( ( result , index ) => {
82- const documentName = String (
83- ( result . metadata as Record < string , unknown > ) ?. file_name ?? 'Unknown'
84- ) ;
85-
86- documentChunkCounts [ documentName ] = ( documentChunkCounts [ documentName ] ?? 0 ) + 1 ;
87- const chunkIndex = documentChunkCounts [ documentName ] ;
88-
89- return (
90- < div
91- className = "rounded-lg border border-gray-200 bg-white p-4 transition-shadow hover:shadow-md"
92- key = { result . id }
93- >
94- < div className = "mb-2 flex items-center justify-between" >
95- < div className = "flex items-center space-x-2 text-sm text-gray-500" >
96- < span className = "font-medium" > Result { index + 1 } </ span >
97-
98- < span > •</ span >
99-
100- < span className = "font-medium" > { documentName } </ span >
101-
102- < span > •</ span >
103-
104- < span > Chunk { chunkIndex } </ span >
105-
106- { result . score != null && (
107- < >
108- < span > •</ span >
109-
110- < span className = "font-medium text-blue-600" >
111- Score: { ( result . score * 100 ) . toFixed ( 1 ) } %
112- </ span >
113- </ >
114- ) }
115- </ div >
116- </ div >
117-
118- < p className = "text-sm leading-relaxed text-gray-700" > { result . content } </ p >
119-
120- { result . metadata && (
121- < div className = "mt-3 rounded-md bg-gray-50 p-2 text-xs text-gray-600" >
122- < span className = "font-medium" > Metadata: </ span >
123-
124- < pre className = "mt-1 overflow-x-auto" >
125- < code > { JSON . stringify ( result . metadata , null , 2 ) } </ code >
126- </ pre >
127- </ div >
128- ) }
129- </ div >
130- ) ;
131- } ) ;
132- } ) ( )
133- ) }
134- </ div >
135- ) }
144+ { searchQuery && < div className = "space-y-2" > { renderSearchResults ( ) } </ div > }
136145 </ div >
137146 ) ;
138147} ;
0 commit comments