Fix group members

This commit is contained in:
Bill 2022-02-22 21:39:42 -05:00
parent 54312a412e
commit cdb0760e19
3 changed files with 84 additions and 82 deletions

View File

@ -12,30 +12,31 @@ import { GroupMembersView } from './views/members/GroupMembersView';
export const GroupsView: FC<{}> = props => export const GroupsView: FC<{}> = props =>
{ {
const [ isCreatorVisible, setIsCreatorVisible ] = useState<boolean>(false); const [ currentGroupId, setCurrentGroupId ] = useState<number>(null);
const [ groupMembersId, setGroupMembersId ] = useState<number>(null); const [ currentGroupLevelId, setCurrentGroupLevelId ] = useState<number>(null);
const [ groupMembersLevel, setGroupMembersLevel ] = useState<number>(null); const [ isMembersVisible, setMembersVisible ] = useState<boolean>(false);
const [ isCreatorVisible, setCreatorVisible ] = useState<boolean>(false);
const [ groupsState, dispatchGroupsState ] = useReducer(GroupsReducer, initialGroups); const [ groupsState, dispatchGroupsState ] = useReducer(GroupsReducer, initialGroups);
const onGroupPurchasedEvent = useCallback((event: GroupPurchasedEvent) =>
{
const parser = event.getParser();
setIsCreatorVisible(false);
TryVisitRoom(parser.roomId);
}, []);
CreateMessageHook(GroupPurchasedEvent, onGroupPurchasedEvent);
const closeMembers = () => const closeMembers = () =>
{ {
BatchUpdates(() => BatchUpdates(() =>
{ {
setGroupMembersId(null); setCurrentGroupId(null);
setGroupMembersLevel(null); setCurrentGroupLevelId(null);
}); });
} }
const onGroupPurchasedEvent = useCallback((event: GroupPurchasedEvent) =>
{
const parser = event.getParser();
setCreatorVisible(false);
TryVisitRoom(parser.roomId);
}, []);
CreateMessageHook(GroupPurchasedEvent, onGroupPurchasedEvent);
const linkReceived = useCallback((url: string) => const linkReceived = useCallback((url: string) =>
{ {
const parts = url.split('/'); const parts = url.split('/');
@ -45,7 +46,7 @@ export const GroupsView: FC<{}> = props =>
switch(parts[1]) switch(parts[1])
{ {
case 'create': case 'create':
setIsCreatorVisible(true); setCreatorVisible(true);
return; return;
case 'manage': case 'manage':
if(!parts[2]) return; if(!parts[2]) return;
@ -55,12 +56,16 @@ export const GroupsView: FC<{}> = props =>
case 'members': case 'members':
if(!parts[2]) return; if(!parts[2]) return;
const groupId = (parseInt(parts[2]) || -1);
const levelId = (parseInt(parts[3]) || 3);
BatchUpdates(() => BatchUpdates(() =>
{ {
setGroupMembersId(Number(parts[2])); setCurrentGroupId(groupId);
setCurrentGroupLevelId(levelId);
if(parts[3]) setGroupMembersLevel(Number(parts[3])); setMembersVisible(true);
}); });
return; return;
} }
}, []); }, []);
@ -86,9 +91,10 @@ export const GroupsView: FC<{}> = props =>
<GroupsContextProvider value={ { groupsState, dispatchGroupsState } }> <GroupsContextProvider value={ { groupsState, dispatchGroupsState } }>
<GroupsMessageHandler /> <GroupsMessageHandler />
<div className="nitro-groups"> <div className="nitro-groups">
<GroupCreatorView isVisible={ isCreatorVisible } onClose={ () => setIsCreatorVisible(false) } /> <GroupCreatorView isVisible={ isCreatorVisible } onClose={ () => setCreatorVisible(false) } />
<GroupManagerView /> <GroupManagerView />
<GroupMembersView groupId={ groupMembersId } levelId={ groupMembersLevel } onClose={ closeMembers } /> { isMembersVisible &&
<GroupMembersView groupId={ currentGroupId } levelId={ currentGroupLevelId } setLevelId={ setCurrentGroupLevelId } onClose={ closeMembers } /> }
<GroupInformationStandaloneView /> <GroupInformationStandaloneView />
</div> </div>
</GroupsContextProvider> </GroupsContextProvider>

View File

@ -1,7 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { GroupAdminGiveComposer, GroupAdminTakeComposer, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupMemberParser, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembersParser, GroupRank, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer'; import { GroupAdminGiveComposer, GroupAdminTakeComposer, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupMemberParser, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembersParser, GroupRank, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
import classNames from 'classnames'; import classNames from 'classnames';
import { FC, KeyboardEvent, useCallback, useEffect, useState } from 'react'; import { Dispatch, FC, SetStateAction, useCallback, useEffect, useState } from 'react';
import { GetSessionDataManager, GetUserProfile, LocalizeText } from '../../../../api'; import { GetSessionDataManager, GetUserProfile, LocalizeText } from '../../../../api';
import { Base, Button, Column, Flex, Grid, Text } from '../../../../common'; import { Base, Button, Column, Flex, Grid, Text } from '../../../../common';
import { BatchUpdates, CreateMessageHook, SendMessageHook } from '../../../../hooks'; import { BatchUpdates, CreateMessageHook, SendMessageHook } from '../../../../hooks';
@ -14,66 +14,29 @@ interface GroupMembersViewProps
{ {
groupId: number; groupId: number;
levelId: number; levelId: number;
setLevelId: Dispatch<SetStateAction<number>>;
onClose: () => void; onClose: () => void;
} }
export const GroupMembersView: FC<GroupMembersViewProps> = props => export const GroupMembersView: FC<GroupMembersViewProps> = props =>
{ {
const { groupId = null, levelId = null, onClose = null } = props; const { groupId = -1, levelId = -1, setLevelId = null, onClose = null } = props;
const [ pageData, setPageData ] = useState<GroupMembersParser>(null); const [ pageData, setPageData ] = useState<GroupMembersParser>(null);
const [ pageId, setPageId ] = useState<number>(-1);
const [ searchQuery, setSearchQuery ] = useState<string>(''); const [ searchQuery, setSearchQuery ] = useState<string>('');
const [ searchLevelId, setSearchLevelId ] = useState<number>(3);
const [ totalPages, setTotalPages ] = useState<number>(0); const [ totalPages, setTotalPages ] = useState<number>(0);
const [ removingMemberName, setRemovingMemberName ] = useState<string>(null); const [ removingMemberName, setRemovingMemberName ] = useState<string>(null);
const searchMembers = useCallback((pageId: number, newLevelId?: number) => const refreshMembers = useCallback(() =>
{ {
if(!groupId) return; if((groupId === -1) || (levelId === -1) || (pageId === -1)) return;
SendMessageHook(new GroupMembersComposer(groupId, pageId, searchQuery, ((newLevelId !== undefined) ? newLevelId : searchLevelId))); SendMessageHook(new GroupMembersComposer(groupId, pageId, searchQuery, levelId));
}, [ groupId, searchLevelId, searchQuery ]); }, [ groupId, levelId, pageId, searchQuery ]);
const onGroupMembersEvent = useCallback((event: GroupMembersEvent) => const previousPage = () => setPageId(prevValue => (prevValue - 1));
{
const parser = event.getParser();
BatchUpdates(() => const nextPage = () => setPageId(prevValue => (prevValue + 1));
{
setPageData(null);
setPageData(parser);
setSearchLevelId(parser.level);
setTotalPages(Math.ceil(parser.totalMembersCount / parser.pageSize));
});
}, []);
CreateMessageHook(GroupMembersEvent, onGroupMembersEvent);
const onGroupConfirmMemberRemoveEvent = useCallback((event: GroupConfirmMemberRemoveEvent) =>
{
const parser = event.getParser();
NotificationUtilities.confirm(LocalizeText(((parser.furnitureCount > 0) ? 'group.kickconfirm.desc' : 'group.kickconfirm_nofurni.desc'), [ 'user', 'amount' ], [ removingMemberName, parser.furnitureCount.toString() ]), () =>
{
SendMessageHook(new GroupRemoveMemberComposer(pageData.groupId, parser.userId));
searchMembers(pageData.pageIndex);
}, null);
setRemovingMemberName(null);
}, [ pageData, removingMemberName, searchMembers ]);
CreateMessageHook(GroupConfirmMemberRemoveEvent, onGroupConfirmMemberRemoveEvent);
const selectSearchLevelId = (level: number) =>
{
setSearchLevelId(level);
searchMembers(0, level);
}
const previousPage = () => searchMembers((pageData.pageIndex - 1));
const nextPage = () => searchMembers((pageData.pageIndex + 1));
const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => ((event.key === 'Enter') && searchMembers(pageData.pageIndex));
const getRankDescription = (member: GroupMemberParser) => const getRankDescription = (member: GroupMemberParser) =>
{ {
@ -96,7 +59,7 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
if(member.rank !== GroupRank.ADMIN) SendMessageHook(new GroupAdminGiveComposer(pageData.groupId, member.id)); if(member.rank !== GroupRank.ADMIN) SendMessageHook(new GroupAdminGiveComposer(pageData.groupId, member.id));
else SendMessageHook(new GroupAdminTakeComposer(pageData.groupId, member.id)); else SendMessageHook(new GroupAdminTakeComposer(pageData.groupId, member.id));
searchMembers(pageData.pageIndex); refreshMembers();
} }
const acceptMembership = (member: GroupMemberParser) => const acceptMembership = (member: GroupMemberParser) =>
@ -104,7 +67,8 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
if(member.rank !== GroupRank.REQUESTED) return; if(member.rank !== GroupRank.REQUESTED) return;
SendMessageHook(new GroupMembershipAcceptComposer(pageData.groupId, member.id)); SendMessageHook(new GroupMembershipAcceptComposer(pageData.groupId, member.id));
searchMembers(pageData.pageIndex);
refreshMembers();
} }
const removeMemberOrDeclineMembership = (member: GroupMemberParser) => const removeMemberOrDeclineMembership = (member: GroupMemberParser) =>
@ -112,7 +76,8 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
if(member.rank === GroupRank.REQUESTED) if(member.rank === GroupRank.REQUESTED)
{ {
SendMessageHook(new GroupMembershipDeclineComposer(pageData.groupId, member.id)); SendMessageHook(new GroupMembershipDeclineComposer(pageData.groupId, member.id));
searchMembers(pageData.pageIndex);
refreshMembers();
return; return;
} }
@ -121,21 +86,52 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
SendMessageHook(new GroupConfirmRemoveMemberComposer(pageData.groupId, member.id)); SendMessageHook(new GroupConfirmRemoveMemberComposer(pageData.groupId, member.id));
} }
useEffect(() => const onGroupMembersEvent = useCallback((event: GroupMembersEvent) =>
{ {
const parser = event.getParser();
BatchUpdates(() => BatchUpdates(() =>
{ {
setPageData(null); setPageData(parser);
setSearchQuery(''); //setSearchLevelId(parser.level);
setSearchLevelId(0); setTotalPages(Math.ceil(parser.totalMembersCount / parser.pageSize));
}); });
}, []);
if(!groupId) return; CreateMessageHook(GroupMembersEvent, onGroupMembersEvent);
if(levelId !== null) setSearchLevelId(levelId); const onGroupConfirmMemberRemoveEvent = useCallback((event: GroupConfirmMemberRemoveEvent) =>
{
const parser = event.getParser();
searchMembers(0, levelId); NotificationUtilities.confirm(LocalizeText(((parser.furnitureCount > 0) ? 'group.kickconfirm.desc' : 'group.kickconfirm_nofurni.desc'), [ 'user', 'amount' ], [ removingMemberName, parser.furnitureCount.toString() ]), () =>
}, [ groupId, levelId, searchMembers ]); {
SendMessageHook(new GroupRemoveMemberComposer(pageData.groupId, parser.userId));
refreshMembers();
}, null);
setRemovingMemberName(null);
}, [ pageData, removingMemberName, refreshMembers ]);
CreateMessageHook(GroupConfirmMemberRemoveEvent, onGroupConfirmMemberRemoveEvent);
useEffect(() =>
{
setPageId(0);
}, [ groupId, levelId, searchQuery ]);
useEffect(() =>
{
})
useEffect(() =>
{
if((groupId === -1) || (levelId === -1) || (pageId === -1)) return;
SendMessageHook(new GroupMembersComposer(groupId, pageId, searchQuery, levelId));
}, [ groupId, levelId, pageId, searchQuery ]);
if(!groupId || !pageData) return null; if(!groupId || !pageData) return null;
@ -148,8 +144,8 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
<BadgeImageView badgeCode={ pageData.badge } isGroup={ true } className="mx-auto d-block"/> <BadgeImageView badgeCode={ pageData.badge } isGroup={ true } className="mx-auto d-block"/>
</Flex> </Flex>
<Column fullWidth gap={ 1 }> <Column fullWidth gap={ 1 }>
<input type="text" className="form-control form-control-sm w-100" placeholder={ LocalizeText('group.members.searchinfo') } value={ searchQuery } onChange={ (e) => setSearchQuery(e.target.value) } onBlur={ () => searchMembers(pageData.pageIndex) } onKeyDown={ onKeyDown } /> <input type="text" className="form-control form-control-sm w-100" placeholder={ LocalizeText('group.members.searchinfo') } value={ searchQuery } onChange={ event => setSearchQuery(event.target.value) } />
<select className="form-select form-select-sm w-100" value={ searchLevelId } onChange={ (e) => selectSearchLevelId(Number(e.target.value)) }> <select className="form-select form-select-sm w-100" value={ levelId } onChange={ event => setLevelId(parseInt(event.target.value)) }>
<option value="0">{ LocalizeText('group.members.search.all') }</option> <option value="0">{ LocalizeText('group.members.search.all') }</option>
<option value="1">{ LocalizeText('group.members.search.admins') }</option> <option value="1">{ LocalizeText('group.members.search.admins') }</option>
<option value="2">{ LocalizeText('group.members.search.pending') }</option> <option value="2">{ LocalizeText('group.members.search.pending') }</option>

View File

@ -36,7 +36,7 @@ export const GroupTabSettingsView: FC<{}> = props =>
{ STATES.map((state, index) => { STATES.map((state, index) =>
{ {
return ( return (
<Flex alignItems="center" gap={ 1 }> <Flex key={ index } alignItems="center" gap={ 1 }>
<input className="form-check-input" type="radio" name="groupState" checked={ (groupState === index) } onChange={ event => setState(index) } /> <input className="form-check-input" type="radio" name="groupState" checked={ (groupState === index) } onChange={ event => setState(index) } />
<Column gap={ 0 }> <Column gap={ 0 }>
<Flex gap={ 1 }> <Flex gap={ 1 }>