import { useCallback, useState } from 'react' import { Button, Col, Form, FormControl, Row } from 'react-bootstrap' import { useTranslation } from 'react-i18next' import { deleteJSON, FetchError, postJSON } from '@/infrastructure/fetch-json' import MaterialIcon from '../../../shared/components/material-icon' import Tooltip from '../../../shared/components/tooltip' import getMeta from '../../../utils/meta' import { parseEmails } from '../utils/emails' import ErrorAlert, { APIError } from './error-alert' import UserRow from './user-row' import useUserSelection from '../hooks/use-user-selection' import { User } from '../../../../../types/group-management/user' import { debugConsole } from '@/utils/debugging' type ManagersPaths = { addMember: string removeMember: string } type UsersTableProps = { groupName: string paths: ManagersPaths translations: { title: string subtitle: string remove: string } } export function ManagersTable({ groupName, translations, paths, }: UsersTableProps) { const { t } = useTranslation() const { users, setUsers, selectedUsers, selectAllUsers, unselectAllUsers, selectUser, unselectUser, } = useUserSelection(getMeta('ol-users') || []) const [emailString, setEmailString] = useState('') const [inviteUserInflightCount, setInviteUserInflightCount] = useState(0) const [inviteError, setInviteError] = useState() const [removeMemberInflightCount, setRemoveMemberInflightCount] = useState(0) const [removeMemberError, setRemoveMemberError] = useState() const addManagers = useCallback( e => { e.preventDefault() setInviteError(undefined) const emails = parseEmails(emailString) ;(async () => { for (const email of emails) { setInviteUserInflightCount(count => count + 1) try { const data = await postJSON<{ user: User }>(paths.addMember, { body: { email, }, }) if (data.user) { const alreadyListed = users.find( user => user.email === data.user.email ) if (!alreadyListed) { setUsers(users => [...users, data.user]) } } setEmailString('') } catch (error: unknown) { debugConsole.error(error) setInviteError((error as FetchError)?.data?.error || {}) } setInviteUserInflightCount(count => count - 1) } })() }, [emailString, paths.addMember, users, setUsers] ) const removeManagers = useCallback( e => { e.preventDefault() setRemoveMemberError(undefined) ;(async () => { for (const user of selectedUsers) { let url if (paths.removeMember && user._id) { url = `${paths.removeMember}/${user._id}` } else { return } setRemoveMemberInflightCount(count => count + 1) try { await deleteJSON(url, {}) setUsers(users => users.filter(u => u !== user)) unselectUser(user) } catch (error: unknown) { debugConsole.error(error) setRemoveMemberError((error as FetchError)?.data?.error || {}) } setRemoveMemberInflightCount(count => count - 1) } })() }, [selectedUsers, unselectUser, setUsers, paths.removeMember] ) const handleSelectAllClick = useCallback( (e: React.ChangeEvent) => { if (e.target.checked) { selectAllUsers() } else { unselectAllUsers() } }, [selectAllUsers, unselectAllUsers] ) const handleEmailsChange = useCallback( e => { setEmailString(e.target.value) }, [setEmailString] ) return (

{' '} {groupName || translations.title}

{removeMemberInflightCount > 0 ? ( ) : ( <> {selectedUsers.length > 0 && ( )} )}

{translations.subtitle}

  • {t('email')} {t('name')} {t('last_active')} (?) {t('accepted_invite')}
  • {users.length === 0 && (
  • {t('no_members')}
  • )} {users.map(user => ( ))}

{t('add_more_managers')}

{inviteUserInflightCount > 0 ? ( ) : ( )} {t('add_comma_separated_emails_help')}
) }