@@ -126,6 +126,8 @@ const TeamLeaderDisplay = ({
126126 email_address : teamLead . email_address ,
127127 display_position : teamLead . display_position ?? undefined ,
128128 image_url : teamLead . image_url ?? undefined ,
129+ username : ( teamLead as any ) . username ?? null ,
130+ username_updated_at : ( teamLead as any ) . username_updated_at ?? null ,
129131 availability_status : undefined ,
130132 internal_status : undefined ,
131133 years_of_experience : undefined ,
@@ -199,7 +201,7 @@ const TeamMembersGrid = ({
199201
200202 return (
201203 < div className = "h-full flex flex-col" >
202- < h4 className = "text-base sm:text-lg font-semibold text-white mb-1" > Team Members</ h4 >
204+ < h4 className = "text-base sm:text-lg font-semibold text-white mb-1 mt-[-15px] " > Team Members</ h4 >
203205 < div className = "mb-1 sm:mb-2 md:mt-2" >
204206 < span className = "text-white text-xs sm:text-sm" > { members . length } members</ span >
205207 </ div >
@@ -315,6 +317,33 @@ const AddMembersModal = ({
315317 const [ isUpdating , setIsUpdating ] = useState ( false ) ;
316318 const [ availableMembers , setAvailableMembers ] = useState < Codev [ ] > ( [ ] ) ;
317319 const [ isLoadingMembers , setIsLoadingMembers ] = useState ( false ) ;
320+ const [ loadError , setLoadError ] = useState < string | null > ( null ) ;
321+
322+ // ✅ NEW: Direct fetch function that includes ALL internal statuses including INTERN
323+ const fetchAllCodevs = useCallback ( async ( ) : Promise < Codev [ ] > => {
324+ if ( ! supabase ) {
325+ console . error ( 'Supabase client not available' ) ;
326+ return [ ] ;
327+ }
328+
329+ try {
330+ const { data, error } = await supabase
331+ . from ( 'codev' )
332+ . select ( '*' )
333+ . in ( 'internal_status' , [ 'GRADUATED' , 'INTERN' , 'MENTOR' , 'TRAINING' , 'ADMIN' , 'ONBOARDING' ] )
334+ . order ( 'first_name' , { ascending : true } ) ;
335+
336+ if ( error ) {
337+ console . error ( 'Error fetching codevs:' , error ) ;
338+ throw error ;
339+ }
340+
341+ return data || [ ] ;
342+ } catch ( error ) {
343+ console . error ( 'Failed to fetch codevs directly:' , error ) ;
344+ throw error ;
345+ }
346+ } , [ supabase ] ) ;
318347
319348 // ✅ Enhanced profile fetching with timeout protection
320349 const getCompleteCodevProfileSafe = useCallback ( async ( codevId : string ) : Promise < Codev | null > => {
@@ -404,31 +433,66 @@ const AddMembersModal = ({
404433 }
405434 } , [ getCompleteCodevProfileSafe , openProfileModal ] ) ;
406435
407- // ✅ Load available members with timeout
436+ // ✅ FIXED: Load available members using direct fetch that includes INTERNS
408437 useEffect ( ( ) => {
438+ let isMounted = true ;
439+ let timeoutId : NodeJS . Timeout ;
440+
409441 const loadMembers = async ( ) => {
410- if ( ! isOpen ) return ;
442+ if ( ! isOpen || ! supabase ) return ;
411443
412444 setIsLoadingMembers ( true ) ;
445+ setLoadError ( null ) ;
446+
413447 try {
414- const loadPromise = getProjectCodevs ( ) ;
415- const timeoutPromise = new Promise < never > ( ( _ , reject ) =>
416- setTimeout ( ( ) => reject ( new Error ( 'Load members timeout' ) ) , 10000 )
417- ) ;
418-
419- const users = await Promise . race ( [ loadPromise , timeoutPromise ] ) ;
420- setAvailableMembers ( users || [ ] ) ;
421- } catch ( error ) {
448+ // Set up timeout
449+ timeoutId = setTimeout ( ( ) => {
450+ if ( isMounted ) {
451+ throw new Error ( 'Loading timeout' ) ;
452+ }
453+ } , 30000 ) ;
454+
455+ // ✅ Use direct fetch instead of getProjectCodevs()
456+ const users = await fetchAllCodevs ( ) ;
457+
458+ clearTimeout ( timeoutId ) ;
459+
460+ if ( isMounted ) {
461+ console . log ( '✅ Loaded users:' , users . length ) ;
462+ setAvailableMembers ( users || [ ] ) ;
463+ setLoadError ( null ) ;
464+ }
465+ } catch ( error : any ) {
422466 console . error ( 'Failed to fetch members:' , error ) ;
423- toast . error ( 'Failed to load members' ) ;
424- setAvailableMembers ( [ ] ) ;
467+
468+ if ( isMounted ) {
469+ const errorMessage = error ?. message || 'Failed to load members' ;
470+ setLoadError ( errorMessage ) ;
471+
472+ if ( errorMessage . includes ( 'timeout' ) ) {
473+ toast . error ( 'Loading members is taking longer than expected. Please try again.' ) ;
474+ } else {
475+ toast . error ( 'Failed to load members. Please try again.' ) ;
476+ }
477+
478+ setAvailableMembers ( [ ] ) ;
479+ }
425480 } finally {
426- setIsLoadingMembers ( false ) ;
481+ if ( isMounted ) {
482+ setIsLoadingMembers ( false ) ;
483+ }
427484 }
428485 } ;
429486
430487 loadMembers ( ) ;
431- } , [ isOpen ] ) ;
488+
489+ return ( ) => {
490+ isMounted = false ;
491+ if ( timeoutId ) {
492+ clearTimeout ( timeoutId ) ;
493+ }
494+ } ;
495+ } , [ isOpen , supabase , fetchAllCodevs ] ) ;
432496
433497 // ✅ Initialize selected members
434498 useEffect ( ( ) => {
@@ -493,10 +557,11 @@ const AddMembersModal = ({
493557 if ( ! isOpen ) {
494558 setSearchQuery ( "" ) ;
495559 setSelectedMembers ( [ ] ) ;
560+ setLoadError ( null ) ;
496561 }
497562 } , [ isOpen ] ) ;
498563
499- // ✅ Submit handler with timeout
564+ // ✅ FIXED: Submit handler with username and username_updated_at
500565 const handleSubmit = async ( ) => {
501566 if ( ! teamLeadData ) {
502567 toast . error ( 'Team leader not found' ) ;
@@ -513,6 +578,8 @@ const AddMembersModal = ({
513578 positions : [ ] ,
514579 tech_stacks : [ ] ,
515580 display_position : teamLeadData . display_position ?? undefined ,
581+ username : ( teamLeadData as any ) . username ?? null ,
582+ username_updated_at : ( teamLeadData as any ) . username_updated_at ?? null ,
516583 } ,
517584 ...selectedMembers
518585 . filter ( ( member ) => member . id !== teamLeadData . id )
@@ -522,18 +589,12 @@ const AddMembersModal = ({
522589 } ) ) ,
523590 ] ;
524591
525- const updatePromise = updateProjectMembers (
592+ const result = await updateProjectMembers (
526593 project . id ,
527594 updatedMembers ,
528595 teamLeadData . id ,
529596 ) ;
530597
531- const timeoutPromise = new Promise < never > ( ( _ , reject ) =>
532- setTimeout ( ( ) => reject ( new Error ( 'Update timeout' ) ) , 15000 )
533- ) ;
534-
535- const result = await Promise . race ( [ updatePromise , timeoutPromise ] ) ;
536-
537598 if ( result . success ) {
538599 toast . success ( "Team members updated successfully!" , { id : loadingToast } ) ;
539600 await onUpdate ( selectedMembers ) ;
@@ -550,6 +611,25 @@ const AddMembersModal = ({
550611 }
551612 } ;
552613
614+ // ✅ Retry loading members
615+ const handleRetryLoad = async ( ) => {
616+ setLoadError ( null ) ;
617+ setIsLoadingMembers ( true ) ;
618+
619+ try {
620+ const users = await fetchAllCodevs ( ) ;
621+ setAvailableMembers ( users || [ ] ) ;
622+ setLoadError ( null ) ;
623+ } catch ( error ) {
624+ console . error ( 'Retry failed:' , error ) ;
625+ setLoadError ( 'Failed to load members' ) ;
626+ toast . error ( 'Failed to load members. Please try again.' ) ;
627+ setAvailableMembers ( [ ] ) ;
628+ } finally {
629+ setIsLoadingMembers ( false ) ;
630+ }
631+ } ;
632+
553633 if ( ! isOpen ) return null ;
554634
555635 return (
@@ -605,6 +685,20 @@ const AddMembersModal = ({
605685 < div className = "animate-spin rounded-full h-8 w-8 border-b-2 border-customBlue-500 mx-auto mb-3" > </ div >
606686 < p > Loading members...</ p >
607687 </ div >
688+ ) : loadError ? (
689+ < div className = "text-center py-8" >
690+ < div className = "text-red-400 mb-4" >
691+ < p className = "font-semibold mb-2" > Failed to load members</ p >
692+ < p className = "text-sm text-gray-400" > { loadError } </ p >
693+ </ div >
694+ < Button
695+ onClick = { handleRetryLoad }
696+ variant = "outline"
697+ className = "border-customBlue-500 text-customBlue-400 hover:bg-customBlue-500/10"
698+ >
699+ Try Again
700+ </ Button >
701+ </ div >
608702 ) : filteredUsers . length > 0 ? (
609703 filteredUsers . slice ( 0 , 50 ) . map ( ( user ) => (
610704 < div
0 commit comments