mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-16 00:50:18 -04:00
add admin stuff
This commit is contained in:
parent
c61f0aa914
commit
2acdca681a
|
@ -1,7 +1,9 @@
|
|||
import { useMemo } from 'react';
|
||||
import { createContext, useEffect, useState } from 'react';
|
||||
import { getGroup } from '../api';
|
||||
import EventCreatorLink from '../EventCreator/EventCreatorLink';
|
||||
import EventStream from '../EventStream';
|
||||
import { useMe } from '../hooks';
|
||||
import { IGroup } from '../types';
|
||||
import UILink from '../UI/UILink';
|
||||
import useImmutable from '../useImmutable';
|
||||
|
@ -13,6 +15,7 @@ const DEFAULT_GROUP = (): IGroup => ({
|
|||
name: '',
|
||||
users: [],
|
||||
events: [],
|
||||
admins: [],
|
||||
joinCode: null,
|
||||
});
|
||||
|
||||
|
@ -21,6 +24,7 @@ export const GroupContext = createContext({ group: DEFAULT_GROUP() });
|
|||
export default function Group({ id }: { id: number }) {
|
||||
const [group, setGroup] = useImmutable<IGroup | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const me = useMe();
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
|
@ -29,6 +33,14 @@ export default function Group({ id }: { id: number }) {
|
|||
.finally(() => setLoading(false));
|
||||
}, [id, setGroup]);
|
||||
|
||||
const isAdmin = useMemo(() => {
|
||||
if (!group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return group.admins.some((a) => a.id === me?.id);
|
||||
}, [group, me?.id]);
|
||||
|
||||
if (loading) {
|
||||
return <h1>Loading...</h1>;
|
||||
}
|
||||
|
@ -48,8 +60,12 @@ export default function Group({ id }: { id: number }) {
|
|||
<br />
|
||||
<GroupMembersLink />
|
||||
<br />
|
||||
<GroupSettingsLink />
|
||||
<br />
|
||||
{isAdmin && (
|
||||
<>
|
||||
<GroupSettingsLink />
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
<EventCreatorLink />
|
||||
</div>
|
||||
<br />
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
import { useMemo } from 'react';
|
||||
import { useCallback, useContext, useState } from 'react';
|
||||
import { lightgrey } from '../../lib/colors';
|
||||
import { generateCode, resetCode } from '../api';
|
||||
import { useMe } from '../hooks';
|
||||
import UIButton from '../UI/UIButton';
|
||||
import { GroupContext } from './Group';
|
||||
|
||||
export default function GroupInviteCodeGenerator() {
|
||||
export default function GroupInviteCode() {
|
||||
const { group } = useContext(GroupContext);
|
||||
|
||||
const me = useMe();
|
||||
|
||||
const isAdmin = useMemo(
|
||||
() => group.admins.some((a) => a.id === me?.id),
|
||||
[group.admins, me?.id]
|
||||
);
|
||||
|
||||
const [shown, setShown] = useState(false);
|
||||
|
||||
const generateJoinCode = useCallback(() => {
|
||||
|
@ -34,44 +43,50 @@ export default function GroupInviteCodeGenerator() {
|
|||
</code>{' '}
|
||||
(click to show/hide)
|
||||
</span>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<UIButton
|
||||
onClick={resetJoinCode}
|
||||
style={{
|
||||
backgroundColor: lightgrey,
|
||||
margin: '0.5rem',
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
Reset
|
||||
</UIButton>
|
||||
<UIButton
|
||||
onClick={generateJoinCode}
|
||||
style={{
|
||||
backgroundColor: lightgrey,
|
||||
margin: '0.5rem',
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
Regenerate
|
||||
</UIButton>
|
||||
</div>
|
||||
{isAdmin && (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<UIButton
|
||||
onClick={resetJoinCode}
|
||||
style={{
|
||||
backgroundColor: lightgrey,
|
||||
margin: '0.5rem',
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
Reset
|
||||
</UIButton>
|
||||
<UIButton
|
||||
onClick={generateJoinCode}
|
||||
style={{
|
||||
backgroundColor: lightgrey,
|
||||
margin: '0.5rem',
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
Regenerate
|
||||
</UIButton>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
This group has no way for new members to join.
|
||||
<UIButton
|
||||
onClick={generateJoinCode}
|
||||
style={{
|
||||
backgroundColor: lightgrey,
|
||||
marginTop: '0.5rem',
|
||||
marginBottom: '0.5rem',
|
||||
}}
|
||||
>
|
||||
Generate a code
|
||||
</UIButton>
|
||||
{isAdmin ? (
|
||||
<UIButton
|
||||
onClick={generateJoinCode}
|
||||
style={{
|
||||
backgroundColor: lightgrey,
|
||||
marginTop: '0.5rem',
|
||||
marginBottom: '0.5rem',
|
||||
}}
|
||||
>
|
||||
Generate a code
|
||||
</UIButton>
|
||||
) : (
|
||||
'Contact an admin to create a code'
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,15 +1,47 @@
|
|||
import { useContext, useState } from 'react';
|
||||
import { useCallback, useContext, useMemo, useState } from 'react';
|
||||
import { addGroupAdmin, removeGroupAdmin } from '../api';
|
||||
import { useMe } from '../hooks';
|
||||
import UIPressable from '../UI/UIPressable';
|
||||
import UISecondaryBox from '../UI/UISecondaryBox';
|
||||
import { GroupContext } from './Group';
|
||||
import GroupInviteCodeGenerator from './GroupInviteCodeGenerator';
|
||||
import GroupInviteCode from './GroupInviteCode';
|
||||
|
||||
export default function GroupMembersLink() {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { group } = useContext(GroupContext);
|
||||
const me = useMe();
|
||||
|
||||
const handleClick = () => setOpen(!open);
|
||||
const handleClick = useCallback(() => setOpen((o) => !o), []);
|
||||
|
||||
const adminIds = useMemo(
|
||||
() => new Set(group.admins.map((a) => a.id)),
|
||||
[group.admins]
|
||||
);
|
||||
|
||||
const addAdmin = useCallback(
|
||||
(adminId: number, adminName: string) => {
|
||||
addGroupAdmin(group.id, adminId).then(({ status }) => {
|
||||
if (status === 'success') {
|
||||
group.admins.push({ id: adminId, name: adminName });
|
||||
}
|
||||
});
|
||||
},
|
||||
[group.admins, group.id]
|
||||
);
|
||||
|
||||
const amIAdmin = me?.id ? adminIds.has(me.id) : false;
|
||||
|
||||
const removeAdmin = useCallback(
|
||||
(adminId: number) => {
|
||||
removeGroupAdmin(group.id, adminId).then((res) => {
|
||||
if (res.status === 'success') {
|
||||
group.admins = group.admins.filter((admin) => admin.id !== adminId);
|
||||
}
|
||||
});
|
||||
},
|
||||
[group]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -20,12 +52,24 @@ export default function GroupMembersLink() {
|
|||
<UISecondaryBox style={{ width: '100%', textAlign: 'center' }}>
|
||||
<h1>Members</h1>
|
||||
|
||||
{group.users.map(({ name }) => (
|
||||
<span key={name}>{name}</span>
|
||||
{group.users.map(({ name, id }) => (
|
||||
<span key={id}>
|
||||
{name} {adminIds.has(id) && ' (admin)'}{' '}
|
||||
{amIAdmin &&
|
||||
(adminIds.has(id) ? (
|
||||
<button onClick={() => removeAdmin(id)}>
|
||||
Remove as admin
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={() => addAdmin(id, name)}>
|
||||
Add as admin
|
||||
</button>
|
||||
))}
|
||||
</span>
|
||||
))}
|
||||
<br />
|
||||
|
||||
<GroupInviteCodeGenerator />
|
||||
<GroupInviteCode />
|
||||
</UISecondaryBox>
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -145,6 +145,22 @@ export async function createGroup(name: string): Promise<{ id: number }> {
|
|||
return { id };
|
||||
}
|
||||
|
||||
export async function addGroupAdmin(
|
||||
id: number,
|
||||
userId: number
|
||||
): Promise<{ status: 'success' | 'error' }> {
|
||||
const { status } = await post(`/groups/${id}/add_admin`, { userId });
|
||||
return { status };
|
||||
}
|
||||
|
||||
export async function removeGroupAdmin(
|
||||
id: number,
|
||||
userId: number
|
||||
): Promise<{ status: 'success' | 'error' }> {
|
||||
const { status } = await post(`/groups/${id}/remove_admin`, { userId });
|
||||
return { status };
|
||||
}
|
||||
|
||||
export async function getNotifications() {
|
||||
return await get('/users/@me/received_requests_and_invites');
|
||||
}
|
||||
|
|
|
@ -54,6 +54,10 @@ export type IGroup = {
|
|||
id: number;
|
||||
name: string;
|
||||
}[];
|
||||
admins: {
|
||||
id: number;
|
||||
name: string;
|
||||
}[];
|
||||
joinCode: string | null;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user