import { type ComponentProps, useCallback, type Dispatch, type SetStateAction, } from 'react' import { useTranslation } from 'react-i18next' import { Dropdown, DropdownItem, DropdownMenu, DropdownToggle, } from '@/features/ui/components/bootstrap-5/dropdown-menu' import { User } from '../../../../../../types/group-management/user' import useAsync from '@/shared/hooks/use-async' import { type FetchError, postJSON } from '@/infrastructure/fetch-json' import { GroupUserAlert } from '../../utils/types' import { useGroupMembersContext } from '../../context/group-members-context' import getMeta from '@/utils/meta' import MaterialIcon from '@/shared/components/material-icon' import DropdownListItem from '@/features/ui/components/bootstrap-5/dropdown-list-item' import { Spinner } from 'react-bootstrap-5' type resendInviteResponse = { success: boolean } type ManagedUserDropdownButtonProps = { user: User openOffboardingModalForUser: (user: User) => void openUnlinkUserModal: (user: User) => void groupId: string setGroupUserAlert: Dispatch> } export default function DropdownButton({ user, openOffboardingModalForUser, openUnlinkUserModal, groupId, setGroupUserAlert, }: ManagedUserDropdownButtonProps) { const { t } = useTranslation() const { removeMember } = useGroupMembersContext() const { runAsync: runResendManagedUserInviteAsync, isLoading: isResendingManagedUserInvite, } = useAsync() const { runAsync: runResendLinkSSOInviteAsync, isLoading: isResendingSSOLinkInvite, } = useAsync() const { runAsync: runResendGroupInviteAsync, isLoading: isResendingGroupInvite, } = useAsync() const managedUsersActive = getMeta('ol-managedUsersActive') const groupSSOActive = getMeta('ol-groupSSOActive') const userPending = user.invite const isGroupSSOLinked = !userPending && user.enrollment?.sso?.some(sso => sso.groupId === groupId) const isUserManaged = !userPending && user.enrollment?.managedBy === groupId const handleResendManagedUserInvite = useCallback( async user => { try { const result = await runResendManagedUserInviteAsync( postJSON( `/manage/groups/${groupId}/resendManagedUserInvite/${user._id}` ) ) if (result.success) { setGroupUserAlert({ variant: 'resendManagedUserInviteSuccess', email: user.email, }) } } catch (err) { if ((err as FetchError)?.response?.status === 429) { setGroupUserAlert({ variant: 'resendInviteTooManyRequests', email: user.email, }) } else { setGroupUserAlert({ variant: 'resendManagedUserInviteFailed', email: user.email, }) } } }, [setGroupUserAlert, groupId, runResendManagedUserInviteAsync] ) const handleResendLinkSSOInviteAsync = useCallback( async user => { try { const result = await runResendLinkSSOInviteAsync( postJSON(`/manage/groups/${groupId}/resendSSOLinkInvite/${user._id}`) ) if (result.success) { setGroupUserAlert({ variant: 'resendSSOLinkInviteSuccess', email: user.email, }) } } catch (err) { if ((err as FetchError)?.response?.status === 429) { setGroupUserAlert({ variant: 'resendInviteTooManyRequests', email: user.email, }) } else { setGroupUserAlert({ variant: 'resendSSOLinkInviteFailed', email: user.email, }) } } }, [setGroupUserAlert, groupId, runResendLinkSSOInviteAsync] ) const handleResendGroupInvite = useCallback( async user => { try { await runResendGroupInviteAsync( postJSON(`/manage/groups/${groupId}/resendInvite/`, { body: { email: user.email, }, }) ) setGroupUserAlert({ variant: 'resendGroupInviteSuccess', email: user.email, }) } catch (err) { if ((err as FetchError)?.response?.status === 429) { setGroupUserAlert({ variant: 'resendInviteTooManyRequests', email: user.email, }) } else { setGroupUserAlert({ variant: 'resendGroupInviteFailed', email: user.email, }) } } }, [setGroupUserAlert, groupId, runResendGroupInviteAsync] ) const onResendManagedUserInviteClick = () => { handleResendManagedUserInvite(user) } const onResendSSOLinkInviteClick = () => { handleResendLinkSSOInviteAsync(user) } const onResendGroupInviteClick = () => { handleResendGroupInvite(user) } const onDeleteUserClick = () => { openOffboardingModalForUser(user) } const onRemoveFromGroup = () => { removeMember(user) } const onUnlinkUserClick = () => { openUnlinkUserModal(user) } const buttons = [] if (userPending) { buttons.push( {t('resend_group_invite')} ) } if (managedUsersActive && !isUserManaged && !userPending) { buttons.push( {t('resend_managed_user_invite')} ) } if (groupSSOActive && isGroupSSOLinked) { buttons.push( {t('unlink_user')} ) } if (groupSSOActive && !isGroupSSOLinked && !userPending) { buttons.push( {t('resend_link_sso')} ) } if (isUserManaged && !user.isEntityAdmin) { buttons.push( {t('delete_user')} ) } else if (!isUserManaged) { buttons.push( {t('remove_from_group')} ) } if (buttons.length === 0) { buttons.push( {t('no_actions')} ) } return ( {buttons} ) } type MenuItemButtonProps = { isLoading?: boolean 'data-testid'?: string } & Pick, 'children' | 'onClick' | 'className'> & Pick, 'variant'> function MenuItemButton({ children, onClick, className, isLoading, variant, 'data-testid': dataTestId, }: MenuItemButtonProps) { return ( ) }