@@ -468,7 +468,33 @@ const SubmissionFormContent: React.FC<SubmissionFormContentProps> = ({
468468 form . setValue ( 'links' , updatedLinks , { shouldValidate : true } ) ;
469469 } ;
470470
471+ // Team size configuration and computed state (only when hackathon defines limits)
472+ const teamMin = currentHackathon ?. teamMin ;
473+ const teamMax = currentHackathon ?. teamMax ;
474+ const hasTeamLimits = teamMin !== undefined && teamMax !== undefined ;
475+ const watchedTeamMembers = form . watch ( 'teamMembers' ) ;
476+ const currentTeamSize = ( watchedTeamMembers ?. length ?? 0 ) + 1 ;
477+ const isTeamAtCapacity = hasTeamLimits && currentTeamSize >= teamMax ;
478+ const isTeamBelowMinimum = hasTeamLimits && currentTeamSize < teamMin ;
479+ const membersNeededForMinimum = hasTeamLimits ? teamMin - currentTeamSize : 0 ;
480+
481+ function getTeamSizeBadgeStyle ( ) : string {
482+ if ( isTeamAtCapacity ) {
483+ return 'border-yellow-500 bg-yellow-500/10 text-yellow-500' ;
484+ }
485+ if ( isTeamBelowMinimum ) {
486+ return 'border-orange-500 bg-orange-500/10 text-orange-500' ;
487+ }
488+ return 'border-gray-600 text-gray-400' ;
489+ }
490+
471491 const handleAddInvitee = ( ) => {
492+ // Guard: prevent adding members when team is at capacity
493+ if ( isTeamAtCapacity ) {
494+ toast . error ( `Team is at maximum capacity (${ teamMax } members)` ) ;
495+ return ;
496+ }
497+
472498 if ( ! currentInviteeName || ! currentInviteeRole || ! currentInviteeEmail ) {
473499 toast . error ( 'Please fill in name, email and role' ) ;
474500 return ;
@@ -517,6 +543,14 @@ const SubmissionFormContent: React.FC<SubmissionFormContentProps> = ({
517543 form . setError ( 'teamName' , { message : 'Team Name is required' } ) ;
518544 return ;
519545 }
546+
547+ if ( isTeamBelowMinimum ) {
548+ toast . error (
549+ `Your team needs at least ${ teamMin } members. Please invite ${ membersNeededForMinimum } more member${ membersNeededForMinimum > 1 ? 's' : '' } to continue.`
550+ ) ;
551+ return ;
552+ }
553+
520554 isValid = true ;
521555 }
522556 } else {
@@ -931,9 +965,35 @@ const SubmissionFormContent: React.FC<SubmissionFormContentProps> = ({
931965 />
932966
933967 < div className = 'space-y-3' >
934- < FormLabel className = 'text-white' >
935- Invite Members (Optional)
936- </ FormLabel >
968+ < div className = 'flex items-center justify-between' >
969+ < FormLabel className = 'text-white' >
970+ Invite Members
971+ { hasTeamLimits && teamMin > 1 && (
972+ < span className = 'ml-1 text-xs text-gray-400' >
973+ (min { teamMin } members)
974+ </ span >
975+ ) }
976+ </ FormLabel >
977+ { hasTeamLimits && (
978+ < Badge
979+ variant = 'outline'
980+ className = { cn (
981+ 'transition-colors' ,
982+ getTeamSizeBadgeStyle ( )
983+ ) }
984+ >
985+ < Users className = 'mr-1 h-3 w-3' />
986+ { currentTeamSize } / { teamMax } members
987+ </ Badge >
988+ ) }
989+ </ div >
990+ { isTeamBelowMinimum && (
991+ < p className = 'text-xs text-orange-400' >
992+ You need at least { membersNeededForMinimum } more
993+ member{ membersNeededForMinimum > 1 ? 's' : '' } to
994+ proceed.
995+ </ p >
996+ ) }
937997 < div className = 'flex flex-col gap-3' >
938998 < div className = 'grid grid-cols-1 gap-3 md:grid-cols-3' >
939999 < Input
@@ -943,6 +1003,7 @@ const SubmissionFormContent: React.FC<SubmissionFormContentProps> = ({
9431003 setCurrentInviteeName ( e . target . value )
9441004 }
9451005 className = 'border-gray-700 bg-gray-800/50 text-white'
1006+ disabled = { isTeamAtCapacity }
9461007 />
9471008 < Input
9481009 placeholder = 'Email'
@@ -952,6 +1013,7 @@ const SubmissionFormContent: React.FC<SubmissionFormContentProps> = ({
9521013 setCurrentInviteeEmail ( e . target . value )
9531014 }
9541015 className = 'border-gray-700 bg-gray-800/50 text-white'
1016+ disabled = { isTeamAtCapacity }
9551017 />
9561018 < Input
9571019 placeholder = 'Role (e.g. Designer)'
@@ -960,15 +1022,22 @@ const SubmissionFormContent: React.FC<SubmissionFormContentProps> = ({
9601022 setCurrentInviteeRole ( e . target . value )
9611023 }
9621024 className = 'border-gray-700 bg-gray-800/50 text-white'
1025+ disabled = { isTeamAtCapacity }
9631026 />
9641027 </ div >
9651028 < Button
9661029 type = 'button'
9671030 onClick = { handleAddInvitee }
968- className = 'self-start bg-gray-800 text-white hover:bg-gray-700'
1031+ disabled = { isTeamAtCapacity }
1032+ className = { cn (
1033+ 'self-start' ,
1034+ isTeamAtCapacity
1035+ ? 'cursor-not-allowed bg-gray-700 text-gray-500 opacity-50'
1036+ : 'bg-gray-800 text-white hover:bg-gray-700'
1037+ ) }
9691038 >
9701039 < Plus className = 'mr-2 h-4 w-4' />
971- Add Member
1040+ { isTeamAtCapacity ? 'Team Full' : ' Add Member' }
9721041 </ Button >
9731042 </ div >
9741043
0 commit comments