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 { createContext, useEffect, useState } from 'react';
|
||||||
import { getGroup } from '../api';
|
import { getGroup } from '../api';
|
||||||
import EventCreatorLink from '../EventCreator/EventCreatorLink';
|
import EventCreatorLink from '../EventCreator/EventCreatorLink';
|
||||||
import EventStream from '../EventStream';
|
import EventStream from '../EventStream';
|
||||||
|
import { useMe } from '../hooks';
|
||||||
import { IGroup } from '../types';
|
import { IGroup } from '../types';
|
||||||
import UILink from '../UI/UILink';
|
import UILink from '../UI/UILink';
|
||||||
import useImmutable from '../useImmutable';
|
import useImmutable from '../useImmutable';
|
||||||
|
@ -13,6 +15,7 @@ const DEFAULT_GROUP = (): IGroup => ({
|
||||||
name: '',
|
name: '',
|
||||||
users: [],
|
users: [],
|
||||||
events: [],
|
events: [],
|
||||||
|
admins: [],
|
||||||
joinCode: null,
|
joinCode: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,6 +24,7 @@ export const GroupContext = createContext({ group: DEFAULT_GROUP() });
|
||||||
export default function Group({ id }: { id: number }) {
|
export default function Group({ id }: { id: number }) {
|
||||||
const [group, setGroup] = useImmutable<IGroup | null>(null);
|
const [group, setGroup] = useImmutable<IGroup | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const me = useMe();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
@ -29,6 +33,14 @@ export default function Group({ id }: { id: number }) {
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}, [id, setGroup]);
|
}, [id, setGroup]);
|
||||||
|
|
||||||
|
const isAdmin = useMemo(() => {
|
||||||
|
if (!group) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return group.admins.some((a) => a.id === me?.id);
|
||||||
|
}, [group, me?.id]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <h1>Loading...</h1>;
|
return <h1>Loading...</h1>;
|
||||||
}
|
}
|
||||||
|
@ -48,8 +60,12 @@ export default function Group({ id }: { id: number }) {
|
||||||
<br />
|
<br />
|
||||||
<GroupMembersLink />
|
<GroupMembersLink />
|
||||||
<br />
|
<br />
|
||||||
<GroupSettingsLink />
|
{isAdmin && (
|
||||||
<br />
|
<>
|
||||||
|
<GroupSettingsLink />
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<EventCreatorLink />
|
<EventCreatorLink />
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { useCallback, useContext, useState } from 'react';
|
import { useCallback, useContext, useState } from 'react';
|
||||||
import { lightgrey } from '../../lib/colors';
|
import { lightgrey } from '../../lib/colors';
|
||||||
import { generateCode, resetCode } from '../api';
|
import { generateCode, resetCode } from '../api';
|
||||||
|
import { useMe } from '../hooks';
|
||||||
import UIButton from '../UI/UIButton';
|
import UIButton from '../UI/UIButton';
|
||||||
import { GroupContext } from './Group';
|
import { GroupContext } from './Group';
|
||||||
|
|
||||||
export default function GroupInviteCodeGenerator() {
|
export default function GroupInviteCode() {
|
||||||
const { group } = useContext(GroupContext);
|
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 [shown, setShown] = useState(false);
|
||||||
|
|
||||||
const generateJoinCode = useCallback(() => {
|
const generateJoinCode = useCallback(() => {
|
||||||
|
@ -34,44 +43,50 @@ export default function GroupInviteCodeGenerator() {
|
||||||
</code>{' '}
|
</code>{' '}
|
||||||
(click to show/hide)
|
(click to show/hide)
|
||||||
</span>
|
</span>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
{isAdmin && (
|
||||||
<UIButton
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
onClick={resetJoinCode}
|
<UIButton
|
||||||
style={{
|
onClick={resetJoinCode}
|
||||||
backgroundColor: lightgrey,
|
style={{
|
||||||
margin: '0.5rem',
|
backgroundColor: lightgrey,
|
||||||
flex: 1,
|
margin: '0.5rem',
|
||||||
}}
|
flex: 1,
|
||||||
>
|
}}
|
||||||
Reset
|
>
|
||||||
</UIButton>
|
Reset
|
||||||
<UIButton
|
</UIButton>
|
||||||
onClick={generateJoinCode}
|
<UIButton
|
||||||
style={{
|
onClick={generateJoinCode}
|
||||||
backgroundColor: lightgrey,
|
style={{
|
||||||
margin: '0.5rem',
|
backgroundColor: lightgrey,
|
||||||
flex: 1,
|
margin: '0.5rem',
|
||||||
}}
|
flex: 1,
|
||||||
>
|
}}
|
||||||
Regenerate
|
>
|
||||||
</UIButton>
|
Regenerate
|
||||||
</div>
|
</UIButton>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
This group has no way for new members to join.
|
This group has no way for new members to join.
|
||||||
<UIButton
|
{isAdmin ? (
|
||||||
onClick={generateJoinCode}
|
<UIButton
|
||||||
style={{
|
onClick={generateJoinCode}
|
||||||
backgroundColor: lightgrey,
|
style={{
|
||||||
marginTop: '0.5rem',
|
backgroundColor: lightgrey,
|
||||||
marginBottom: '0.5rem',
|
marginTop: '0.5rem',
|
||||||
}}
|
marginBottom: '0.5rem',
|
||||||
>
|
}}
|
||||||
Generate a code
|
>
|
||||||
</UIButton>
|
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 UIPressable from '../UI/UIPressable';
|
||||||
import UISecondaryBox from '../UI/UISecondaryBox';
|
import UISecondaryBox from '../UI/UISecondaryBox';
|
||||||
import { GroupContext } from './Group';
|
import { GroupContext } from './Group';
|
||||||
import GroupInviteCodeGenerator from './GroupInviteCodeGenerator';
|
import GroupInviteCode from './GroupInviteCode';
|
||||||
|
|
||||||
export default function GroupMembersLink() {
|
export default function GroupMembersLink() {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const { group } = useContext(GroupContext);
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -20,12 +52,24 @@ export default function GroupMembersLink() {
|
||||||
<UISecondaryBox style={{ width: '100%', textAlign: 'center' }}>
|
<UISecondaryBox style={{ width: '100%', textAlign: 'center' }}>
|
||||||
<h1>Members</h1>
|
<h1>Members</h1>
|
||||||
|
|
||||||
{group.users.map(({ name }) => (
|
{group.users.map(({ name, id }) => (
|
||||||
<span key={name}>{name}</span>
|
<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 />
|
<br />
|
||||||
|
|
||||||
<GroupInviteCodeGenerator />
|
<GroupInviteCode />
|
||||||
</UISecondaryBox>
|
</UISecondaryBox>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -145,6 +145,22 @@ export async function createGroup(name: string): Promise<{ id: number }> {
|
||||||
return { id };
|
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() {
|
export async function getNotifications() {
|
||||||
return await get('/users/@me/received_requests_and_invites');
|
return await get('/users/@me/received_requests_and_invites');
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,10 @@ export type IGroup = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}[];
|
}[];
|
||||||
|
admins: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
joinCode: string | null;
|
joinCode: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user