brf/client/admin/components/admission_form.tsx

91 lines
2.4 KiB
TypeScript

import { h, type FunctionComponent, type TargetedSubmitEvent } from 'preact'
import { useCallback } from 'preact/hooks'
import rek, { type FetchError } from 'rek'
import useRequestState from '../../shared/hooks/use_request_state.ts'
import serializeForm from '../../shared/utils/serialize_form.ts'
import Button from './button.tsx'
import Checkbox from './checkbox.tsx'
import Input from './input.tsx'
import Message from './message.tsx'
import sutil from './utility.module.scss'
const AdmissionForm: FunctionComponent<{
admission?: ANY
onCancel?: ANY
onCreate?: ANY
onUpdate?: ANY
roles?: ANY[]
}> = ({ admission, onCancel, onCreate, onUpdate, roles }) => {
const [{ error, pending, success }, actions] = useRequestState<FetchError>()
const create = useCallback(async (e: TargetedSubmitEvent<HTMLFormElement>) => {
e.preventDefault()
actions.pending()
try {
const form = e.currentTarget
const result = await rek[admission ? 'patch' : 'post'](
`/api/admissions${admission ? '/' + admission.id : ''}`,
serializeForm(form),
)
actions.success()
if (admission) {
onUpdate?.(result)
} else {
form.reset()
onCreate?.(result)
}
} catch (err) {
actions.error(err as FetchError)
}
}, [])
return (
<form onSubmit={create}>
{success && (
<Message type='success' dismiss={actions.reset}>
Admission {admission ? 'updated' : 'created'}!
</Message>
)}
{error && (
<Message type='error' dismiss={actions.reset}>
{error.status || 500} {error.body?.message || error.message}
</Message>
)}
<Input name='regex' label='Regex' type='text' defaultValue={admission?.regex} required />
{roles && (
<div>
{roles.map((role) => (
<Checkbox
key={role.id}
name='roles'
label={role.name}
value={role.id}
defaultChecked={!!admission?.roles.find((r: ANY) => r.id === role.id)}
/>
))}
</div>
)}
<div className={sutil.row}>
<Button disabled={pending} type='submit'>
{admission ? 'Update' : 'Create'}
</Button>
{onCancel && (
<Button disabled={pending} onClick={onCancel} type='button'>
Cancel
</Button>
)}
</div>
</form>
)
}
export default AdmissionForm