QualificationsPage: FormDialog refactor

This commit is contained in:
Dawid Wysokiński 2021-03-13 13:23:11 +01:00
parent d09704f5e8
commit 19d43b96ba
2 changed files with 44 additions and 37 deletions

View File

@ -1,10 +1,10 @@
import { useEffect, useMemo } from 'react'; import { useEffect } from 'react';
import { Controller, useFieldArray, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { omit, pick } from 'lodash'; import { omit, pick } from 'lodash';
import useProfessionAutocomplete from './FormDialog.useProfessionAutocomplete.js'; import useProfessionAutocomplete from './FormDialog.useProfessionAutocomplete.js';
import { FORMULAS, MAX_NAME_LENGTH } from './constants'; import { FORMULAS, MAX_NAME_LENGTH } from './constants';
import { Maybe, Qualification, QualificationInput } from 'libs/graphql/types'; import { Maybe, Qualification, QualificationInput } from 'libs/graphql/types';
import { ExtendedProfession, Input } from './types'; import { Input } from './types';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import { import {
@ -42,43 +42,18 @@ const FormDialog = ({
setValue, setValue,
formState: { isSubmitting }, formState: { isSubmitting },
} = useForm<Input>({}); } = useForm<Input>({});
const { fields: selectedProfessions } = useFieldArray<
ExtendedProfession,
'key'
>({
control,
name: 'professions',
keyName: 'key',
});
const { const {
professions, professions,
loading, loading,
isLoadingSuggestions, isLoadingSuggestions,
suggestions,
setSearch, setSearch,
autocompleteOptions,
selectedProfessions,
} = useProfessionAutocomplete({ } = useProfessionAutocomplete({
qualificationID: qualification?.id, qualificationID: qualification?.id,
omit: selectedProfessions.map(profession => profession?.id ?? 0), control: control,
}); });
const classes = useStyles(); const classes = useStyles();
const autocompleteOptions:
| typeof selectedProfessions
| typeof suggestions = useMemo(() => {
return [
...suggestions
.filter(
profession =>
!selectedProfessions.some(
otherProfession => otherProfession.id === profession.id
)
)
.map(p => ({ ...p, disabled: false })),
...selectedProfessions.map(p => ({
...p,
disabled: true,
})),
];
}, [suggestions, selectedProfessions]);
useEffect(() => { useEffect(() => {
reset({ reset({
@ -86,7 +61,7 @@ const FormDialog = ({
}); });
}, [professions, reset]); }, [professions, reset]);
const prepateDataBeforeSave = (data: Input): QualificationInput => { const prepareDataBeforeSave = (data: Input): QualificationInput => {
return { return {
...pick(data, ['name', 'description', 'formula', 'code']), ...pick(data, ['name', 'description', 'formula', 'code']),
associateProfession: data.professions associateProfession: data.professions
@ -109,7 +84,7 @@ const FormDialog = ({
}; };
const _onSubmit = async (data: Input) => { const _onSubmit = async (data: Input) => {
const success = await onSubmit(prepateDataBeforeSave(data)); const success = await onSubmit(prepareDataBeforeSave(data));
if (success) { if (success) {
onClose(); onClose();
} }
@ -183,7 +158,7 @@ const FormDialog = ({
loading={isLoadingSuggestions} loading={isLoadingSuggestions}
value={selectedProfessions} value={selectedProfessions}
getOptionDisabled={option => !!option.disabled} getOptionDisabled={option => !!option.disabled}
onChange={(_, opts, reason) => { onChange={(_, opts) => {
setValue( setValue(
'professions', 'professions',
opts.map(profession => omit(profession, 'key')) opts.map(profession => omit(profession, 'key'))

View File

@ -1,5 +1,6 @@
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useApolloClient, useQuery } from '@apollo/client'; import { useApolloClient, useQuery } from '@apollo/client';
import { Control, useFieldArray } from 'react-hook-form';
import { useDebounce } from 'react-use'; import { useDebounce } from 'react-use';
import { QUERY_PROFESSIONS } from './queries'; import { QUERY_PROFESSIONS } from './queries';
import { import {
@ -12,15 +13,23 @@ import { ExtendedProfession } from './types';
export interface Options { export interface Options {
qualificationID?: Maybe<Scalars['ID']>; qualificationID?: Maybe<Scalars['ID']>;
omit?: Scalars['ID'][]; control: Control;
} }
const useProfessionAutocomplete = ({ qualificationID, omit = [] }: Options) => { const useProfessionAutocomplete = ({ qualificationID, control }: Options) => {
const [suggestions, setSuggestions] = useState<ExtendedProfession[]>([]); const [suggestions, setSuggestions] = useState<ExtendedProfession[]>([]);
const [isLoadingSuggestions, setIsLoadingSuggestions] = useState<boolean>( const [isLoadingSuggestions, setIsLoadingSuggestions] = useState<boolean>(
false false
); );
const [search, setSearch] = useState<string>(''); const [search, setSearch] = useState<string>('');
const { fields: selectedProfessions } = useFieldArray<
ExtendedProfession,
'key'
>({
control,
name: 'professions',
keyName: 'key',
});
const client = useApolloClient(); const client = useApolloClient();
const { data, loading } = useQuery< const { data, loading } = useQuery<
Pick<Query, 'professions'>, Pick<Query, 'professions'>,
@ -35,6 +44,24 @@ const useProfessionAutocomplete = ({ qualificationID, omit = [] }: Options) => {
}, },
}); });
const professions = useMemo(() => data?.professions.items ?? [], [data]); const professions = useMemo(() => data?.professions.items ?? [], [data]);
const autocompleteOptions:
| typeof selectedProfessions
| typeof suggestions = useMemo(() => {
return [
...suggestions
.filter(
profession =>
!selectedProfessions.some(
otherProfession => otherProfession.id === profession.id
)
)
.map(p => ({ ...p, disabled: false })),
...selectedProfessions.map(p => ({
...p,
disabled: true,
})),
];
}, [suggestions, selectedProfessions]);
const loadSuggestions = async (search: string) => { const loadSuggestions = async (search: string) => {
setIsLoadingSuggestions(true); setIsLoadingSuggestions(true);
@ -46,7 +73,10 @@ const useProfessionAutocomplete = ({ qualificationID, omit = [] }: Options) => {
query: QUERY_PROFESSIONS, query: QUERY_PROFESSIONS,
fetchPolicy: 'no-cache', fetchPolicy: 'no-cache',
variables: { variables: {
filter: { nameIEQ: '%' + search + '%', idNEQ: omit }, filter: {
nameIEQ: '%' + search + '%',
idNEQ: selectedProfessions.map(profession => profession.id ?? 0),
},
limit: 10, limit: 10,
}, },
}); });
@ -74,6 +104,8 @@ const useProfessionAutocomplete = ({ qualificationID, omit = [] }: Options) => {
suggestions, suggestions,
setSearch, setSearch,
search, search,
autocompleteOptions,
selectedProfessions,
}; };
}; };