add dialogs frfr

This commit is contained in:
Michael Fatemi 2021-08-11 19:50:42 -04:00
parent 8ad8726780
commit 97268397d6
13 changed files with 118 additions and 53 deletions

View File

@ -84,11 +84,11 @@ export default function EventCreator({ group }: { group: IGroup }) {
]); ]);
return ( return (
<UISecondaryBox style={{ textAlign: 'center' }}> <UISecondaryBox style={{ textAlign: 'center', minWidth: '25rem' }}>
<h1 style={{ textAlign: 'center', marginBottom: '0.5rem' }}> <h3 style={{ textAlign: 'center', marginBottom: '0.5rem' }}>
Create Event Create Event
</h1> </h3>
<h3 style={{ textAlign: 'center', marginTop: '0.5rem' }}>{group.name}</h3> <h4 style={{ textAlign: 'center', marginTop: '0.5rem' }}>{group.name}</h4>
Name Name
<UITextInput value={name} onChangeText={setName} disabled={creating} /> <UITextInput value={name} onChangeText={setName} disabled={creating} />
<br /> <br />

View File

@ -1,5 +1,6 @@
import { useContext } from 'react'; import { useContext } from 'react';
import { GroupContext } from '../Group/Group'; import { GroupContext } from '../Group/Group';
import UIDialogShell from '../UI/UIDialogShell';
import UIPressable from '../UI/UIPressable'; import UIPressable from '../UI/UIPressable';
import useToggle from '../useToggle'; import useToggle from '../useToggle';
import EventCreator from './EventCreator'; import EventCreator from './EventCreator';
@ -12,10 +13,9 @@ export default function EventCreatorLink() {
<> <>
<UIPressable onClick={toggle}>Create Event</UIPressable> <UIPressable onClick={toggle}>Create Event</UIPressable>
{open && ( {open && (
<> <UIDialogShell onClose={toggle}>
<br />
<EventCreator group={group} /> <EventCreator group={group} />
</> </UIDialogShell>
)} )}
</> </>
); );

View File

@ -30,7 +30,14 @@ export default function Group({ id }: { id: number }) {
useEffect(() => { useEffect(() => {
setLoading(true); setLoading(true);
getGroup(id) getGroup(id)
.then(setGroup) .then((group) => {
// @ts-ignore
if ('status' in group && group.status === 'error') {
setGroup(null);
} else {
setGroup(group);
}
})
.finally(() => setLoading(false)); .finally(() => setLoading(false));
}, [id, setGroup]); }, [id, setGroup]);
@ -54,7 +61,7 @@ export default function Group({ id }: { id: number }) {
style={{ style={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
minWidth: '10rem', minWidth: '15rem',
}} }}
> >
<h1>{group.name}</h1> <h1>{group.name}</h1>

View File

@ -1,6 +1,7 @@
import { useCallback, useContext, useMemo, useState } from 'react'; import { useCallback, useContext, useMemo, useState } from 'react';
import { addGroupAdmin, removeGroupAdmin } from '../api'; import { addGroupAdmin, removeGroupAdmin } from '../api';
import { useMe } from '../hooks'; import { useMe } from '../hooks';
import UIDialogShell from '../UI/UIDialogShell';
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';
@ -47,9 +48,14 @@ export default function GroupMembersLink() {
<> <>
<UIPressable onClick={handleClick}>Members</UIPressable> <UIPressable onClick={handleClick}>Members</UIPressable>
{open && ( {open && (
<> <UIDialogShell onClose={() => setOpen(false)}>
<br /> <UISecondaryBox
<UISecondaryBox style={{ width: '100%', textAlign: 'center' }}> style={{
textAlign: 'center',
backgroundColor: '#fdfdfd',
}}
cancelClicks
>
<h3>Members</h3> <h3>Members</h3>
{group.users.map(({ name, id }) => ( {group.users.map(({ name, id }) => (
@ -71,7 +77,7 @@ export default function GroupMembersLink() {
<GroupInviteCode /> <GroupInviteCode />
</UISecondaryBox> </UISecondaryBox>
</> </UIDialogShell>
)} )}
</> </>
); );

View File

@ -9,6 +9,8 @@ export default function GroupSettings({ group }: { group: IGroup }) {
const [deletionSuccessful, setDeletionSuccessful] = const [deletionSuccessful, setDeletionSuccessful] =
useState<boolean | null>(null); useState<boolean | null>(null);
const [confirmingDeletion, setConfirmingDeletion] = useState(false);
const onClickedDelete = useCallback(() => { const onClickedDelete = useCallback(() => {
deleteGroup(group.id) deleteGroup(group.id)
.then(({ status }) => { .then(({ status }) => {
@ -19,12 +21,29 @@ export default function GroupSettings({ group }: { group: IGroup }) {
}); });
}, [group.id]); }, [group.id]);
const confirmDeletion = useCallback(() => {
setConfirmingDeletion(false);
onClickedDelete();
}, [onClickedDelete]);
const cancelDeletion = useCallback(() => {
setConfirmingDeletion(false);
}, [setConfirmingDeletion]);
return ( return (
<UISecondaryBox style={{ width: '100%', textAlign: 'center' }}> <UISecondaryBox style={{ textAlign: 'center', minWidth: '20rem' }}>
<h1>Settings</h1> <h3>Settings</h3>
{deletionSuccessful !== true && ( {deletionSuccessful !== true &&
<UIPressable onClick={onClickedDelete}>Delete Group</UIPressable> (confirmingDeletion ? (
)} <>
<UIPressable onClick={confirmDeletion}>Confirm</UIPressable>
<UIPressable onClick={cancelDeletion}>Cancel</UIPressable>
</>
) : (
<UIPressable onClick={() => setConfirmingDeletion(true)}>
Delete Group
</UIPressable>
))}
{deletionSuccessful !== null && {deletionSuccessful !== null &&
(deletionSuccessful ? ( (deletionSuccessful ? (
<span> <span>

View File

@ -1,4 +1,5 @@
import { useContext } from 'react'; import { useContext } from 'react';
import UIDialogShell from '../UI/UIDialogShell';
import UIPressable from '../UI/UIPressable'; import UIPressable from '../UI/UIPressable';
import useToggle from '../useToggle'; import useToggle from '../useToggle';
import { GroupContext } from './Group'; import { GroupContext } from './Group';
@ -12,10 +13,9 @@ export default function GroupSettingsLink() {
<> <>
<UIPressable onClick={toggle}>Settings</UIPressable> <UIPressable onClick={toggle}>Settings</UIPressable>
{open && ( {open && (
<> <UIDialogShell onClose={toggle}>
<br />
<GroupSettings group={group} /> <GroupSettings group={group} />
</> </UIDialogShell>
)} )}
</> </>
); );

View File

@ -28,7 +28,7 @@ export default function GroupCreator() {
const buttonEnabled = name.length > 0 && !creating; const buttonEnabled = name.length > 0 && !creating;
return ( return (
<UISecondaryBox style={{ width: '100%', boxSizing: 'border-box' }}> <UISecondaryBox style={{ minWidth: '25rem' }}>
<h3 style={{ textAlign: 'center' }}>Create Group</h3> <h3 style={{ textAlign: 'center' }}>Create Group</h3>
Name Name
<UITextInput onChangeText={setName} value={name} /> <UITextInput onChangeText={setName} value={name} />

View File

@ -1,25 +1,20 @@
import GroupCreator from './GroupCreator'; import UIButton from '../UI/UIButton';
import UIDialogShell from '../UI/UIDialogShell';
import useToggle from '../useToggle'; import useToggle from '../useToggle';
import GroupCreator from './GroupCreator';
export default function GroupCreatorLink() { export default function GroupCreatorLink() {
const [open, toggle] = useToggle(false); const [open, toggle] = useToggle(false);
return ( return (
<div style={{ width: '100%', textAlign: 'center' }}> <div style={{ width: '100%', textAlign: 'center' }}>
<div <UIButton onClick={toggle} style={{ backgroundColor: '#f3f3f3' }}>
style={{
cursor: 'pointer',
userSelect: 'none',
}}
onClick={toggle}
>
Create Group Create Group
</div> </UIButton>
{open && ( {open && (
<> <UIDialogShell onClose={toggle}>
<br />
<GroupCreator /> <GroupCreator />
</> </UIDialogShell>
)} )}
</div> </div>
); );

View File

@ -2,7 +2,6 @@ import { useCallback, useEffect, useState } from 'react';
import { joinGroup, resolveCode } from './api'; import { joinGroup, resolveCode } from './api';
import UIButton from './UI/UIButton'; import UIButton from './UI/UIButton';
import UIPressable from './UI/UIPressable'; import UIPressable from './UI/UIPressable';
import UISecondaryBox from './UI/UISecondaryBox';
import UITextInput from './UI/UITextInput'; import UITextInput from './UI/UITextInput';
import useToggle from './useToggle'; import useToggle from './useToggle';
@ -11,19 +10,21 @@ export type GroupPreview = {
id: number; id: number;
}; };
function GroupJoiner() { export function GroupJoiner() {
const [code, setCode] = useState(''); const [code, setCode] = useState('');
const [joining, setJoining] = useState(false); const [joining, setJoining] = useState(false);
const [group, setGroup] = useState<GroupPreview | null>(null); const [group, setGroup] = useState<GroupPreview | null>(null);
useEffect(() => { useEffect(() => {
const initialCode = code; if (code) {
resolveCode(code).then((group) => { const initialCode = code;
if (code === initialCode) { resolveCode(code).then((group) => {
setGroup(group); if (code === initialCode) {
} setGroup(group);
}); }
});
}
}, [code]); }, [code]);
const join = useCallback(() => { const join = useCallback(() => {
@ -44,10 +45,13 @@ function GroupJoiner() {
const buttonEnabled = code.length > 0 && !joining; const buttonEnabled = code.length > 0 && !joining;
return ( return (
<UISecondaryBox style={{ width: '100%', textAlign: 'center' }}> <div style={{ display: 'flex', flexDirection: 'column' }}>
<h3>Join Group</h3> <span style={{ fontSize: '0.875rem' }}>Join group with code:</span>
Code <UITextInput
<UITextInput value={code} onChangeText={setCode} /> value={code}
onChangeText={setCode}
style={{ border: '2px solid grey' }}
/>
{group && ( {group && (
<> <>
<br /> <br />
@ -62,7 +66,7 @@ function GroupJoiner() {
</UIButton> </UIButton>
</> </>
)} )}
</UISecondaryBox> </div>
); );
} }

View File

@ -1,8 +1,8 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { getGroups } from '../api'; import { getGroups } from '../api';
import { IGroup } from '../types';
import GroupCreatorLink from '../GroupCreator/GroupCreatorLink'; import GroupCreatorLink from '../GroupCreator/GroupCreatorLink';
import GroupJoinerLink from '../GroupJoinerLink'; import { GroupJoiner } from '../GroupJoinerLink';
import { IGroup } from '../types';
import GroupList from './GroupList'; import GroupList from './GroupList';
export default function Groups() { export default function Groups() {
@ -21,7 +21,7 @@ export default function Groups() {
}} }}
> >
<h1 style={{ textAlign: 'center' }}>Groups</h1> <h1 style={{ textAlign: 'center' }}>Groups</h1>
<GroupJoinerLink /> <GroupJoiner />
<br /> <br />
<GroupCreatorLink /> <GroupCreatorLink />
<br /> <br />

View File

@ -0,0 +1,23 @@
export default function UIDialogShell({
children,
onClose,
}: {
children: React.ReactNode;
onClose: () => void;
}) {
return (
<div
style={{
position: 'fixed',
zIndex: 100,
inset: 0,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
onClick={onClose}
>
{children}
</div>
);
}

View File

@ -13,9 +13,11 @@ const baseStyle: CSSProperties = {
export default function UISecondaryBox({ export default function UISecondaryBox({
children, children,
style, style,
cancelClicks = true,
}: { }: {
children: ReactNode; children: ReactNode;
style?: CSSProperties; style?: CSSProperties;
cancelClicks?: boolean;
}) { }) {
const computedStyle = useMemo(() => { const computedStyle = useMemo(() => {
if (!style) { if (!style) {
@ -23,5 +25,12 @@ export default function UISecondaryBox({
} }
return { ...baseStyle, ...style }; return { ...baseStyle, ...style };
}, [style]); }, [style]);
return <div style={computedStyle}>{children}</div>; return (
<div
style={computedStyle}
{...(cancelClicks ? { onClick: (e) => e.stopPropagation() } : {})}
>
{children}
</div>
);
} }

View File

@ -1,4 +1,4 @@
import { useCallback } from 'react'; import { CSSProperties, useCallback } from 'react';
const baseStyle = { const baseStyle = {
marginTop: '0.5em', marginTop: '0.5em',
@ -13,10 +13,12 @@ export default function UITextInput({
value, value,
disabled = false, disabled = false,
onChangeText, onChangeText,
style,
}: { }: {
value: string; value: string;
disabled?: boolean; disabled?: boolean;
onChangeText: (text: string) => void; onChangeText: (text: string) => void;
style?: CSSProperties;
}) { }) {
const onChange = useCallback( const onChange = useCallback(
(e) => onChangeText(e.target.value), (e) => onChangeText(e.target.value),
@ -24,7 +26,7 @@ export default function UITextInput({
); );
return ( return (
<input <input
style={baseStyle} style={style ? { ...baseStyle, ...style } : baseStyle}
value={value} value={value}
disabled={disabled} disabled={disabled}
onChange={onChange} onChange={onChange}