import {useEffect, useState} from 'react';
import {AnimatePresence, m} from 'framer-motion';
import {useWorkspaceWithMembers} from './requests/workspace-with-members';
import {ProgressCircle} from '../ui/progress/progress-circle';
import {Workspace} from './types/workspace';
import {GroupIcon} from '../icons/material/Group';
import {WorkspaceMember} from './types/workspace-member';
import {useAuth} from '../auth/use-auth';
import {
ChipField,
ChipValue,
} from '../ui/forms/input-field/chip-field/chip-field';
import {useValueLists} from '../http/value-lists';
import {Button} from '../ui/buttons/button';
import {ArrowDropDownIcon} from '../icons/material/ArrowDropDown';
import {useInviteMembers} from './requests/invite-members';
import {WorkspaceInvite} from './types/workspace-invite';
import {ConfirmationDialog} from '../ui/overlays/dialog/confirmation-dialog';
import {useResendInvite} from './requests/resend-invite';
import {isEmail} from '../utils/string/is-email';
import {ButtonSize} from '../ui/buttons/button-size';
import {useChangeRole} from './requests/change-role';
import {IconButton} from '../ui/buttons/icon-button';
import {useRemoveMember} from './requests/remove-member';
import {CloseIcon} from '../icons/material/Close';
import {ExitToAppIcon} from '../icons/material/ExitToApp';
import {toast} from '../ui/toast/toast';
import {DialogTrigger} from '../ui/overlays/dialog/dialog-trigger';
import {Menu, MenuItem, MenuTrigger} from '../ui/navigation/menu/menu-trigger';
import {useDialogContext} from '../ui/overlays/dialog/dialog-context';
import {Dialog} from '../ui/overlays/dialog/dialog';
import {DialogHeader} from '../ui/overlays/dialog/dialog-header';
import {DialogBody} from '../ui/overlays/dialog/dialog-body';
import {Trans} from '../i18n/trans';
import {useTrans} from '../i18n/use-trans';
import {message} from '../i18n/message';
import {LeaveWorkspaceConfirmation} from './leave-workspace-confirmation';
interface WorkspaceMembersDialogProps {
workspace: Workspace;
}
export function WorkspaceMembersDialog({
workspace,
}: WorkspaceMembersDialogProps) {
const {data, isLoading} = useWorkspaceWithMembers(workspace.id);
return (
);
}
interface ManagerProps {
workspace: Workspace;
}
function Manager({workspace}: ManagerProps) {
const {user} = useAuth();
const can = usePermissions(workspace);
const members: (WorkspaceMember | WorkspaceInvite)[] = [
...(workspace.members || []),
...(workspace.invites || []),
];
const shouldHideOtherMembers = !can.update && !can.delete;
return (
{can.invite &&
}
{members.map(member => {
if (shouldHideOtherMembers && member.id !== user?.id) {
return null;
}
return (
);
})}
{shouldHideOtherMembers && (
)}
);
}
interface MemberListItemProps {
member: WorkspaceMember | WorkspaceInvite;
workspace: Workspace;
}
function MemberListItem({workspace, member}: MemberListItemProps) {
return (
);
}
function usePermissions(workspace: Workspace) {
const {user: authUser} = useAuth();
const response = {update: false, invite: false, delete: false};
const permissions = ['update', 'invite', 'delete'] as const;
const authMember = workspace.members?.find(mb => mb.id === authUser?.id);
if (authMember) {
permissions.forEach(permission => {
response[permission] =
authMember.is_owner ||
!!authMember.permissions?.find(
p => p.name === `workspace_members.${permission}`,
);
});
}
return response;
}
interface MemberActionsProps {
workspace: Workspace;
member: WorkspaceMember | WorkspaceInvite;
}
function MemberActions({workspace, member}: MemberActionsProps) {
const [selectedRole, setSelectedRole] = useState(member.role_id);
const changeRole = useChangeRole();
const {user} = useAuth();
const can = usePermissions(workspace);
const isOwner = member.model_type === 'member' && member.is_owner;
const isCurrentUser =
member.model_type === 'member' && user?.id === member.id;
const roleSelector =
!can.update || isOwner || isCurrentUser ? (
) : (
{
setSelectedRole(roleId);
changeRole.mutate({
roleId,
workspaceId: workspace.id,
member,
});
}}
/>
);
return (
<>
{roleSelector}
{!isOwner && (isCurrentUser || can.delete) && (
)}
>
);
}
interface InviteChipFieldProps {
workspace: Workspace;
}
function InviteChipField({workspace}: InviteChipFieldProps) {
const {trans} = useTrans();
const [chips, setChips] = useState([]);
const allEmailsValid = chips.every(chip => !chip.invalid);
const displayWith = (chip: ChipValue) => chip.description || chip.name;
const [selectedRole, setSelectedRole] = useState();
const inviteMembers = useInviteMembers();
const {data} = useValueLists(['workspaceRoles']);
useEffect(() => {
if (!selectedRole && data?.workspaceRoles?.length) {
setSelectedRole(data.workspaceRoles[0].id);
}
}, [data, selectedRole]);
return (
{
const invalid = !isEmail(chip.description);
return {
...chip,
invalid,
errorMessage: invalid
? trans({message: 'Not a valid email'})
: undefined,
};
}}
placeholder={trans({message: 'Enter email addresses'})}
label={}
/>
{chips.length && selectedRole ? (
) : null}
);
}
interface RemoveMemberButtonProps {
member: WorkspaceMember | WorkspaceInvite;
workspace: Workspace;
type: 'leave' | 'remove';
}
function RemoveMemberButton({
member,
workspace,
type,
}: RemoveMemberButtonProps) {
const removeMember = useRemoveMember();
const {close} = useDialogContext();
return (
{
if (isConfirmed) {
removeMember.mutate({
workspaceId: workspace.id,
memberId: member.id,
memberType: member.model_type,
});
if (type === 'leave') {
close();
toast(message('Left workspace'));
}
}
}}
>
{type === 'leave' ? : }
{type === 'leave' ? (
) : (
)}
);
}
interface RemoveMemberConfirmationProps {
member: WorkspaceMember | WorkspaceInvite;
}
function RemoveMemberConfirmation({member}: RemoveMemberConfirmationProps) {
return (
}
body={
}
confirm={}
/>
);
}
interface RoleMenuTriggerProps {
onChange: (value: number) => void;
value?: number;
size?: ButtonSize;
className?: string;
isDisabled?: boolean;
}
function RoleMenuTrigger({
value,
onChange,
size = 'xs',
className,
isDisabled,
}: RoleMenuTriggerProps) {
const {data} = useValueLists(['workspaceRoles']);
const role = data?.workspaceRoles?.find(r => r.id === value);
if (!value || !role || !data?.workspaceRoles) return null;
return (
{
onChange(newValue as number);
}}
>
}
>
);
}
interface MemberDisplayNameAppendProps {
member: WorkspaceMember | WorkspaceInvite;
workspace: Workspace;
}
function MemberDisplayNameAppend({
member,
workspace,
}: MemberDisplayNameAppendProps) {
const {user} = useAuth();
const can = usePermissions(workspace);
if (user?.id === member.id) {
return (
()
);
}
if (member.model_type === 'invite') {
return (
·
{can.invite ? (
<>
·
>
) : null}
);
}
return null;
}
function ResendInviteDialogTrigger({
member,
workspace,
}: MemberDisplayNameAppendProps) {
const resendInvite = useResendInvite();
return (
{
if (isConfirmed) {
resendInvite.mutate({
workspaceId: workspace.id,
inviteId: member.id as string,
});
}
}}
>
}
body={
}
confirm={}
/>
);
}