@@ -98,13 +98,21 @@ export const TopicRefiner: FC<Omit<TopicRefinerProps, 'isLlmProcessing'>> = ({
9898 const [ topicCounts , setTopicCounts ] = useState < { [ key : string ] : number } > ( { } ) ;
9999 const [ uniqueReposCount , setUniqueReposCount ] = useState < number > ( 0 ) ;
100100 const [ showConfirmationModal , setShowConfirmationModal ] = useState ( false ) ;
101+ const [ isLoadingUniqueCount , setIsLoadingUniqueCount ] = useState ( false ) ;
102+ const [ uniqueCountError , setUniqueCountError ] = useState < string | null > ( null ) ;
101103
102104 // Function to fetch unique repository count for all finalized topics
103105 const fetchUniqueReposCount = async ( topics : string [ ] ) => {
104106 if ( topics . length === 0 ) {
105107 setUniqueReposCount ( 0 ) ;
108+ setIsLoadingUniqueCount ( false ) ;
109+ setUniqueCountError ( null ) ;
106110 return ;
107111 }
112+
113+ setIsLoadingUniqueCount ( true ) ;
114+ setUniqueCountError ( null ) ;
115+
108116 try {
109117 const response = await fetch ( API_ENDPOINTS . GET_UNIQUE_REPOS , {
110118 method : 'POST' ,
@@ -113,20 +121,54 @@ export const TopicRefiner: FC<Omit<TopicRefinerProps, 'isLlmProcessing'>> = ({
113121 } ,
114122 body : JSON . stringify ( { topics } ) ,
115123 } ) ;
124+
125+ if ( ! response . ok ) {
126+ throw new Error ( `HTTP ${ response . status } : ${ response . statusText } ` ) ;
127+ }
128+
116129 const data = await response . json ( ) ;
117130 if ( data . success ) {
118131 setUniqueReposCount ( data . count ) ;
132+ console . log ( 'Unique repos count updated:' , data . count ) ;
133+ } else {
134+ throw new Error ( data . message || 'Failed to get unique repos count' ) ;
119135 }
120136 } catch ( error ) {
121137 console . error ( 'Error fetching unique repos count:' , error ) ;
138+ setUniqueCountError ( error instanceof Error ? error . message : 'Unknown error' ) ;
139+ // Set a fallback count based on topic counts to ensure popup still works
140+ const fallbackCount = topics . reduce ( ( total , topic ) => {
141+ return total + ( topicCounts [ topic ] || 0 ) ;
142+ } , 0 ) ;
143+ setUniqueReposCount ( fallbackCount ) ;
144+ } finally {
145+ setIsLoadingUniqueCount ( false ) ;
122146 }
123147 } ;
124148
125149 // Update unique repos count when finalized topics change
126150 useEffect ( ( ) => {
151+ console . log ( 'Finalized topics changed, fetching unique repos count:' , finalizedTopics ) ;
127152 fetchUniqueReposCount ( finalizedTopics ) ;
128153 } , [ finalizedTopics ] ) ;
129154
155+ // Also update when topicCounts change to ensure accuracy
156+ useEffect ( ( ) => {
157+ if ( finalizedTopics . length > 0 && ! isLoadingUniqueCount ) {
158+ // Recalculate if we have new topic counts
159+ const hasAllCounts = finalizedTopics . every ( topic => topicCounts [ topic ] ) ;
160+ if ( hasAllCounts ) {
161+ const calculatedCount = finalizedTopics . reduce ( ( total , topic ) => {
162+ return total + ( topicCounts [ topic ] || 0 ) ;
163+ } , 0 ) ;
164+ // Only update if it's significantly different to avoid unnecessary API calls
165+ if ( Math . abs ( calculatedCount - uniqueReposCount ) > 100 ) {
166+ setUniqueReposCount ( calculatedCount ) ;
167+ }
168+ }
169+ }
170+ } , [ topicCounts , finalizedTopics , isLoadingUniqueCount , uniqueReposCount ] ) ;
171+
130172 // Calculate total repositories for finalized topics using topicCounts
131173 const totalRepositories = useMemo ( ( ) => {
132174 return finalizedTopics . reduce ( ( total , topic ) => {
@@ -439,11 +481,28 @@ export const TopicRefiner: FC<Omit<TopicRefinerProps, 'isLlmProcessing'>> = ({
439481 } , [ ] ) ;
440482
441483 const handleSubmitFinalizedTopics = async ( ) => {
484+ // Wait for unique count to be loaded if it's still loading
485+ if ( isLoadingUniqueCount ) {
486+ console . log ( 'Waiting for unique count to load...' ) ;
487+ // Wait a bit for the count to load
488+ await new Promise ( resolve => setTimeout ( resolve , 500 ) ) ;
489+ }
490+
442491 // Add confirmation for large repository counts
443492 if ( uniqueReposCount > 10000 ) {
493+ console . log ( 'Showing confirmation modal for large dataset:' , uniqueReposCount ) ;
494+ setShowConfirmationModal ( true ) ;
495+ return ;
496+ }
497+
498+ // If we have an error but still have a count, check if it's over threshold
499+ if ( uniqueCountError && uniqueReposCount > 10000 ) {
500+ console . log ( 'Showing confirmation modal despite error, count:' , uniqueReposCount ) ;
444501 setShowConfirmationModal ( true ) ;
445502 return ;
446503 }
504+
505+ console . log ( 'Proceeding with submission, unique count:' , uniqueReposCount ) ;
447506 await submitTopics ( ) ;
448507 } ;
449508
@@ -845,17 +904,54 @@ export const TopicRefiner: FC<Omit<TopicRefinerProps, 'isLlmProcessing'>> = ({
845904 < div className = "d-flex justify-content-end align-items-center mt-4 gap-3" >
846905 < div className = "text-muted" style = { { fontSize : '0.9rem' } } >
847906 < div > Total Topic Occurrences: < span className = "fw-bold" > { totalRepositories . toLocaleString ( ) } </ span > </ div >
848- < div > Unique Repositories: < span className = "fw-bold" > { uniqueReposCount . toLocaleString ( ) } </ span > </ div >
907+ < div className = "d-flex align-items-center gap-2" >
908+ Unique Repositories:
909+ { isLoadingUniqueCount ? (
910+ < span className = "d-flex align-items-center gap-1" >
911+ < div className = "spinner-border spinner-border-sm" role = "status" style = { { width : "0.75rem" , height : "0.75rem" } } >
912+ < span className = "visually-hidden" > Loading...</ span >
913+ </ div >
914+ < span className = "fw-bold" > Loading...</ span >
915+ </ span >
916+ ) : uniqueCountError ? (
917+ < span className = "fw-bold text-danger" title = { uniqueCountError } >
918+ { uniqueReposCount . toLocaleString ( ) } (Fallback)
919+ </ span >
920+ ) : (
921+ < span className = "fw-bold" > { uniqueReposCount . toLocaleString ( ) } </ span >
922+ ) }
923+ </ div >
924+ { uniqueCountError && (
925+ < div className = "d-flex align-items-center gap-2 mt-1" >
926+ < small className = "text-danger" >
927+ ⚠️ Using fallback count due to API error
928+ </ small >
929+ < button
930+ className = "btn btn-sm btn-outline-secondary"
931+ onClick = { ( ) => fetchUniqueReposCount ( finalizedTopics ) }
932+ disabled = { isLoadingUniqueCount }
933+ style = { { fontSize : '0.75rem' , padding : '0.25rem 0.5rem' } }
934+ >
935+ { isLoadingUniqueCount ? (
936+ < div className = "spinner-border spinner-border-sm" role = "status" style = { { width : "0.75rem" , height : "0.75rem" } } >
937+ < span className = "visually-hidden" > Loading...</ span >
938+ </ div >
939+ ) : (
940+ 'Retry'
941+ ) }
942+ </ button >
943+ </ div >
944+ ) }
849945 </ div >
850946 < button
851947 className = "btn d-flex align-items-center"
852948 onClick = { handleSubmitFinalizedTopics }
853- disabled = { finalizedTopics . length === 0 || isSubmitting }
949+ disabled = { finalizedTopics . length === 0 || isSubmitting || isLoadingUniqueCount }
854950 style = { {
855951 color : 'white' ,
856952 backgroundColor : '#198754' , // Bootstrap's success color
857953 borderColor : '#198754' ,
858- opacity : finalizedTopics . length === 0 || isSubmitting ? 0.65 : 1
954+ opacity : finalizedTopics . length === 0 || isSubmitting || isLoadingUniqueCount ? 0.65 : 1
859955 } }
860956 >
861957 { isSubmitting ? (
@@ -1011,7 +1107,10 @@ export const TopicRefiner: FC<Omit<TopicRefinerProps, 'isLlmProcessing'>> = ({
10111107 < button
10121108 type = "button"
10131109 className = "btn-close"
1014- onClick = { ( ) => setShowConfirmationModal ( false ) }
1110+ onClick = { ( ) => {
1111+ console . log ( 'Confirmation modal closed by user' ) ;
1112+ setShowConfirmationModal ( false ) ;
1113+ } }
10151114 aria-label = "Close"
10161115 > </ button >
10171116 </ div >
@@ -1023,20 +1122,27 @@ export const TopicRefiner: FC<Omit<TopicRefinerProps, 'isLlmProcessing'>> = ({
10231122 < p className = "mb-0" >
10241123 This may take a while to process and could impact performance. Are you sure you want to continue?
10251124 </ p >
1125+ < small className = "d-block mt-2 text-muted" >
1126+ Debug: Threshold is 10,000, current count: { uniqueReposCount }
1127+ </ small >
10261128 </ div >
10271129 </ div >
10281130 < div className = "modal-footer" >
10291131 < button
10301132 type = "button"
10311133 className = "btn btn-secondary"
1032- onClick = { ( ) => setShowConfirmationModal ( false ) }
1134+ onClick = { ( ) => {
1135+ console . log ( 'Confirmation modal cancelled by user' ) ;
1136+ setShowConfirmationModal ( false ) ;
1137+ } }
10331138 >
10341139 Cancel
10351140 </ button >
10361141 < button
10371142 type = "button"
10381143 className = "btn btn-danger"
10391144 onClick = { async ( ) => {
1145+ console . log ( 'Confirmation modal confirmed by user, proceeding with submission' ) ;
10401146 setShowConfirmationModal ( false ) ;
10411147 await submitTopics ( ) ;
10421148 } }
0 commit comments