QualificationsPage: split FormDialog into two components

This commit is contained in:
Dawid Wysokiński 2021-04-11 11:15:56 +02:00
parent 57500d8c6e
commit 89cc8fded8
2 changed files with 144 additions and 154 deletions

View File

@ -1,5 +1,4 @@
import { useEffect } from 'react';
import { useUpdateEffect } from 'react-use';
import { Controller, useForm } from 'react-hook-form';
import { omit, pick } from 'lodash';
import useProfessionAutocomplete from './FormDialog.useProfessionAutocomplete.js';
@ -27,20 +26,15 @@ export interface FormDialogProps extends Pick<DialogProps, 'open'> {
onSubmit: (input: QualificationInput) => Promise<boolean> | boolean;
}
const FormDialog = ({
open,
onClose,
qualification,
onSubmit,
}: FormDialogProps) => {
const Form = ({ onClose, qualification, onSubmit }: FormDialogProps) => {
const editMode = Boolean(qualification);
const {
register,
handleSubmit,
errors,
control,
reset,
setValue,
reset,
formState: { isSubmitting },
} = useForm<Input>({});
const {
@ -60,31 +54,27 @@ const FormDialog = ({
professions,
});
}, [professions, reset]);
useUpdateEffect(() => {
if (!open && selectedProfessions.length > 0) {
setValue('professions', []);
}
}, [open]);
const prepareDataBeforeSave = (data: Input): QualificationInput => {
return {
...pick(data, ['name', 'description', 'formula', 'code']),
associateProfession: data.professions
.filter(
?.filter(
profession =>
!professions.some(
otherProfession => otherProfession.id === profession.id
)
)
.map(profession => profession.id),
dissociateProfession: professions
.filter(
profession =>
!data.professions.some(
otherProfession => otherProfession.id === profession.id
)
)
.map(profession => profession.id),
dissociateProfession: (data.professions
? professions.filter(
profession =>
!data.professions.some(
otherProfession => otherProfession.id === profession.id
)
)
: professions
).map(profession => profession.id),
};
};
@ -96,136 +86,138 @@ const FormDialog = ({
};
return (
<Dialog
open={open}
onClose={isSubmitting ? undefined : onClose}
fullWidth
maxWidth="xs"
>
<form onSubmit={handleSubmit(_onSubmit)}>
<DialogTitle>
{editMode ? 'Edycja kwalifikacji' : 'Tworzenie kwalifikacji'}
</DialogTitle>
<DialogContent className={classes.dialogContent}>
<TextField
fullWidth
label="Nazwa kwalifikacji"
name="name"
defaultValue={qualification?.name}
inputRef={register({
required: 'Te pole jest wymagane.',
maxLength: {
value: MAX_NAME_LENGTH,
message: `Maksymalna długość nazwy kwalifikacji to ${MAX_NAME_LENGTH} znaki.`,
},
})}
error={!!errors.name?.message}
helperText={errors.name?.message ?? ''}
/>
<TextField
fullWidth
label="Oznaczenie kwalifikacji"
name="code"
defaultValue={qualification?.code}
inputRef={register({
required: 'Te pole jest wymagane.',
})}
error={!!errors.code?.message}
helperText={errors.code?.message ?? ''}
/>
<Controller
name="formula"
defaultValue={qualification?.formula ?? FORMULAS[0]}
control={control}
as={
<TextField select fullWidth label="Formuła">
{FORMULAS.map(formula => (
<MenuItem key={formula} value={formula}>
{formula}
</MenuItem>
))}
</TextField>
}
/>
<TextField
fullWidth
label="Opis"
name="description"
defaultValue={qualification?.description}
inputRef={register}
multiline
/>
{!loading && (
<Autocomplete
multiple
options={autocompleteOptions}
getOptionLabel={option => option?.name ?? ''}
loading={isLoadingSuggestions}
value={selectedProfessions}
getOptionDisabled={option => !!option.disabled}
onChange={(_, opts) => {
setValue(
'professions',
opts.map(profession => omit(profession, 'key'))
);
}}
getOptionSelected={(option, value) =>
option && value && option.id === value.id
}
renderInput={params => (
<TextField
{...params}
variant="standard"
label="Zawody"
onChange={e => {
setSearch(e.target.value);
}}
InputProps={{
...params.InputProps,
endAdornment: (
<>
{isLoadingSuggestions ? (
<CircularProgress color="inherit" size={20} />
) : null}
</>
),
}}
/>
)}
/>
)}
{selectedProfessions.map((profession, index) => {
return (
<input
type="hidden"
key={profession.id}
name={`professions[${index}].id`}
ref={register({ valueAsNumber: true })}
defaultValue={profession.id}
/>
);
<form onSubmit={handleSubmit(_onSubmit)}>
<DialogTitle>
{editMode ? 'Edycja kwalifikacji' : 'Tworzenie kwalifikacji'}
</DialogTitle>
<DialogContent className={classes.dialogContent}>
<TextField
fullWidth
label="Nazwa kwalifikacji"
name="name"
defaultValue={qualification?.name}
inputRef={register({
required: 'Te pole jest wymagane.',
maxLength: {
value: MAX_NAME_LENGTH,
message: `Maksymalna długość nazwy kwalifikacji to ${MAX_NAME_LENGTH} znaki.`,
},
})}
</DialogContent>
<DialogActions>
<Button
color="secondary"
type="button"
variant="contained"
onClick={onClose}
disabled={isSubmitting}
>
Anuluj
</Button>
<Button
type="submit"
color="primary"
variant="contained"
disabled={isSubmitting}
>
{editMode ? 'Zapisz' : 'Utwórz'}
</Button>
</DialogActions>
</form>
error={!!errors.name?.message}
helperText={errors.name?.message ?? ''}
/>
<TextField
fullWidth
label="Oznaczenie kwalifikacji"
name="code"
defaultValue={qualification?.code}
inputRef={register({
required: 'Te pole jest wymagane.',
})}
error={!!errors.code?.message}
helperText={errors.code?.message ?? ''}
/>
<Controller
name="formula"
defaultValue={qualification?.formula ?? FORMULAS[0]}
control={control}
as={
<TextField select fullWidth label="Formuła">
{FORMULAS.map(formula => (
<MenuItem key={formula} value={formula}>
{formula}
</MenuItem>
))}
</TextField>
}
/>
<TextField
fullWidth
label="Opis"
name="description"
defaultValue={qualification?.description}
inputRef={register}
multiline
/>
{!loading && (
<Autocomplete
multiple
options={autocompleteOptions}
getOptionLabel={option => option?.name ?? ''}
loading={isLoadingSuggestions}
value={selectedProfessions}
getOptionDisabled={option => !!option.disabled}
onChange={(_, opts) => {
setValue(
'professions',
opts.map(profession => omit(profession, 'key'))
);
}}
getOptionSelected={(option, value) =>
option && value && option.id === value.id
}
renderInput={params => (
<TextField
{...params}
variant="standard"
label="Zawody"
onChange={e => {
setSearch(e.target.value);
}}
InputProps={{
...params.InputProps,
endAdornment: (
<>
{isLoadingSuggestions ? (
<CircularProgress color="inherit" size={20} />
) : null}
</>
),
}}
/>
)}
/>
)}
{selectedProfessions.map((profession, index) => {
return (
<input
type="hidden"
key={profession.id}
name={`professions[${index}].id`}
ref={register({ valueAsNumber: true })}
defaultValue={profession.id}
/>
);
})}
</DialogContent>
<DialogActions>
<Button
color="secondary"
type="button"
variant="contained"
onClick={onClose}
disabled={isSubmitting}
>
Anuluj
</Button>
<Button
type="submit"
color="primary"
variant="contained"
disabled={isSubmitting}
>
{editMode ? 'Zapisz' : 'Utwórz'}
</Button>
</DialogActions>
</form>
);
};
const FormDialog = (props: FormDialogProps) => {
const { open, onClose } = props;
return (
<Dialog open={open} onClose={onClose} fullWidth maxWidth="xs">
<Form {...props} />
</Dialog>
);
};

View File

@ -44,9 +44,7 @@ const useProfessionAutocomplete = ({ qualificationID, control }: Options) => {
},
});
const professions = useMemo(() => data?.professions.items ?? [], [data]);
const autocompleteOptions:
| typeof selectedProfessions
| typeof suggestions = useMemo(() => {
const autocompleteOptions: typeof selectedProfessions = useMemo(() => {
return [
...suggestions
.filter(