Skip to content

Commit

Permalink
Refactor admin registrate page
Browse files Browse the repository at this point in the history
Replace redux-form with react-final-form and clean up some of the routing and redux data fetching
  • Loading branch information
eikhr committed Oct 20, 2023
1 parent 90c6bbd commit eeae32c
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 149 deletions.
14 changes: 14 additions & 0 deletions app/components/Form/SubmitButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Button } from '@webkom/lego-bricks';
import { spySubmittable } from 'app/utils/formSpyUtils';
import type { ReactNode } from 'react';

type Props = {
children: ReactNode;
};

export const SubmitButton = ({ children }: Props) =>
spySubmittable((submittable) => (
<Button submit disabled={!submittable}>
{children}
</Button>
));
22 changes: 0 additions & 22 deletions app/routes/events/EventAdminRegisterRoute.ts

This file was deleted.

226 changes: 103 additions & 123 deletions app/routes/events/components/EventAdministrate/AdminRegister.tsx
Original file line number Diff line number Diff line change
@@ -1,131 +1,111 @@
import { Button } from '@webkom/lego-bricks';
import { Field } from 'redux-form';
import { waitinglistPoolId } from 'app/actions/EventActions';
import { legoForm, TextEditor, SelectInput } from 'app/components/Form';
import { RenderErrorMessage } from 'app/components/Form/Field';
import type { ID, EventPool, User } from 'app/models';
import type { FormProps } from 'react-redux';
import { LoadingIndicator } from '@webkom/lego-bricks';
import { Field } from 'react-final-form';
import { adminRegister, waitinglistPoolId } from 'app/actions/EventActions';
import { TextEditor, SelectInput } from 'app/components/Form';
import LegoFinalForm from 'app/components/Form/LegoFinalForm';
import SubmissionError from 'app/components/Form/SubmissionError';
import { SubmitButton } from 'app/components/Form/SubmitButton';
import { selectPoolsForEvent } from 'app/reducers/events';
import { useAppDispatch, useAppSelector } from 'app/store/hooks';
import type { DetailedEvent } from 'app/store/models/Event';
import type { AutocompleteUser } from 'app/store/models/User';
import { createValidator, required } from 'app/utils/validation';
import type { FormApi } from 'final-form';

type Props = {
eventId: ID;
adminRegister: (
arg0: ID,
arg1: ID,
arg2: ID,
arg3: string,
arg4: string
) => Promise<any>;
pools: Array<EventPool>;
} & FormProps;

const AdminRegister = ({
handleSubmit,
pools,
invalid,
pristine,
submitting,
error,
}: Props) => {
return (
<div
style={{
width: '400px',
}}
>
<form onSubmit={handleSubmit}>
<Field
placeholder="Begrunnelse"
label="Begrunnelse"
name="adminRegistrationReason"
component={TextEditor.Field}
/>
<Field
placeholder="Tilbakemelding"
label="Tilbakemelding"
name="feedback"
component={TextEditor.Field}
/>
<Field
name="pool"
component={SelectInput.Field}
placeholder="Pool"
label="Pool"
options={pools
.map((pool) => ({
value: pool.id,
label: pool.name,
}))
.concat([
{
value: waitinglistPoolId,
label: 'Venteliste',
},
])}
/>
<Field
name="user"
component={SelectInput.AutocompleteField}
filter={['users.user']}
placeholder="Bruker"
label="Bruker"
/>
<RenderErrorMessage error={error} />
<Button type="submit" disabled={invalid || pristine || submitting}>
Registrer
</Button>
</form>
</div>
);
type FormValues = {
user: AutocompleteUser;
pool: {
value: number;
label: string;
};
feedback: string;
adminRegistrationReason: string;
};

function validateForm(data) {
const errors = {};

if (!data.reason) {
errors.reason = 'Forklaring er påkrevet';
}
type Props = {
event: DetailedEvent;
};

if (!data.pool) {
errors.pool = 'Pool er påkrevet';
}
const AdminRegister = (props: Props) => {
const { event } = props;
const fetching = useAppSelector((state) => state.events.fetching);
const pools = useAppSelector((state) =>
selectPoolsForEvent(state, {
eventId: event.id,
})
);

if (!data.user) {
errors.user = 'Bruker er påkrevet';
}
const dispatch = useAppDispatch();
const onSubmit = async (values: FormValues, form: FormApi<FormValues>) => {
await dispatch(
adminRegister(
event.id,
values.user.id,
values.pool?.value,
values.feedback,
values.adminRegistrationReason
)
);
form.restart();
};

return errors;
}
return (
<LoadingIndicator loading={fetching}>
<LegoFinalForm onSubmit={onSubmit} validate={validate} subscription={{}}>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field
required
name="user"
component={SelectInput.AutocompleteField}
filter={['users.user']}
placeholder="Bruker"
label="Bruker"
/>
<Field
required
name="pool"
component={SelectInput.Field}
placeholder="Pool"
label="Pool"
options={pools
.map((pool) => ({
value: pool.id,
label: pool.name,
}))
.concat([
{
value: waitinglistPoolId,
label: 'Venteliste',
},
])}
/>
<Field
required
placeholder="Begrunnelse"
label="Begrunnelse"
name="adminRegistrationReason"
component={TextEditor.Field}
/>
<Field
placeholder="Tilbakemelding"
label="Melding til arrangør"
name="feedback"
component={TextEditor.Field}
/>
<SubmissionError />
<SubmitButton>Adminregistrer</SubmitButton>
</form>
)}
</LegoFinalForm>
</LoadingIndicator>
);
};

const onSubmit = (
{
user,
pool,
feedback,
adminRegistrationReason,
}: {
user: User;
pool: {
value: number;
label: string;
};
feedback: string;
adminRegistrationReason: string;
},
_,
{ reset, eventId, adminRegister }: Props
) =>
adminRegister(
eventId,
user.id,
pool?.value,
feedback,
adminRegistrationReason
).then(() => {
reset();
});
const validate = createValidator({
adminRegistrationReason: [required()],
pool: [required()],
user: [required()],
});

export default legoForm({
form: 'adminRegister',
validate: validateForm,
onSubmit,
})(AdminRegister);
export default AdminRegister;
6 changes: 2 additions & 4 deletions app/routes/events/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const EventAdministrateRoute = loadable(
const EventAttendeeRoute = loadable(() => import('./EventAttendeeRoute'));
const EventAllergiesRoute = loadable(() => import('./EventAllergiesRoute'));
const EventAdminRegisterRoute = loadable(
() => import('./EventAdminRegisterRoute')
() => import('./components/EventAdministrate/AdminRegister')
);
const EventAbacardRoute = loadable(() => import('./EventAbacardRoute'));
const PageNotFound = loadable(() => import('../pageNotFound'));
Expand Down Expand Up @@ -118,9 +118,7 @@ const eventRoute = ({
path={`${match.path}/admin-register`}
Component={EventAdminRegisterRoute}
passedProps={{
currentUser,
loggedIn,
...props,
event: props.event,
}}
/>
<RouteWrapper
Expand Down

0 comments on commit eeae32c

Please sign in to comment.