11"use client"
22
3- import React , { FC , useState } from "react" ;
3+ import React , { FC , useState , useEffect } from "react" ;
44import {
55 Sparkles ,
66 Check ,
77 Plus ,
8- AlertCircle ,
98 Edit ,
10- X ,
119 ThumbsUp ,
1210 Settings
1311} from "lucide-react" ;
1412import { API_ENDPOINTS } from '../lib/config' ;
13+ import { FaArrowLeft } from "react-icons/fa" ;
1514
1615interface AIModel {
1716 id : string ;
@@ -47,9 +46,9 @@ interface TopicRefinerProps {
4746 newTopic : string ;
4847 setNewTopic : ( topic : string ) => void ;
4948 addNewTopic : ( ) => void ;
50- removeTopic : ( topic : string ) => void ;
5149 prevStep : ( ) => void ;
5250 handleSubmit : ( ) => void ;
51+ searchTerm : string ;
5352}
5453
5554export const TopicRefiner : FC < TopicRefinerProps > = ( {
@@ -62,23 +61,32 @@ export const TopicRefiner: FC<TopicRefinerProps> = ({
6261 newTopic = "" ,
6362 setNewTopic,
6463 addNewTopic,
65- removeTopic,
6664 prevStep,
67- handleSubmit
65+ handleSubmit,
66+ searchTerm
6867} ) => {
6968 const [ showPromptModal , setShowPromptModal ] = useState ( false ) ;
69+ const [ showWelcomeModal , setShowWelcomeModal ] = useState ( true ) ;
7070 const [ customPrompt , setCustomPrompt ] = useState (
7171 "Please analyze these topics and suggest related or more specific topics that might be relevant."
7272 ) ;
7373 const [ selectedModel , setSelectedModel ] = useState ( 'gpt-4' ) ;
7474 const [ apiKey , setApiKey ] = useState ( '' ) ;
7575
76+ useEffect ( ( ) => {
77+ // Disable scroll on mount
78+ document . body . style . overflow = "hidden" ;
79+ return ( ) => {
80+ // Restore scroll on unmount
81+ document . body . style . overflow = "" ;
82+ } ;
83+ } , [ ] ) ;
84+
7685 const handleGetSuggestions = async ( ) => {
7786 if ( ! apiKey ) {
7887 alert ( 'Please enter an API key' ) ;
7988 return ;
8089 }
81-
8290 if ( selectedTopics . length === 0 ) {
8391 alert ( 'Please select at least one topic before requesting suggestions' ) ;
8492 return ;
@@ -87,48 +95,91 @@ export const TopicRefiner: FC<TopicRefinerProps> = ({
8795 try {
8896 const response = await fetch ( API_ENDPOINTS . AI_PROCESS , {
8997 method : 'POST' ,
90- headers : {
91- 'Content-Type' : 'application/json' ,
92- 'Authorization' : `Bearer ${ apiKey } `
93- } ,
98+ headers : { 'Content-Type' : 'application/json' } ,
9499 body : JSON . stringify ( {
95- model : selectedModel ,
96- prompt : customPrompt ,
97- topics : selectedTopics
100+ selectedModel,
101+ customPrompt,
102+ apiKey,
103+ searchTerm,
104+ selectedTopics
98105 } )
99106 } ) ;
100-
101- if ( ! response . ok ) {
102- throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
103- }
104-
105107 const data = await response . json ( ) ;
106-
107- if ( data . suggestions ) {
108- setLlmSuggestions ( data . suggestions ) ;
109- }
110-
111- if ( showPromptModal ) {
112- setShowPromptModal ( false ) ;
108+ if ( data . success && data . result ) {
109+ setLlmSuggestions ( data . result ) ;
110+ } else {
111+ alert ( 'Failed to get AI suggestions.' ) ;
113112 }
113+ setShowPromptModal ( false ) ;
114114 } catch ( error ) {
115- console . error ( 'Error getting suggestions:' , error ) ;
116- alert ( "Failed to get AI suggestions. Please try again." ) ;
115+ alert ( 'Failed to get AI suggestions. Please try again.' ) ;
117116 }
118117 } ;
119118
120119 return (
121- < >
122- < div className = "card shadow-sm" >
120+ < main className = "container-fluid py-4" style = { { height : '100vh' , overflowY : 'auto' } } >
121+ { /* Navigation/Header Row */ }
122+ < div className = "mx-auto" style = { { maxWidth : '90%' } } >
123+ < div className = "d-flex align-items-center justify-content-between mb-4" >
124+ { /* Left side with back button and titles */ }
125+ < div className = "d-flex align-items-center" >
126+ < button
127+ className = "btn btn-outline-secondary me-3"
128+ style = { { borderRadius : '50%' , width : '40px' , height : '40px' , padding : 0 } }
129+ onClick = { ( ) => {
130+ if ( showWelcomeModal ) {
131+ setShowWelcomeModal ( false ) ;
132+ } else {
133+ prevStep ( ) ;
134+ }
135+ } }
136+ >
137+ < FaArrowLeft />
138+ </ button >
139+ < div >
140+ < h1 className = "mb-0" > Topic-Centric Filtering</ h1 >
141+ < h2 className = "h5 text-muted mb-0 mt-1" > Refine Your Topics</ h2 >
142+ </ div >
143+ </ div >
144+ { /* Right side with step indicator */ }
145+ < div className = "d-flex align-items-center gap-4" >
146+ < div className = "d-flex align-items-center gap-2 position-relative" >
147+ < div
148+ className = { "rounded-circle d-flex align-items-center justify-content-center text-dark bg-primary text-white" }
149+ style = { { width : "32px" , height : "32px" , zIndex : 1 } }
150+ >
151+ 1
152+ </ div >
153+ < div
154+ style = { {
155+ width : "40px" ,
156+ height : "2px" ,
157+ backgroundColor : "#0d6efd" ,
158+ transition : "background-color 0.3s ease"
159+ } }
160+ />
161+ < div
162+ className = { "rounded-circle d-flex align-items-center justify-content-center text-dark bg-primary text-white" }
163+ style = { { width : "32px" , height : "32px" , zIndex : 1 } }
164+ >
165+ 2
166+ </ div >
167+ </ div >
168+ < div className = "text-muted" >
169+ Step 2 of 2
170+ </ div >
171+ </ div >
172+ </ div >
173+ </ div >
174+ < div className = "card shadow-sm mx-auto" style = { { maxWidth : '90%' } } >
123175 < div className = "card-body" >
124- { /* <h2 className="card-title mb-3">Refine Your Topics</h2> */ }
125176 < p className = "text-muted mb-4" > Use AI suggestions to refine your topics or manually add/remove topics.</ p >
126177
127178 < div className = "row g-4" >
128179 { /* LLM Suggestions */ }
129180 < div className = "col-md-6" >
130- < div className = "card h-100" >
131- < div className = "card-body" >
181+ < div className = "card h-100" style = { { minHeight : 420 } } >
182+ < div className = "card-body" style = { { minHeight : 420 , maxHeight : 420 } } >
132183 < div className = "d-flex justify-content-between align-items-center mb-4" >
133184 < h3 className = "h5 mb-0 d-flex align-items-center" >
134185 < Sparkles className = "text-warning me-2" size = { 20 } />
@@ -145,36 +196,49 @@ export const TopicRefiner: FC<TopicRefinerProps> = ({
145196 </ button >
146197 </ div >
147198 </ div >
148-
149- { llmSuggestions . length > 0 ? (
150- < div className = "list-group" style = { { maxHeight : '400px' , overflowY : 'auto' } } >
151- { llmSuggestions . map ( ( suggestion ) => (
152- < div key = { suggestion } className = "list-group-item d-flex justify-content-between align-items-center" >
153- < span > { suggestion } </ span >
154- < button
155- className = { `btn btn-sm ${ selectedTopics . includes ( suggestion ) ? 'btn-success' : 'btn-outline-primary' } ` }
156- onClick = { ( ) => selectLlmSuggestion ( suggestion ) }
157- disabled = { selectedTopics . includes ( suggestion ) }
158- >
159- { selectedTopics . includes ( suggestion ) ? (
199+ { /* Show selected topics first */ }
200+ { selectedTopics . length > 0 && llmSuggestions . length === 0 && (
201+ < div className = "d-flex flex-column h-100" style = { { minHeight : 250 , justifyContent : 'flex-start' } } >
202+ < div className = "list-group w-100 mb-0" style = { { flex : 1 , overflowY : 'auto' , maxHeight : 300 , marginBottom : 0 , paddingBottom : 0 } } >
203+ { selectedTopics . map ( ( topic ) => (
204+ < div key = { topic } className = "list-group-item d-flex justify-content-between align-items-center" >
205+ < span > { topic } </ span >
206+ < button
207+ className = "btn btn-sm btn-outline-secondary"
208+ disabled
209+ >
160210 < Check size = { 16 } />
161- ) : (
162- < Plus size = { 16 } />
163- ) }
164- </ button >
165- </ div >
166- ) ) }
211+ </ button >
212+ </ div >
213+ ) ) }
214+ </ div >
215+ </ div >
216+ ) }
217+ { /* Show AI suggestions (excluding selected topics) */ }
218+ { llmSuggestions . length > 0 ? (
219+ < div >
220+ < h6 className = "text-muted mb-2" > New Suggestions</ h6 >
221+ < div className = "list-group" style = { { maxHeight : '200px' , overflowY : 'auto' } } >
222+ { llmSuggestions
223+ . filter ( suggestion => ! selectedTopics . includes ( suggestion ) )
224+ . map ( ( suggestion ) => (
225+ < div key = { suggestion } className = "list-group-item d-flex justify-content-between align-items-center" >
226+ < span > { suggestion } </ span >
227+ < button
228+ className = "btn btn-sm btn-outline-primary"
229+ onClick = { ( ) => selectLlmSuggestion ( suggestion ) }
230+ >
231+ < Plus size = { 16 } />
232+ </ button >
233+ </ div >
234+ ) ) }
235+ </ div >
167236 </ div >
168237 ) : (
169- < div className = "text-center text-muted py-5" >
238+ < div className = "text-center py-5" >
170239 { isLlmProcessing ? (
171240 < p className = "text-primary" > Analyzing topics...</ p >
172- ) : (
173- < >
174- < AlertCircle size = { 32 } className = "mb-3" />
175- < p > Configure AI settings to receive suggestions</ p >
176- </ >
177- ) }
241+ ) : null }
178242 </ div >
179243 ) }
180244 </ div >
@@ -183,8 +247,8 @@ export const TopicRefiner: FC<TopicRefinerProps> = ({
183247
184248 { /* Manual Topic Management */ }
185249 < div className = "col-md-6" >
186- < div className = "card h-100" >
187- < div className = "card-body" >
250+ < div className = "card h-100" style = { { minHeight : 180 } } >
251+ < div className = "card-body" style = { { minHeight : 180 , maxHeight : 180 , overflowY : 'auto' } } >
188252 < h3 className = "h5 mb-4 d-flex align-items-center" >
189253 < Edit size = { 20 } className = "text-primary me-2" />
190254 Customize Topics
@@ -209,38 +273,12 @@ export const TopicRefiner: FC<TopicRefinerProps> = ({
209273 </ button >
210274 </ div >
211275 </ div >
212-
213- < div >
214- < h4 className = "h6 mb-3" > Selected Topics ({ selectedTopics . length } )</ h4 >
215- < div className = "list-group" style = { { maxHeight : '400px' , overflowY : 'auto' } } >
216- { selectedTopics . length > 0 ? (
217- selectedTopics . map ( ( topic ) => (
218- < div key = { topic } className = "list-group-item d-flex justify-content-between align-items-center" >
219- < span > { topic } </ span >
220- < button
221- className = "btn btn-sm btn-outline-danger"
222- onClick = { ( ) => removeTopic ( topic ) }
223- >
224- < X size = { 16 } />
225- </ button >
226- </ div >
227- ) )
228- ) : (
229- < p className = "text-muted text-center py-4 fst-italic" >
230- No topics selected yet.
231- </ p >
232- ) }
233- </ div >
234- </ div >
235276 </ div >
236277 </ div >
237278 </ div >
238279 </ div >
239280
240- < div className = "d-flex justify-content-between mt-4" >
241- < button className = "btn btn-outline-secondary" onClick = { prevStep } >
242- Back
243- </ button >
281+ < div className = "d-flex justify-content-end mt-4" >
244282 < button
245283 className = "btn btn-success d-flex align-items-center"
246284 onClick = { handleSubmit }
@@ -253,6 +291,47 @@ export const TopicRefiner: FC<TopicRefinerProps> = ({
253291 </ div >
254292 </ div >
255293
294+ { /* Welcome Modal */ }
295+ { showWelcomeModal && (
296+ < div className = "modal show d-block" tabIndex = { - 1 } role = "dialog" style = { { backgroundColor : 'rgba(0,0,0,0.5)' } } >
297+ < div className = "modal-dialog modal-dialog-centered" >
298+ < div className = "modal-content" >
299+ < div className = "modal-header" >
300+ < h5 className = "modal-title d-flex align-items-center" >
301+ < Sparkles className = "text-warning me-2" size = { 20 } />
302+ Welcome to Topic Refinement
303+ </ h5 >
304+ < button
305+ type = "button"
306+ className = "btn-close"
307+ onClick = { ( ) => setShowWelcomeModal ( false ) }
308+ aria-label = "Close"
309+ > </ button >
310+ </ div >
311+ < div className = "modal-body" >
312+ < div className = "alert alert-info mb-0" >
313+ < p className = "mb-0" >
314+ Your selected topics have been loaded. Please use AI to further refine them with your search term: < span className = "badge bg-primary" style = { { fontSize : '1rem' } } > { searchTerm } </ span >
315+ </ p >
316+ </ div >
317+ </ div >
318+ < div className = "modal-footer" >
319+ { /* <button
320+ type="button"
321+ className="btn btn-primary"
322+ onClick={() => {
323+ setShowWelcomeModal(false);
324+ setShowPromptModal(true);
325+ }}
326+ >
327+ Configure AI Settings
328+ </button> */ }
329+ </ div >
330+ </ div >
331+ </ div >
332+ </ div >
333+ ) }
334+
256335 { /* Prompt Customization Modal */ }
257336 { showPromptModal && (
258337 < div className = "modal show d-block" tabIndex = { - 1 } role = "dialog" style = { { backgroundColor : 'rgba(0,0,0,0.5)' } } >
@@ -368,6 +447,6 @@ export const TopicRefiner: FC<TopicRefinerProps> = ({
368447 </ div >
369448 </ div >
370449 ) }
371- </ >
450+ </ main >
372451 ) ;
373452} ;
0 commit comments