diff --git a/src/features/QualificationsPage/QualificationsPage.tsx b/src/features/QualificationsPage/QualificationsPage.tsx index a362048..1864be4 100644 --- a/src/features/QualificationsPage/QualificationsPage.tsx +++ b/src/features/QualificationsPage/QualificationsPage.tsx @@ -200,7 +200,7 @@ const QualificationsPage = () => { open={ dialogType === DialogType.Create || dialogType === DialogType.Edit } - qualification={qualificationBeingEdited as QualificationInput} + qualification={qualificationBeingEdited} onSubmit={handleFormDialogSubmit} onClose={() => setDialogType(DialogType.None)} /> diff --git a/src/features/QualificationsPage/components/FormDialog/FormDialog.tsx b/src/features/QualificationsPage/components/FormDialog/FormDialog.tsx index af034c6..568ec63 100644 --- a/src/features/QualificationsPage/components/FormDialog/FormDialog.tsx +++ b/src/features/QualificationsPage/components/FormDialog/FormDialog.tsx @@ -1,12 +1,15 @@ -import { useState } from 'react'; -import { useForm, Controller } from 'react-hook-form'; -import { pick } from 'lodash'; -import { MAX_NAME_LENGTH, FORMULAS } from './constants'; -import { QualificationInput } from 'libs/graphql/types'; +import { useEffect, useMemo } from 'react'; +import { Controller, useFieldArray, useForm } from 'react-hook-form'; +import { omit, pick } from 'lodash'; +import useProfessionAutocomplete from './FormDialog.useProfessionAutocomplete.js'; +import { FORMULAS, MAX_NAME_LENGTH } from './constants'; +import { Maybe, Qualification, QualificationInput } from 'libs/graphql/types'; +import { ExtendedProfession, Input } from './types'; import { makeStyles } from '@material-ui/core/styles'; import { Button, + CircularProgress, Dialog, DialogActions, DialogContent, @@ -15,9 +18,10 @@ import { MenuItem, TextField, } from '@material-ui/core'; +import { Autocomplete } from '@material-ui/lab'; export interface FormDialogProps extends Pick { - qualification?: QualificationInput; + qualification?: Maybe; onClose: () => void; onSubmit: (input: QualificationInput) => Promise | boolean; } @@ -34,20 +38,78 @@ const FormDialog = ({ handleSubmit, errors, control, - } = useForm({}); - const [isSubmitting, setIsSubmitting] = useState(false); + reset, + setValue, + formState: { isSubmitting }, + } = useForm({}); + const { fields: selectedProfessions } = useFieldArray< + ExtendedProfession, + 'key' + >({ + control, + name: 'professions', + keyName: 'key', + }); + const { + professions, + loading, + isLoadingSuggestions, + suggestions, + setSearch, + } = useProfessionAutocomplete({ + qualificationID: qualification?.id, + omit: selectedProfessions.map(profession => profession?.id ?? 0), + }); const classes = useStyles(); - - const _onSubmit = async (data: QualificationInput) => { - setIsSubmitting(true); - const filtered = editMode - ? pick( - data, - Object.keys(data).filter(key => data[key as keyof QualificationInput]) + const autocompleteOptions: + | typeof selectedProfessions + | typeof suggestions = useMemo(() => { + return [ + ...suggestions + .filter( + profession => + !selectedProfessions.some( + otherProfession => otherProfession.id === profession.id + ) ) - : data; - const success = await onSubmit(filtered); - setIsSubmitting(false); + .map(p => ({ ...p, disabled: false })), + ...selectedProfessions.map(p => ({ + ...p, + disabled: true, + })), + ]; + }, [suggestions, selectedProfessions]); + + useEffect(() => { + reset({ + professions, + }); + }, [professions, reset]); + + const prepateDataBeforeSave = (data: Input): QualificationInput => { + return { + ...pick(data, ['name', 'description', 'formula', 'code']), + associateProfession: data.professions + .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), + }; + }; + + const _onSubmit = async (data: Input) => { + const success = await onSubmit(prepateDataBeforeSave(data)); if (success) { onClose(); } @@ -113,6 +175,56 @@ const FormDialog = ({ inputRef={register} multiline /> + {!loading && ( + option?.name ?? ''} + loading={isLoadingSuggestions} + value={selectedProfessions} + getOptionDisabled={option => !!option.disabled} + onChange={(_, opts, reason) => { + setValue( + 'professions', + opts.map(profession => omit(profession, 'key')) + ); + }} + getOptionSelected={(option, value) => + option && value && option.id === value.id + } + renderInput={params => ( + { + setSearch(e.target.value); + }} + InputProps={{ + ...params.InputProps, + endAdornment: ( + <> + {isLoadingSuggestions ? ( + + ) : null} + + ), + }} + /> + )} + /> + )} + {selectedProfessions.map((profession, index) => { + return ( + + ); + })}