@@ -41,6 +41,35 @@ interface Application {
4141 project : { _id : string ; title : string } ;
4242}
4343
44+ interface Mentor {
45+ _id : string ;
46+ name : string ;
47+ email : string ;
48+ company ?: string ;
49+ jobTitle ?: string ;
50+ picture ?: string ;
51+ expertise ?: string [ ] ;
52+ isActive : boolean ;
53+ isVerified : boolean ;
54+ createdAt ?: string ;
55+ }
56+
57+ interface Mentee {
58+ _id : string ;
59+ name : string ;
60+ email : string ;
61+ university ?: string ;
62+ degree ?: string ;
63+ picture ?: string ;
64+ skills ?: string [ ] ;
65+ mentor ?: { _id : string ; name : string ; company ?: string ; jobTitle ?: string ; picture ?: string } | string ;
66+ projects ?: Array < string | { _id : string } > ;
67+ applications ?: Array < string | { _id : string } > ;
68+ isActive : boolean ;
69+ isVerified : boolean ;
70+ createdAt ?: string ;
71+ }
72+
4473interface Stats {
4574 projects : { total : number ; open : number ; inProgress : number ; completed : number } ;
4675 mentors : number ;
@@ -52,6 +81,8 @@ export default function AdminDSOCPage() {
5281 const [ activeTab , setActiveTab ] = useState ( 'overview' ) ;
5382 const [ projects , setProjects ] = useState < Project [ ] > ( [ ] ) ;
5483 const [ applications , setApplications ] = useState < Application [ ] > ( [ ] ) ;
84+ const [ mentors , setMentors ] = useState < Mentor [ ] > ( [ ] ) ;
85+ const [ mentees , setMentees ] = useState < Mentee [ ] > ( [ ] ) ;
5586 const [ stats , setStats ] = useState < Stats | null > ( null ) ;
5687 const [ loading , setLoading ] = useState ( true ) ;
5788 const [ search , setSearch ] = useState ( '' ) ;
@@ -62,21 +93,27 @@ export default function AdminDSOCPage() {
6293
6394 const fetchData = async ( ) => {
6495 try {
65- const [ statsRes , projectsRes , appsRes ] = await Promise . all ( [
96+ const [ statsRes , projectsRes , appsRes , mentorsRes , menteesRes ] = await Promise . all ( [
6697 fetch ( '/api/dsoc/stats' ) ,
6798 fetch ( '/api/dsoc/projects?limit=100' ) ,
68- fetch ( '/api/dsoc/applications' )
99+ fetch ( '/api/dsoc/applications' ) ,
100+ fetch ( '/api/dsoc/mentors' ) ,
101+ fetch ( '/api/dsoc/mentees' )
69102 ] ) ;
70103
71- const [ statsData , projectsData , appsData ] = await Promise . all ( [
104+ const [ statsData , projectsData , appsData , mentorsData , menteesData ] = await Promise . all ( [
72105 statsRes . json ( ) ,
73106 projectsRes . json ( ) ,
74- appsRes . json ( )
107+ appsRes . json ( ) ,
108+ mentorsRes . json ( ) ,
109+ menteesRes . json ( )
75110 ] ) ;
76111
77112 if ( statsData . success ) setStats ( statsData . data ) ;
78113 if ( projectsData . success ) setProjects ( projectsData . data ) ;
79114 if ( appsData . success ) setApplications ( appsData . data ) ;
115+ if ( mentorsData . success ) setMentors ( mentorsData . data || [ ] ) ;
116+ if ( menteesData . success ) setMentees ( menteesData . data || [ ] ) ;
80117 } catch ( error ) {
81118 console . error ( 'Error fetching data:' , error ) ;
82119 } finally {
@@ -398,23 +435,183 @@ export default function AdminDSOCPage() {
398435
399436 { /* Mentors Tab */ }
400437 { activeTab === 'mentors' && (
401- < div className = "neo-brutal-card p-12 text-center" >
402- < Users className = "w-16 h-16 mx-auto text-muted-foreground mb-4" />
403- < h3 className = "text-xl font-bold mb-2" > Mentor Management</ h3 >
404- < p className = "text-muted-foreground" >
405- Coming soon - manage mentor profiles, verification, and project assignments.
406- </ p >
438+ < div className = "space-y-6" >
439+ < div className = "neo-brutal-card p-6 flex items-center justify-between gap-4 flex-wrap" >
440+ < div >
441+ < h3 className = "text-xl font-bold mb-1" > Mentor Management</ h3 >
442+ < p className = "text-muted-foreground" >
443+ Review mentor profiles, see verification state, and open the public mentor page.
444+ </ p >
445+ </ div >
446+ < div className = "flex items-center gap-3 text-sm font-bold uppercase tracking-wider" >
447+ < span className = "neo-brutal-badge bg-[var(--dsoc-secondary)] text-white" >
448+ Total { mentors . length }
449+ </ span >
450+ < span className = "neo-brutal-badge bg-[var(--dsoc-success)] text-white" >
451+ Active { mentors . filter ( ( mentor ) => mentor . isActive ) . length }
452+ </ span >
453+ </ div >
454+ </ div >
455+
456+ { mentors . length === 0 ? (
457+ < div className = "neo-brutal-card p-12 text-center" >
458+ < Users className = "w-16 h-16 mx-auto text-muted-foreground mb-4" />
459+ < h3 className = "text-xl font-bold mb-2" > No mentors found</ h3 >
460+ < p className = "text-muted-foreground" >
461+ Create a mentor from the DSOC mentor registration page or seed one in the database.
462+ </ p >
463+ </ div >
464+ ) : (
465+ < div className = "grid gap-4 md:grid-cols-2 xl:grid-cols-3" >
466+ { mentors . map ( ( mentor ) => (
467+ < div key = { mentor . _id } className = "neo-brutal-card p-5 flex flex-col gap-4" >
468+ < div className = "flex items-start gap-4" >
469+ < div className = "w-14 h-14 rounded-full overflow-hidden border-4 border-[var(--dsoc-dark)] bg-[var(--dsoc-dark)] text-white flex items-center justify-center font-black shrink-0" >
470+ { mentor . picture ? (
471+ < img src = { mentor . picture } alt = { mentor . name } className = "w-full h-full object-cover" />
472+ ) : (
473+ mentor . name
474+ . split ( ' ' )
475+ . map ( ( part ) => part [ 0 ] )
476+ . join ( '' )
477+ . slice ( 0 , 2 )
478+ ) }
479+ </ div >
480+
481+ < div className = "min-w-0 flex-1" >
482+ < h4 className = "font-bold text-lg leading-tight" > { mentor . name } </ h4 >
483+ < p className = "text-sm text-muted-foreground truncate" > { mentor . email } </ p >
484+ < p className = "text-sm text-muted-foreground mt-1" >
485+ { mentor . jobTitle || 'Mentor' } { mentor . company ? ` · ${ mentor . company } ` : '' }
486+ </ p >
487+ </ div >
488+ </ div >
489+
490+ < div className = "flex flex-wrap gap-2 text-xs font-bold uppercase tracking-wider" >
491+ < span className = { `neo-brutal-badge ${ mentor . isActive ? 'bg-[var(--dsoc-success)] text-white' : 'bg-gray-300 text-black' } ` } >
492+ { mentor . isActive ? 'Active' : 'Inactive' }
493+ </ span >
494+ < span className = { `neo-brutal-badge ${ mentor . isVerified ? 'bg-[var(--dsoc-primary)] text-white' : 'bg-[var(--dsoc-pink)] text-white' } ` } >
495+ { mentor . isVerified ? 'Verified' : 'Pending Review' }
496+ </ span >
497+ </ div >
498+
499+ { mentor . expertise && mentor . expertise . length > 0 && (
500+ < div className = "flex flex-wrap gap-2" >
501+ { mentor . expertise . slice ( 0 , 4 ) . map ( ( skill ) => (
502+ < span key = { skill } className = "px-2 py-1 text-xs font-bold border-2 border-[var(--dsoc-dark)] bg-background" >
503+ { skill }
504+ </ span >
505+ ) ) }
506+ </ div >
507+ ) }
508+
509+ < Link
510+ href = "/mentor"
511+ className = "neo-brutal-btn neo-brutal-btn-secondary w-full justify-center"
512+ >
513+ View Mentor Portal
514+ </ Link >
515+ </ div >
516+ ) ) }
517+ </ div >
518+ ) }
407519 </ div >
408520 ) }
409521
410522 { /* Mentees Tab */ }
411523 { activeTab === 'mentees' && (
412- < div className = "neo-brutal-card p-12 text-center" >
413- < Users className = "w-16 h-16 mx-auto text-muted-foreground mb-4" />
414- < h3 className = "text-xl font-bold mb-2" > Mentee Management</ h3 >
415- < p className = "text-muted-foreground" >
416- Coming soon - manage mentee profiles and project participation.
417- </ p >
524+ < div className = "space-y-6" >
525+ < div className = "neo-brutal-card p-6 flex items-center justify-between gap-4 flex-wrap" >
526+ < div >
527+ < h3 className = "text-xl font-bold mb-1" > Mentee Management</ h3 >
528+ < p className = "text-muted-foreground" >
529+ Review mentee profiles, verify status, and see their mentor/project connections.
530+ </ p >
531+ </ div >
532+ < div className = "flex items-center gap-3 text-sm font-bold uppercase tracking-wider" >
533+ < span className = "neo-brutal-badge bg-[var(--dsoc-secondary)] text-white" >
534+ Total { mentees . length }
535+ </ span >
536+ < span className = "neo-brutal-badge bg-[var(--dsoc-success)] text-white" >
537+ Active { mentees . filter ( ( mentee ) => mentee . isActive ) . length }
538+ </ span >
539+ </ div >
540+ </ div >
541+
542+ { mentees . length === 0 ? (
543+ < div className = "neo-brutal-card p-12 text-center" >
544+ < Users className = "w-16 h-16 mx-auto text-muted-foreground mb-4" />
545+ < h3 className = "text-xl font-bold mb-2" > No mentees found</ h3 >
546+ < p className = "text-muted-foreground" >
547+ Create a mentee from the DSOC mentee registration page or seed one in the database.
548+ </ p >
549+ </ div >
550+ ) : (
551+ < div className = "grid gap-4 md:grid-cols-2 xl:grid-cols-3" >
552+ { mentees . map ( ( mentee ) => {
553+ const mentorName = typeof mentee . mentor === 'object' ? mentee . mentor . name : null ;
554+
555+ return (
556+ < div key = { mentee . _id } className = "neo-brutal-card p-5 flex flex-col gap-4" >
557+ < div className = "flex items-start gap-4" >
558+ < div className = "w-14 h-14 rounded-full overflow-hidden border-4 border-[var(--dsoc-dark)] bg-[var(--dsoc-dark)] text-white flex items-center justify-center font-black shrink-0" >
559+ { mentee . picture ? (
560+ < img src = { mentee . picture } alt = { mentee . name } className = "w-full h-full object-cover" />
561+ ) : (
562+ mentee . name
563+ . split ( ' ' )
564+ . map ( ( part ) => part [ 0 ] )
565+ . join ( '' )
566+ . slice ( 0 , 2 )
567+ ) }
568+ </ div >
569+
570+ < div className = "min-w-0 flex-1" >
571+ < h4 className = "font-bold text-lg leading-tight" > { mentee . name } </ h4 >
572+ < p className = "text-sm text-muted-foreground truncate" > { mentee . email } </ p >
573+ < p className = "text-sm text-muted-foreground mt-1" >
574+ { mentee . degree || 'Mentee' } { mentee . university ? ` · ${ mentee . university } ` : '' }
575+ </ p >
576+ </ div >
577+ </ div >
578+
579+ < div className = "flex flex-wrap gap-2 text-xs font-bold uppercase tracking-wider" >
580+ < span className = { `neo-brutal-badge ${ mentee . isActive ? 'bg-[var(--dsoc-success)] text-white' : 'bg-gray-300 text-black' } ` } >
581+ { mentee . isActive ? 'Active' : 'Inactive' }
582+ </ span >
583+ < span className = { `neo-brutal-badge ${ mentee . isVerified ? 'bg-[var(--dsoc-primary)] text-white' : 'bg-[var(--dsoc-pink)] text-white' } ` } >
584+ { mentee . isVerified ? 'Verified' : 'Pending Review' }
585+ </ span >
586+ </ div >
587+
588+ < div className = "text-sm text-muted-foreground space-y-1" >
589+ < p > < span className = "font-bold text-foreground" > Mentor:</ span > { mentorName || 'Unassigned' } </ p >
590+ < p > < span className = "font-bold text-foreground" > Projects:</ span > { mentee . projects ?. length || 0 } </ p >
591+ < p > < span className = "font-bold text-foreground" > Applications:</ span > { mentee . applications ?. length || 0 } </ p >
592+ </ div >
593+
594+ { mentee . skills && mentee . skills . length > 0 && (
595+ < div className = "flex flex-wrap gap-2" >
596+ { mentee . skills . slice ( 0 , 4 ) . map ( ( skill ) => (
597+ < span key = { skill } className = "px-2 py-1 text-xs font-bold border-2 border-[var(--dsoc-dark)] bg-background" >
598+ { skill }
599+ </ span >
600+ ) ) }
601+ </ div >
602+ ) }
603+
604+ < Link
605+ href = "/dsoc/register/mentee"
606+ className = "neo-brutal-btn neo-brutal-btn-secondary w-full justify-center"
607+ >
608+ View Mentee Portal
609+ </ Link >
610+ </ div >
611+ ) ;
612+ } ) }
613+ </ div >
614+ ) }
418615 </ div >
419616 ) }
420617 </ main >
0 commit comments