diff --git a/frontend/src/components/group/GroupCreateBox.tsx b/frontend/src/components/group/GroupCreateBox.tsx index 0bcde31..01f2896 100644 --- a/frontend/src/components/group/GroupCreateBox.tsx +++ b/frontend/src/components/group/GroupCreateBox.tsx @@ -4,6 +4,7 @@ import {useAuthorizationContext} from "../../contexts/authorization" import {useCacheContext} from "../../contexts/cache" import {ManagedResource, ManagedViewSet} from "../../hooks/useManagedViewSet" import {SophonResearchGroup} from "../../types/SophonTypes" +import {Validators} from "../../utils/Validators" /** @@ -24,15 +25,66 @@ export interface GroupCreateBoxProps { } +/** + * A {@link Box} to create or edit a {@link SophonResearchGroup}. + * + * @constructor + */ export function GroupCreateBox({viewSet, resource}: GroupCreateBoxProps): JSX.Element | null { const authorization = useAuthorizationContext() const cache = useCacheContext() const name = - useFormState(resource?.value.name ?? "", val => val.length > 0 ? true : undefined) + useFormState( + resource?.value.name ?? "", + Validators.notZeroLength, + ) const description = - useFormState(resource?.value.description ?? "", val => val.length > 0 ? true : undefined) + useFormState( + resource?.value.description ?? "", + Validators.notZeroLength, + ) + + const members = + useFormState( + resource?.value.members ?? [], + Validators.alwaysValid, + ) + + const access = + useFormState<"OPEN" | "MANUAL" | undefined>( + resource?.value.access ?? undefined, + Validators.notEmpty, + ) + + const slug = + React.useMemo( + () => resource ? resource.value.slug : name.value.replaceAll(/[^A-Za-z0-9-]/g, "-").toLowerCase(), + [resource, name], + ) + + const canAdministrate = + React.useMemo( + () => { + if(resource) { + if(!authorization) { + return false + } + if(!authorization.state.user) { + return false + } + if(authorization.state.user.id !== resource.value.owner) { + return false + } + return true + } + else { + return true + } + }, + [authorization, resource], + ) const membersOptions: { [key: string]: number } | undefined = React.useMemo( @@ -46,17 +98,7 @@ export function GroupCreateBox({viewSet, resource}: GroupCreateBoxProps): JSX.El [authorization, cache], ) - const members = - useFormState(resource?.value.members ?? [], arr => arr.length > 0 ? true : undefined) - - const access = - useFormState<"OPEN" | "MANUAL" | undefined>(resource?.value.access ?? undefined, val => ( - val?.length - ) ? true : undefined) - - const slug = name.value.replaceAll(/[^A-Za-z0-9-]/g, "-").toLowerCase() - - const onSubmit = + const applyChanges = React.useCallback( async () => { if(resource) { @@ -68,8 +110,8 @@ export function GroupCreateBox({viewSet, resource}: GroupCreateBoxProps): JSX.El access: access.value, }) } - else if(viewSet) { - await viewSet.create({ + else { + await viewSet!.create({ name: name.value, slug: slug, description: description.value, @@ -81,34 +123,25 @@ export function GroupCreateBox({viewSet, resource}: GroupCreateBoxProps): JSX.El [viewSet, resource, name, slug, description, members, access], ) - const canAdministrate = - React.useMemo( - () => !resource || - ( - authorization && authorization.state.user && authorization.state.user.id === resource.value.owner - ), - [authorization, resource], - ) - - const canSubmit = + const canApply = React.useMemo( () => name.validity === true && access.validity === true && Boolean(authorization?.state.user?.username), [name, access, authorization], ) - if(!authorization?.state.token) { - return null - } - if(!( - viewSet || resource - )) { - return null - } - if(!canAdministrate) { - return null - } + const hasError = + React.useMemo( + () => viewSet?.operationError || resource?.error, + [viewSet, resource], + ) - const hasError = viewSet?.operationError || resource?.error + if(!authorization?.state.token || + !( + viewSet || resource + ) || + !canAdministrate) { + return null + } return ( @@ -136,14 +169,15 @@ export function GroupCreateBox({viewSet, resource}: GroupCreateBoxProps): JSX.El /> {resource ? "Edit" : "Create"} diff --git a/frontend/src/utils/Validators.ts b/frontend/src/utils/Validators.ts new file mode 100644 index 0000000..63503fe --- /dev/null +++ b/frontend/src/utils/Validators.ts @@ -0,0 +1,25 @@ +import {Validity} from "@steffo/bluelib-react/dist/types" + + +export class Validators { + static alwaysValid(val: T): Validity { + return true + } + + static notEmpty(val: T): Validity { + if(!val) { + return undefined + } + return true + } + + static notZeroLength(val: T): Validity { + if(!val) { + return undefined + } + if(val.length === 0) { + return undefined + } + return true + } +}