import { AddLinkEventTracker, GetSessionDataManager, GroupAdminGiveComposer, GroupAdminTakeComposer, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupMemberParser, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembersParser, GroupRank, GroupRemoveMemberComposer, ILinkEventTracker, RemoveLinkEventTracker } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { FaChevronLeft, FaChevronRight } from 'react-icons/fa'; import { GetUserProfile, LocalizeText, SendMessageComposer } from '../../../api'; import { Button, Column, Flex, Grid, LayoutAvatarImageView, LayoutBadgeImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../common'; import { useMessageEvent, useNotification } from '../../../hooks'; import { classNames } from '../../../layout'; export const GroupMembersView: FC<{}> = props => { const [ groupId, setGroupId ] = useState(-1); const [ levelId, setLevelId ] = useState(-1); const [ membersData, setMembersData ] = useState(null); const [ pageId, setPageId ] = useState(-1); const [ totalPages, setTotalPages ] = useState(0); const [ searchQuery, setSearchQuery ] = useState(''); const [ removingMemberName, setRemovingMemberName ] = useState(null); const { showConfirm = null } = useNotification(); const pendingActionsRef = useRef>(new Set()); const getRankDescription = (member: GroupMemberParser) => { if(member.rank === GroupRank.OWNER) return 'group.members.owner'; if(membersData.admin) { if(member.rank === GroupRank.ADMIN) return 'group.members.removerights'; if(member.rank === GroupRank.MEMBER) return 'group.members.giverights'; } return ''; }; const refreshMembers = useCallback(() => { if((groupId === -1) || (levelId === -1) || (pageId === -1)) return; SendMessageComposer(new GroupMembersComposer(groupId, pageId, searchQuery, levelId)); }, [ groupId, levelId, pageId, searchQuery ]); const toggleAdmin = (member: GroupMemberParser) => { if(!membersData.admin || (member.rank === GroupRank.OWNER)) return; const key = `admin_${member.id}`; if(pendingActionsRef.current.has(key)) return; pendingActionsRef.current.add(key); setTimeout(() => pendingActionsRef.current.delete(key), 2000); if(member.rank !== GroupRank.ADMIN) SendMessageComposer(new GroupAdminGiveComposer(membersData.groupId, member.id)); else SendMessageComposer(new GroupAdminTakeComposer(membersData.groupId, member.id)); refreshMembers(); }; const acceptMembership = (member: GroupMemberParser) => { if(!membersData.admin || (member.rank !== GroupRank.REQUESTED)) return; const key = `accept_${member.id}`; if(pendingActionsRef.current.has(key)) return; pendingActionsRef.current.add(key); setTimeout(() => pendingActionsRef.current.delete(key), 2000); SendMessageComposer(new GroupMembershipAcceptComposer(membersData.groupId, member.id)); refreshMembers(); }; const removeMemberOrDeclineMembership = (member: GroupMemberParser) => { if(!membersData.admin) return; const key = `remove_${member.id}`; if(pendingActionsRef.current.has(key)) return; pendingActionsRef.current.add(key); setTimeout(() => pendingActionsRef.current.delete(key), 2000); if(member.rank === GroupRank.REQUESTED) { SendMessageComposer(new GroupMembershipDeclineComposer(membersData.groupId, member.id)); refreshMembers(); return; } setRemovingMemberName(member.name); SendMessageComposer(new GroupConfirmRemoveMemberComposer(membersData.groupId, member.id)); }; useMessageEvent(GroupMembersEvent, event => { const parser = event.getParser(); setMembersData(parser); setLevelId(parser.level); setTotalPages(Math.ceil(parser.totalMembersCount / parser.pageSize)); }); useMessageEvent(GroupConfirmMemberRemoveEvent, event => { const parser = event.getParser(); showConfirm(LocalizeText(((parser.furnitureCount > 0) ? 'group.kickconfirm.desc' : 'group.kickconfirm_nofurni.desc'), [ 'user', 'amount' ], [ removingMemberName, parser.furnitureCount.toString() ]), () => { SendMessageComposer(new GroupRemoveMemberComposer(membersData.groupId, parser.userId)); refreshMembers(); }, null); setRemovingMemberName(null); }); useEffect(() => { const linkTracker: ILinkEventTracker = { linkReceived: (url: string) => { const parts = url.split('/'); if(parts.length < 2) return; const groupId = (parseInt(parts[1]) || -1); const levelId = (parseInt(parts[2]) || 3); setGroupId(groupId); setLevelId(levelId); setPageId(0); }, eventUrlPrefix: 'group-members/' }; AddLinkEventTracker(linkTracker); return () => RemoveLinkEventTracker(linkTracker); }, []); useEffect(() => { setPageId(0); }, [ groupId, levelId, searchQuery ]); useEffect(() => { if((groupId === -1) || (levelId === -1) || (pageId === -1)) return; SendMessageComposer(new GroupMembersComposer(groupId, pageId, searchQuery, levelId)); }, [ groupId, levelId, pageId, searchQuery ]); useEffect(() => { if(groupId === -1) return; setLevelId(-1); setMembersData(null); setTotalPages(0); setSearchQuery(''); setRemovingMemberName(null); }, [ groupId ]); if((groupId === -1) || !membersData) return null; return ( setGroupId(-1) } />
setSearchQuery(event.target.value) } />
{ membersData.result.map((member, index) => { return (
GetUserProfile(member.id) }>
GetUserProfile(member.id) }>{ member.name } { (member.rank !== GroupRank.REQUESTED) && { LocalizeText('group.members.since', [ 'date' ], [ member.joinedAt ]) } }
{ (member.rank !== GroupRank.REQUESTED) &&
toggleAdmin(member) } />
} { membersData.admin && (member.rank === GroupRank.REQUESTED) &&
acceptMembership(member) } /> } { membersData.admin && (member.rank !== GroupRank.OWNER) && (member.id !== GetSessionDataManager().userId) &&
removeMemberOrDeclineMembership(member) } /> }
); }) } { LocalizeText('group.members.pageinfo', [ 'amount', 'page', 'totalPages' ], [ membersData.totalMembersCount.toString(), (membersData.pageIndex + 1).toString(), totalPages.toString() ]) } ); };