add group invite codes generator, resetor, etc.

This commit is contained in:
Michael Fatemi 2021-07-15 13:32:26 -04:00
parent 9bcc29ac13
commit 9bf4f4c568
8 changed files with 144 additions and 73 deletions

View File

@ -1,9 +1,11 @@
import EventCreator from './EventCreator'; import { useContext } from 'react';
import { IGroup } from '../types'; import { GroupContext } from '../Group/Group';
import useToggle from '../useToggle'; import useToggle from '../useToggle';
import EventCreator from './EventCreator';
export default function EventCreatorLink({ group }: { group: IGroup }) { export default function EventCreatorLink() {
const [open, toggle] = useToggle(false); const [open, toggle] = useToggle(false);
const { group } = useContext(GroupContext);
return ( return (
<div> <div>

View File

@ -1,38 +1,59 @@
import { createContext, useEffect } from 'react';
import { getGroup } from '../api';
import EventCreatorLink from '../EventCreator/EventCreatorLink'; import EventCreatorLink from '../EventCreator/EventCreatorLink';
import EventStream from '../EventStream'; import EventStream from '../EventStream';
import GroupSettingsLink from './GroupSettingsLink';
import { IGroup } from '../types'; import { IGroup } from '../types';
import UILink from '../UI/UILink'; import UILink from '../UI/UILink';
import useImmutable from '../useImmutable';
import GroupMembersLink from './GroupMembersLink'; import GroupMembersLink from './GroupMembersLink';
import GroupSettingsLink from './GroupSettingsLink';
const DEFAULT_GROUP = (): IGroup => ({
id: 0,
name: '',
users: [],
events: [],
joinCode: null,
});
export const GroupContext = createContext({ group: DEFAULT_GROUP() });
export default function Group({ id }: { id: number }) {
const [group, setGroup] = useImmutable<IGroup>(DEFAULT_GROUP());
useEffect(() => {
getGroup(id).then(setGroup);
}, [id, setGroup]);
export default function Group({ group }: { group: IGroup }) {
return ( return (
<div <GroupContext.Provider value={{ group }}>
style={{ <div
textAlign: 'center', style={{
maxWidth: '30rem', textAlign: 'center',
marginLeft: 'auto', maxWidth: '30rem',
marginRight: 'auto', marginLeft: 'auto',
}} marginRight: 'auto',
> }}
<h1>{group.name}</h1> >
<UILink href="/">Home</UILink> <h1>{group.name}</h1>
<br /> <UILink href="/">Home</UILink>
<br /> <br />
<GroupMembersLink group={group} /> <br />
<br /> <GroupMembersLink />
<GroupSettingsLink group={group} /> <br />
<br /> <GroupSettingsLink />
<EventCreatorLink group={group} /> <br />
<br /> <EventCreatorLink />
<br />
{group.events.length > 0 ? ( {group.events.length > 0 ? (
<EventStream events={group.events} /> <EventStream events={group.events} />
) : ( ) : (
<span> <span>
There are no events yet. Click 'create event' above to add one! There are no events yet. Click 'create event' above to add one!
</span> </span>
)} )}
</div> </div>
</GroupContext.Provider>
); );
} }

View File

@ -0,0 +1,72 @@
import { useCallback, useContext } from 'react';
import { lightgrey } from '../../lib/colors';
import { generateCode, resetCode } from '../api';
import UIButton from '../UI/UIButton';
import { GroupContext } from './Group';
export default function GroupInviteCodeGenerator() {
const { group } = useContext(GroupContext);
const generateJoinCode = useCallback(() => {
generateCode(group.id).then((code) => {
group.joinCode = code;
});
}, [group]);
const resetJoinCode = useCallback(() => {
resetCode(group.id).then((code) => {
group.joinCode = null;
});
}, [group]);
if (group.joinCode) {
return (
<>
<span>
Join this group with the code{' '}
<b>
<code>{group.joinCode}</code>
</b>
</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>
</>
);
} 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>
</>
);
}
}

View File

@ -1,11 +1,14 @@
import { useState } from 'react'; import { useContext, useState } from 'react';
import { IGroup } from '../types';
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 GroupInviteCodeGenerator from './GroupInviteCodeGenerator';
export default function GroupMembersLink({ group }: { group: IGroup }) { export default function GroupMembersLink() {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const { group } = useContext(GroupContext);
const handleClick = () => setOpen(!open); const handleClick = () => setOpen(!open);
return ( return (
@ -16,6 +19,9 @@ export default function GroupMembersLink({ group }: { group: IGroup }) {
<br /> <br />
<UISecondaryBox> <UISecondaryBox>
<h1>Members</h1> <h1>Members</h1>
<GroupInviteCodeGenerator />
{group.users.map(({ name }) => ( {group.users.map(({ name }) => (
<span key={name}>{name}</span> <span key={name}>{name}</span>
))} ))}

View File

@ -1,43 +1,8 @@
import { useEffect, useState } from 'react';
import { useParams } from 'react-router'; import { useParams } from 'react-router';
import { Link } from 'react-router-dom';
import { getGroup } from '../api';
import { IGroup } from '../types';
import Group from './Group'; import Group from './Group';
export default function GroupPage() { export default function GroupPage() {
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();
const [loading, setLoading] = useState(true);
const [group, setGroup] = useState<IGroup | null>(null);
useEffect(() => { return <Group id={+id} />;
if (isNaN(+id)) {
setLoading(false);
return;
}
async function load() {
setLoading(true);
getGroup(+id)
.then(setGroup)
.finally(() => setLoading(false));
}
load();
}, [id]);
if (!group && !loading) {
return (
<div style={{ textAlign: 'center' }}>
<h1>Group Not Found</h1>
<Link to="/">Home</Link>
</div>
);
}
if (!group) {
return null;
}
return <Group group={group} />;
} }

View File

@ -1,9 +1,11 @@
import { IGroup } from '../types'; import { useContext } from 'react';
import useToggle from '../useToggle'; import useToggle from '../useToggle';
import { GroupContext } from './Group';
import GroupSettings from './GroupSettings'; import GroupSettings from './GroupSettings';
export default function GroupSettingsLink({ group }: { group: IGroup }) { export default function GroupSettingsLink() {
const [open, toggle] = useToggle(false); const [open, toggle] = useToggle(false);
const { group } = useContext(GroupContext);
return ( return (
<div> <div>

View File

@ -166,7 +166,9 @@ export async function joinGroup(id: number, code: string) {
} }
export async function generateCode(groupId: number) { export async function generateCode(groupId: number) {
return await post('/groups/' + groupId + '/generate_code', {}); const { code } = await post(`/groups/${groupId}/generate_code`, {});
return code;
} }
export async function resetCode(groupId: number) { export async function resetCode(groupId: number) {

View File

@ -54,6 +54,7 @@ export type IGroup = {
id: number; id: number;
name: string; name: string;
}[]; }[];
joinCode: string | null;
}; };
/** /**