FormDialog refactor
This commit is contained in:
parent
72c0cac8b2
commit
7e33fbecf4
|
@ -1,10 +1,15 @@
|
|||
import { useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { Controller, useFieldArray, useForm } from 'react-hook-form';
|
||||
import { omit, pick } from 'lodash';
|
||||
import { polishPlurals } from 'polish-plurals';
|
||||
import useProfessionAutocomplete from './FormDialog.useProfessionAutocomplete.js';
|
||||
import useSuggestions from './FormDialog.useSuggestions';
|
||||
import { FORMULAS, MAX_NAME_LENGTH } from './constants';
|
||||
import { Maybe, Qualification, QualificationInput } from 'libs/graphql/types';
|
||||
import {
|
||||
Maybe,
|
||||
Profession,
|
||||
Qualification,
|
||||
QualificationInput,
|
||||
} from 'libs/graphql/types';
|
||||
import { Input } from './types';
|
||||
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
@ -20,6 +25,7 @@ import {
|
|||
TextField,
|
||||
} from '@material-ui/core';
|
||||
import { Autocomplete } from '@material-ui/lab';
|
||||
import useProfessions from './FormDialog.useProfessions';
|
||||
|
||||
export interface FormDialogProps extends Pick<DialogProps, 'open'> {
|
||||
qualification?: Maybe<Qualification>;
|
||||
|
@ -39,17 +45,29 @@ const Form = ({ onClose, qualification, onSubmit }: FormDialogProps) => {
|
|||
formState: { isSubmitting },
|
||||
} = useForm<Input>({});
|
||||
const {
|
||||
professions,
|
||||
loading,
|
||||
isLoadingSuggestions,
|
||||
setSearch,
|
||||
autocompleteOptions,
|
||||
selectedProfessions,
|
||||
} = useProfessionAutocomplete({
|
||||
qualificationID: qualification?.id,
|
||||
control: control,
|
||||
});
|
||||
suggestions,
|
||||
search,
|
||||
} = useSuggestions();
|
||||
const { professions, loading } = useProfessions(qualification?.id);
|
||||
const classes = useStyles();
|
||||
const { fields: selectedProfessions } = useFieldArray<Profession, 'key'>({
|
||||
control,
|
||||
name: 'professions',
|
||||
keyName: 'key',
|
||||
});
|
||||
const autocompleteOptions: typeof selectedProfessions = useMemo(() => {
|
||||
return [
|
||||
...suggestions.filter(
|
||||
profession =>
|
||||
!selectedProfessions.some(
|
||||
otherProfession => otherProfession.id === profession.id
|
||||
)
|
||||
),
|
||||
...selectedProfessions,
|
||||
];
|
||||
}, [suggestions, selectedProfessions]);
|
||||
useEffect(() => {
|
||||
reset({
|
||||
professions,
|
||||
|
@ -152,7 +170,6 @@ const Form = ({ onClose, qualification, onSubmit }: FormDialogProps) => {
|
|||
getOptionLabel={option => option?.name ?? ''}
|
||||
loading={isLoadingSuggestions}
|
||||
value={selectedProfessions}
|
||||
getOptionDisabled={option => !!option.disabled}
|
||||
onChange={(_, opts) => {
|
||||
setValue(
|
||||
'professions',
|
||||
|
@ -162,14 +179,16 @@ const Form = ({ onClose, qualification, onSubmit }: FormDialogProps) => {
|
|||
getOptionSelected={(option, value) =>
|
||||
option && value && option.id === value.id
|
||||
}
|
||||
inputValue={search}
|
||||
onInputChange={(_, val, reason) => {
|
||||
console.log(reason);
|
||||
setSearch(val);
|
||||
}}
|
||||
renderInput={params => (
|
||||
<TextField
|
||||
{...params}
|
||||
variant="standard"
|
||||
label="Zawody"
|
||||
onChange={e => {
|
||||
setSearch(e.target.value);
|
||||
}}
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
import { useMemo, useState } from 'react';
|
||||
import { useApolloClient, useQuery } from '@apollo/client';
|
||||
import { Control, useFieldArray } from 'react-hook-form';
|
||||
import { useDebounce } from 'react-use';
|
||||
import { QUERY_PROFESSIONS } from './queries';
|
||||
import {
|
||||
Maybe,
|
||||
Query,
|
||||
QueryProfessionsArgs,
|
||||
Scalars,
|
||||
} from 'libs/graphql/types';
|
||||
import { ExtendedProfession } from './types';
|
||||
|
||||
export interface Options {
|
||||
qualificationID?: Maybe<Scalars['ID']>;
|
||||
control: Control;
|
||||
}
|
||||
|
||||
const useProfessionAutocomplete = ({ qualificationID, control }: Options) => {
|
||||
const [suggestions, setSuggestions] = useState<ExtendedProfession[]>([]);
|
||||
const [isLoadingSuggestions, setIsLoadingSuggestions] = useState<boolean>(
|
||||
false
|
||||
);
|
||||
const [search, setSearch] = useState<string>('');
|
||||
const { fields: selectedProfessions } = useFieldArray<
|
||||
ExtendedProfession,
|
||||
'key'
|
||||
>({
|
||||
control,
|
||||
name: 'professions',
|
||||
keyName: 'key',
|
||||
});
|
||||
const client = useApolloClient();
|
||||
const { data, loading } = useQuery<
|
||||
Pick<Query, 'professions'>,
|
||||
QueryProfessionsArgs
|
||||
>(QUERY_PROFESSIONS, {
|
||||
fetchPolicy: 'cache-and-network',
|
||||
skip: !qualificationID,
|
||||
variables: {
|
||||
filter: {
|
||||
qualificationID: [qualificationID ?? 0],
|
||||
},
|
||||
},
|
||||
});
|
||||
const professions = useMemo(() => data?.professions.items ?? [], [data]);
|
||||
const autocompleteOptions: typeof selectedProfessions = 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) => {
|
||||
setIsLoadingSuggestions(true);
|
||||
try {
|
||||
const { data } = await client.query<
|
||||
Pick<Query, 'professions'>,
|
||||
QueryProfessionsArgs
|
||||
>({
|
||||
query: QUERY_PROFESSIONS,
|
||||
fetchPolicy: 'no-cache',
|
||||
variables: {
|
||||
filter: {
|
||||
nameIEQ: '%' + search + '%',
|
||||
idNEQ: selectedProfessions.map(profession => profession.id ?? 0),
|
||||
},
|
||||
limit: 10,
|
||||
},
|
||||
});
|
||||
if (data.professions?.items) {
|
||||
setSuggestions(data.professions.items);
|
||||
}
|
||||
} catch (e) {}
|
||||
setIsLoadingSuggestions(false);
|
||||
};
|
||||
|
||||
useDebounce(
|
||||
() => {
|
||||
loadSuggestions(search);
|
||||
},
|
||||
500,
|
||||
[search]
|
||||
);
|
||||
|
||||
return {
|
||||
professions,
|
||||
loading: professions.length === 0 && loading,
|
||||
isLoadingSuggestions,
|
||||
suggestions,
|
||||
setSearch,
|
||||
search,
|
||||
autocompleteOptions,
|
||||
selectedProfessions,
|
||||
};
|
||||
};
|
||||
|
||||
export default useProfessionAutocomplete;
|
|
@ -0,0 +1,32 @@
|
|||
import { useMemo } from 'react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { QUERY_PROFESSIONS } from './queries';
|
||||
import {
|
||||
Maybe,
|
||||
Query,
|
||||
QueryProfessionsArgs,
|
||||
Scalars,
|
||||
} from 'libs/graphql/types';
|
||||
|
||||
const useProfessions = (qualificationID?: Maybe<Scalars['ID']>) => {
|
||||
const { data, loading } = useQuery<
|
||||
Pick<Query, 'professions'>,
|
||||
QueryProfessionsArgs
|
||||
>(QUERY_PROFESSIONS, {
|
||||
fetchPolicy: 'cache-and-network',
|
||||
skip: !qualificationID,
|
||||
variables: {
|
||||
filter: {
|
||||
qualificationID: [qualificationID ?? 0],
|
||||
},
|
||||
},
|
||||
});
|
||||
const professions = useMemo(() => data?.professions.items ?? [], [data]);
|
||||
|
||||
return {
|
||||
professions,
|
||||
loading: professions.length === 0 && loading,
|
||||
};
|
||||
};
|
||||
|
||||
export default useProfessions;
|
|
@ -0,0 +1,54 @@
|
|||
import { useState } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useDebounce } from 'react-use';
|
||||
import { QUERY_PROFESSIONS } from './queries';
|
||||
import { Profession, Query, QueryProfessionsArgs } from 'libs/graphql/types';
|
||||
|
||||
const useSuggestions = () => {
|
||||
const [suggestions, setSuggestions] = useState<Profession[]>([]);
|
||||
const [isLoadingSuggestions, setIsLoadingSuggestions] = useState<boolean>(
|
||||
false
|
||||
);
|
||||
const [search, setSearch] = useState<string>('');
|
||||
const client = useApolloClient();
|
||||
|
||||
const loadSuggestions = async (search: string) => {
|
||||
setIsLoadingSuggestions(true);
|
||||
try {
|
||||
const { data } = await client.query<
|
||||
Pick<Query, 'professions'>,
|
||||
QueryProfessionsArgs
|
||||
>({
|
||||
query: QUERY_PROFESSIONS,
|
||||
fetchPolicy: 'no-cache',
|
||||
variables: {
|
||||
filter: {
|
||||
nameIEQ: '%' + search + '%',
|
||||
},
|
||||
limit: 10,
|
||||
},
|
||||
});
|
||||
if (data.professions?.items) {
|
||||
setSuggestions(data.professions.items);
|
||||
}
|
||||
} catch (e) {}
|
||||
setIsLoadingSuggestions(false);
|
||||
};
|
||||
|
||||
useDebounce(
|
||||
() => {
|
||||
loadSuggestions(search);
|
||||
},
|
||||
500,
|
||||
[search]
|
||||
);
|
||||
|
||||
return {
|
||||
isLoadingSuggestions,
|
||||
suggestions,
|
||||
setSearch,
|
||||
search,
|
||||
};
|
||||
};
|
||||
|
||||
export default useSuggestions;
|
|
@ -1,12 +1,8 @@
|
|||
import { Profession, QualificationInput } from 'libs/graphql/types';
|
||||
|
||||
export type ExtendedProfession = Profession & {
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export type Input = Omit<
|
||||
QualificationInput,
|
||||
'associateProfession' | 'dissociateProfession'
|
||||
> & {
|
||||
professions: ExtendedProfession[];
|
||||
professions: Profession[];
|
||||
};
|
||||
|
|
Reference in New Issue