Skip to content

Commit 6cf9841

Browse files
authored
fix(invite-modal): remove custom button heights and useEffect anti-pattern (#3082)
* fix(invite-modal): remove custom button heights and useEffect anti-pattern * cleanup
1 parent 656beb8 commit 6cf9841

File tree

2 files changed

+36
-30
lines changed
  • apps/sim/app
    • playground
    • workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/invite-modal

2 files changed

+36
-30
lines changed

apps/sim/app/playground/page.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
Cursor,
2525
DatePicker,
2626
DocumentAttachment,
27+
Download,
2728
Duplicate,
2829
Expand,
2930
Eye,
@@ -51,6 +52,7 @@ import {
5152
NoWrap,
5253
PanelLeft,
5354
Play,
55+
PlayOutline,
5456
Popover,
5557
PopoverBackButton,
5658
PopoverContent,
@@ -214,6 +216,9 @@ export default function PlaygroundPage() {
214216
<VariantRow label='primary'>
215217
<Button variant='primary'>Primary</Button>
216218
</VariantRow>
219+
<VariantRow label='destructive'>
220+
<Button variant='destructive'>Destructive</Button>
221+
</VariantRow>
217222
<VariantRow label='secondary'>
218223
<Button variant='secondary'>Secondary</Button>
219224
</VariantRow>
@@ -290,6 +295,9 @@ export default function PlaygroundPage() {
290295
<VariantRow label='outline'>
291296
<Badge variant='outline'>Outline</Badge>
292297
</VariantRow>
298+
<VariantRow label='type'>
299+
<Badge variant='type'>Type</Badge>
300+
</VariantRow>
293301
<VariantRow label='green'>
294302
<Badge variant='green'>Green</Badge>
295303
<Badge variant='green' dot>
@@ -323,6 +331,9 @@ export default function PlaygroundPage() {
323331
<VariantRow label='teal'>
324332
<Badge variant='teal'>Teal</Badge>
325333
</VariantRow>
334+
<VariantRow label='cyan'>
335+
<Badge variant='cyan'>Cyan</Badge>
336+
</VariantRow>
326337
<VariantRow label='gray'>
327338
<Badge variant='gray'>Gray</Badge>
328339
</VariantRow>
@@ -996,6 +1007,7 @@ export default function PlaygroundPage() {
9961007
{ Icon: Copy, name: 'Copy' },
9971008
{ Icon: Cursor, name: 'Cursor' },
9981009
{ Icon: DocumentAttachment, name: 'DocumentAttachment' },
1010+
{ Icon: Download, name: 'Download' },
9991011
{ Icon: Duplicate, name: 'Duplicate' },
10001012
{ Icon: Expand, name: 'Expand' },
10011013
{ Icon: Eye, name: 'Eye' },
@@ -1011,6 +1023,7 @@ export default function PlaygroundPage() {
10111023
{ Icon: NoWrap, name: 'NoWrap' },
10121024
{ Icon: PanelLeft, name: 'PanelLeft' },
10131025
{ Icon: Play, name: 'Play' },
1026+
{ Icon: PlayOutline, name: 'PlayOutline' },
10141027
{ Icon: Redo, name: 'Redo' },
10151028
{ Icon: Rocket, name: 'Rocket' },
10161029
{ Icon: Trash, name: 'Trash' },

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/invite-modal/invite-modal.tsx

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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
)
@@ -121,10 +120,17 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
121120
useEffect(() => {
122121
if (open) {
123122
setErrorMessage(null)
124-
setSuccessMessage(null)
125123
}
126124
}, [open])
127125

126+
useEffect(() => {
127+
const intervalsRef = cooldownIntervalsRef.current
128+
return () => {
129+
intervalsRef.forEach((interval) => clearInterval(interval))
130+
intervalsRef.clear()
131+
}
132+
}, [])
133+
128134
const addEmail = useCallback(
129135
(email: string) => {
130136
if (!email.trim()) return false
@@ -255,11 +261,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
255261
}
256262

257263
setExistingUserPermissionChanges({})
258-
259-
setSuccessMessage(
260-
`Permission changes saved for ${updates.length} user${updates.length !== 1 ? 's' : ''}!`
261-
)
262-
setTimeout(() => setSuccessMessage(null), 3000)
263264
} catch (error) {
264265
logger.error('Error saving permission changes:', error)
265266
const errorMsg =
@@ -282,9 +283,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
282283
if (!userPerms.canAdmin || !hasPendingChanges) return
283284

284285
setExistingUserPermissionChanges({})
285-
setSuccessMessage('Changes restored to original permissions!')
286-
287-
setTimeout(() => setSuccessMessage(null), 3000)
288286
}, [userPerms.canAdmin, hasPendingChanges])
289287

290288
const handleRemoveMemberClick = useCallback((userId: string, email: string) => {
@@ -337,9 +335,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
337335
delete updated[memberToRemove.userId]
338336
return updated
339337
})
340-
341-
setSuccessMessage(`${memberToRemove.email} has been removed from the workspace`)
342-
setTimeout(() => setSuccessMessage(null), 3000)
343338
} catch (error) {
344339
logger.error('Error removing member:', error)
345340
const errorMsg =
@@ -385,9 +380,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
385380
setPendingInvitations((prev) =>
386381
prev.filter((inv) => inv.invitationId !== invitationToRemove.invitationId)
387382
)
388-
389-
setSuccessMessage(`Invitation for ${invitationToRemove.email} has been cancelled`)
390-
setTimeout(() => setSuccessMessage(null), 3000)
391383
} catch (error) {
392384
logger.error('Error cancelling invitation:', error)
393385
const errorMsg =
@@ -427,9 +419,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
427419
throw new Error(data.error || 'Failed to resend invitation')
428420
}
429421

430-
setSuccessMessage(`Invitation resent to ${email}`)
431-
setTimeout(() => setSuccessMessage(null), 3000)
432-
433422
setResentInvitationIds((prev) => ({ ...prev, [invitationId]: true }))
434423
setTimeout(() => {
435424
setResentInvitationIds((prev) => {
@@ -450,6 +439,12 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
450439
return next
451440
})
452441
setResendCooldowns((prev) => ({ ...prev, [invitationId]: 60 }))
442+
443+
const existingInterval = cooldownIntervalsRef.current.get(invitationId)
444+
if (existingInterval) {
445+
clearInterval(existingInterval)
446+
}
447+
453448
const interval = setInterval(() => {
454449
setResendCooldowns((prev) => {
455450
const current = prev[invitationId]
@@ -458,11 +453,14 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
458453
const next = { ...prev }
459454
delete next[invitationId]
460455
clearInterval(interval)
456+
cooldownIntervalsRef.current.delete(invitationId)
461457
return next
462458
}
463459
return { ...prev, [invitationId]: current - 1 }
464460
})
465461
}, 1000)
462+
463+
cooldownIntervalsRef.current.set(invitationId, interval)
466464
}
467465
},
468466
[workspaceId, userPerms.canAdmin, resendCooldowns]
@@ -473,7 +471,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
473471
e.preventDefault()
474472

475473
setErrorMessage(null)
476-
setSuccessMessage(null)
477474

478475
if (validEmails.length === 0 || !workspaceId) {
479476
return
@@ -562,11 +559,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
562559
setEmailItems([])
563560
setUserPermissions([])
564561
}
565-
setShowSent(true)
566-
567-
setTimeout(() => {
568-
setShowSent(false)
569-
}, 4000)
570562
}
571563
} catch (err) {
572564
logger.error('Error inviting members:', err)
@@ -588,13 +580,16 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
588580
setExistingUserPermissionChanges({})
589581
setIsSubmitting(false)
590582
setIsSaving(false)
591-
setShowSent(false)
592583
setErrorMessage(null)
593-
setSuccessMessage(null)
594584
setMemberToRemove(null)
595585
setIsRemovingMember(false)
596586
setInvitationToRemove(null)
597587
setIsRemovingInvitation(false)
588+
setResendCooldowns({})
589+
setResentInvitationIds({})
590+
591+
cooldownIntervalsRef.current.forEach((interval) => clearInterval(interval))
592+
cooldownIntervalsRef.current.clear()
598593
}, [])
599594

600595
return (
@@ -703,7 +698,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
703698
variant='default'
704699
disabled={isSaving || isSubmitting}
705700
onClick={handleRestoreChanges}
706-
className='h-[32px] gap-[8px] px-[12px] font-medium'
707701
>
708702
Restore Changes
709703
</Button>
@@ -712,7 +706,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
712706
variant='tertiary'
713707
disabled={isSaving || isSubmitting}
714708
onClick={handleSaveChanges}
715-
className='h-[32px] gap-[8px] px-[12px] font-medium'
716709
>
717710
{isSaving ? 'Saving...' : 'Save Changes'}
718711
</Button>

0 commit comments

Comments
 (0)