@@ -50,9 +50,8 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
5050 > ( { } )
5151 const [ isSubmitting , setIsSubmitting ] = useState ( false )
5252 const [ isSaving , setIsSaving ] = useState ( false )
53- const [ showSent , setShowSent ] = useState ( false )
53+ const cooldownIntervalsRef = useRef < Map < string , NodeJS . Timeout > > ( new Map ( ) )
5454 const [ errorMessage , setErrorMessage ] = useState < string | null > ( null )
55- const [ successMessage , setSuccessMessage ] = useState < string | null > ( null )
5655 const [ memberToRemove , setMemberToRemove ] = useState < { userId : string ; email : string } | null > (
5756 null
5857 )
@@ -118,6 +117,21 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
118117 }
119118 } , [ open , workspaceId , fetchPendingInvitations , refetchPermissions ] )
120119
120+ // Clear error message when modal opens
121+ useEffect ( ( ) => {
122+ if ( open ) {
123+ setErrorMessage ( null )
124+ }
125+ } , [ open ] )
126+
127+ useEffect ( ( ) => {
128+ const intervalsRef = cooldownIntervalsRef . current
129+ return ( ) => {
130+ intervalsRef . forEach ( ( interval ) => clearInterval ( interval ) )
131+ intervalsRef . clear ( )
132+ }
133+ } , [ ] )
134+
121135 const addEmail = useCallback (
122136 ( email : string ) => {
123137 if ( ! email . trim ( ) ) return false
@@ -248,11 +262,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
248262 }
249263
250264 setExistingUserPermissionChanges ( { } )
251-
252- setSuccessMessage (
253- `Permission changes saved for ${ updates . length } user${ updates . length !== 1 ? 's' : '' } !`
254- )
255- setTimeout ( ( ) => setSuccessMessage ( null ) , 3000 )
256265 } catch ( error ) {
257266 logger . error ( 'Error saving permission changes:' , error )
258267 const errorMsg =
@@ -275,9 +284,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
275284 if ( ! userPerms . canAdmin || ! hasPendingChanges ) return
276285
277286 setExistingUserPermissionChanges ( { } )
278- setSuccessMessage ( 'Changes restored to original permissions!' )
279-
280- setTimeout ( ( ) => setSuccessMessage ( null ) , 3000 )
281287 } , [ userPerms . canAdmin , hasPendingChanges ] )
282288
283289 const handleRemoveMemberClick = useCallback ( ( userId : string , email : string ) => {
@@ -330,9 +336,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
330336 delete updated [ memberToRemove . userId ]
331337 return updated
332338 } )
333-
334- setSuccessMessage ( `${ memberToRemove . email } has been removed from the workspace` )
335- setTimeout ( ( ) => setSuccessMessage ( null ) , 3000 )
336339 } catch ( error ) {
337340 logger . error ( 'Error removing member:' , error )
338341 const errorMsg =
@@ -378,9 +381,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
378381 setPendingInvitations ( ( prev ) =>
379382 prev . filter ( ( inv ) => inv . invitationId !== invitationToRemove . invitationId )
380383 )
381-
382- setSuccessMessage ( `Invitation for ${ invitationToRemove . email } has been cancelled` )
383- setTimeout ( ( ) => setSuccessMessage ( null ) , 3000 )
384384 } catch ( error ) {
385385 logger . error ( 'Error cancelling invitation:' , error )
386386 const errorMsg =
@@ -420,9 +420,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
420420 throw new Error ( data . error || 'Failed to resend invitation' )
421421 }
422422
423- setSuccessMessage ( `Invitation resent to ${ email } ` )
424- setTimeout ( ( ) => setSuccessMessage ( null ) , 3000 )
425-
426423 setResentInvitationIds ( ( prev ) => ( { ...prev , [ invitationId ] : true } ) )
427424 setTimeout ( ( ) => {
428425 setResentInvitationIds ( ( prev ) => {
@@ -443,6 +440,12 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
443440 return next
444441 } )
445442 setResendCooldowns ( ( prev ) => ( { ...prev , [ invitationId ] : 60 } ) )
443+
444+ const existingInterval = cooldownIntervalsRef . current . get ( invitationId )
445+ if ( existingInterval ) {
446+ clearInterval ( existingInterval )
447+ }
448+
446449 const interval = setInterval ( ( ) => {
447450 setResendCooldowns ( ( prev ) => {
448451 const current = prev [ invitationId ]
@@ -451,11 +454,14 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
451454 const next = { ...prev }
452455 delete next [ invitationId ]
453456 clearInterval ( interval )
457+ cooldownIntervalsRef . current . delete ( invitationId )
454458 return next
455459 }
456460 return { ...prev , [ invitationId ] : current - 1 }
457461 } )
458462 } , 1000 )
463+
464+ cooldownIntervalsRef . current . set ( invitationId , interval )
459465 }
460466 } ,
461467 [ workspaceId , userPerms . canAdmin , resendCooldowns ]
@@ -466,7 +472,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
466472 e . preventDefault ( )
467473
468474 setErrorMessage ( null )
469- setSuccessMessage ( null )
470475
471476 if ( validEmails . length === 0 || ! workspaceId ) {
472477 return
@@ -555,11 +560,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
555560 setEmailItems ( [ ] )
556561 setUserPermissions ( [ ] )
557562 }
558- setShowSent ( true )
559-
560- setTimeout ( ( ) => {
561- setShowSent ( false )
562- } , 4000 )
563563 }
564564 } catch ( err ) {
565565 logger . error ( 'Error inviting members:' , err )
@@ -581,23 +581,23 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
581581 setExistingUserPermissionChanges ( { } )
582582 setIsSubmitting ( false )
583583 setIsSaving ( false )
584- setShowSent ( false )
585584 setErrorMessage ( null )
586- setSuccessMessage ( null )
587585 setMemberToRemove ( null )
588586 setIsRemovingMember ( false )
589587 setInvitationToRemove ( null )
590588 setIsRemovingInvitation ( false )
589+ setResendCooldowns ( { } )
590+ setResentInvitationIds ( { } )
591+
592+ cooldownIntervalsRef . current . forEach ( ( interval ) => clearInterval ( interval ) )
593+ cooldownIntervalsRef . current . clear ( )
591594 } , [ ] )
592595
593596 return (
594597 < Modal
595598 open = { open }
596599 onOpenChange = { ( newOpen : boolean ) => {
597- if ( newOpen ) {
598- setErrorMessage ( null )
599- setSuccessMessage ( null )
600- } else {
600+ if ( ! newOpen ) {
601601 resetState ( )
602602 }
603603 onOpenChange ( newOpen )
0 commit comments