Pull request #1457: story(TEAMMSBMOB-20013): альтернативные сценарии
Merge in MCB_FE/mcb-platform-monorepo from story/TEAMMSBMOB-20013 to develop * commit '5c3bf72f251581dc630c4c6d8c2fad2102195ade': feat(TEAMMSBMOB-20013): правки feat(TEAMMSBMOB-20013): альтернативные сценарии feat(TEAMMSBMOB-20013): изм поведение модалки выбора организации, поиска feat(TEAMMSBMOB-20013): Изменение поиска контрагента
This commit is contained in:
+1
-1
@@ -1,3 +1,3 @@
|
||||
const symbolsForExcept = ['.', ',', 'e'];
|
||||
const symbolsForExcept = ['.', ',', 'e', '-', '+', 'E'];
|
||||
|
||||
export { symbolsForExcept };
|
||||
|
||||
+6
-10
@@ -6,7 +6,7 @@ import { Text } from '@fractal-ui/styling';
|
||||
import { Dropdown } from '@msb/fractal-ui-composites';
|
||||
import type { InputSize } from '@msb/fractal-ui-composites/src/input/types';
|
||||
import { Flex, MEDIA, useMediaQuery } from '@msb/shared';
|
||||
import { useFormState, useForm } from 'react-final-form';
|
||||
import { useFormState } from 'react-final-form';
|
||||
import { LOCALIZATION, symbolsForExcept } from '../constants';
|
||||
import * as S from './PartnerSearch.styled';
|
||||
import { Option } from './ui';
|
||||
@@ -56,21 +56,15 @@ const PartnerSearch = ({ partnerName, handleName, showInputFieldName, innField,
|
||||
ogrnField,
|
||||
});
|
||||
|
||||
const { change } = useForm();
|
||||
|
||||
const description = useMemo(() => {
|
||||
if (other[innField] && other[ogrnField]) return `ИНН: ${other[innField]}, ОГРН: ${other[ogrnField]}`;
|
||||
|
||||
if (isMobile) return LOCALIZATION.ORGANIZATION_SEARCH_MOBILE;
|
||||
}, [innField, isMobile, ogrnField, other]);
|
||||
|
||||
const handleSearch = useCallback(
|
||||
e => {
|
||||
onInput();
|
||||
change(partnerName, e.currentTarget.value);
|
||||
},
|
||||
[change, onInput, partnerName]
|
||||
);
|
||||
const handleSearch = useCallback(() => {
|
||||
onInput();
|
||||
}, [onInput]);
|
||||
|
||||
const ref = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -113,6 +107,8 @@ const PartnerSearch = ({ partnerName, handleName, showInputFieldName, innField,
|
||||
<Option
|
||||
key={option.value}
|
||||
dependentName={partnerName}
|
||||
innName={innField}
|
||||
ogrnName={ogrnField}
|
||||
option={option}
|
||||
onClick={onDropdownClick({ value: option.value, inn: option.inn, ogrn: option.ogrn })}
|
||||
/>
|
||||
|
||||
+9
-2
@@ -6,6 +6,8 @@ import * as S from './Option.styled';
|
||||
|
||||
interface Props {
|
||||
dependentName: string;
|
||||
innName: string;
|
||||
ogrnName: string;
|
||||
option: {
|
||||
value: string;
|
||||
label: string;
|
||||
@@ -15,18 +17,23 @@ interface Props {
|
||||
onClick(): void;
|
||||
}
|
||||
|
||||
const Option = ({ onClick, dependentName, option }: Props) => {
|
||||
const Option = ({ onClick, dependentName, option, innName, ogrnName }: Props) => {
|
||||
const { values } = useFormState();
|
||||
|
||||
const value = useMemo(() => values[dependentName], [dependentName, values]);
|
||||
|
||||
const inn = useMemo(() => values[innName], [innName, values]);
|
||||
const ogrn = useMemo(() => values[ogrnName], [ogrnName, values]);
|
||||
|
||||
const notBoldedLabel = useMemo(() => (option.label === value ? option.label : option.label.replace(value, '')), [option.label, value]);
|
||||
|
||||
const notBoldedInn = useMemo(() => (option.inn === value ? option.inn : trimFromStart(option.inn, value)), [option.inn, value]);
|
||||
const notBoldedOgrn = useMemo(() => (option.ogrn === value ? option.ogrn : trimFromStart(option.ogrn, value)), [option.ogrn, value]);
|
||||
|
||||
const selected = value === option.value && option.inn === inn && option.ogrn === ogrn;
|
||||
|
||||
return (
|
||||
<S.DropdownItemStyled selected={value === option.value} onClick={onClick}>
|
||||
<S.DropdownItemStyled selected={selected} onClick={onClick}>
|
||||
<Text.P1>
|
||||
<strong>{!option.inn.startsWith(value) && !option.ogrn.startsWith(value) && option.label !== value && value}</strong>
|
||||
{notBoldedLabel}
|
||||
|
||||
+18
-3
@@ -117,9 +117,24 @@ const usePartnerSearch = ({ organizations, partnerName, showInputFieldName, hand
|
||||
[batch, change, handleName, showInputFieldName]
|
||||
);
|
||||
|
||||
const onBlurNameField = useCallback(() => {
|
||||
setIsOpen(false);
|
||||
}, []);
|
||||
const onBlurNameField = useCallback(
|
||||
e => {
|
||||
setIsOpen(false);
|
||||
|
||||
if (
|
||||
!options.some(opt => opt.value.startsWith(e.event.target.value)) ||
|
||||
!options.some(opt => opt.inn.startsWith(e.event.target.value)) ||
|
||||
!options.some(opt => opt.ogrn.startsWith(e.event.target.value))
|
||||
) {
|
||||
batch(() => {
|
||||
change(innField, undefined);
|
||||
change(ogrnField, undefined);
|
||||
change(partnerName, undefined);
|
||||
});
|
||||
}
|
||||
},
|
||||
[batch, change, innField, ogrnField, options, partnerName]
|
||||
);
|
||||
|
||||
const onInput = useCallback(() => {
|
||||
setIsOpen(true);
|
||||
|
||||
+5
-1
@@ -2,4 +2,8 @@ const LOCALIZATION = {
|
||||
SUBSCRIBE: 'Подписка активна',
|
||||
};
|
||||
|
||||
export { LOCALIZATION };
|
||||
const MODAL_LOCALIZATION = {
|
||||
SELECT: 'Выбрать',
|
||||
};
|
||||
|
||||
export { LOCALIZATION, MODAL_LOCALIZATION };
|
||||
|
||||
+34
-9
@@ -1,9 +1,11 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Icon } from '@fractal-ui/library';
|
||||
import type { ModalButtonProps } from '@fractal-ui/overlays';
|
||||
import { Modal, Drawer } from '@fractal-ui/overlays';
|
||||
import { Dropdown } from '@msb/fractal-ui-composites';
|
||||
import { MEDIA, useMediaQuery } from '@msb/shared';
|
||||
import { useForm, useFormState } from 'react-final-form';
|
||||
import { MODAL_LOCALIZATION } from '../../constants';
|
||||
import { Option } from './Option';
|
||||
import * as S from './Organizations.styled';
|
||||
import { useOrganizations } from '@/shared/model';
|
||||
@@ -21,6 +23,14 @@ const Organizations = ({ textBefore, fieldName, title, onChange }: Props) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { change } = useForm();
|
||||
const { values } = useFormState();
|
||||
const [organizationId, setId] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!organizationId && values[fieldName]) {
|
||||
setId(values[fieldName]);
|
||||
}
|
||||
}, [organizationId, values, fieldName]);
|
||||
|
||||
const { organizationOptions, activeOrganizations } = useOrganizations();
|
||||
|
||||
const organization = useMemo(
|
||||
@@ -33,11 +43,26 @@ const Organizations = ({ textBefore, fieldName, title, onChange }: Props) => {
|
||||
|
||||
const onOptionClick = useCallback(
|
||||
(orgId: string) => () => {
|
||||
change(fieldName, orgId);
|
||||
onChange?.(orgId);
|
||||
handleClose();
|
||||
setId(orgId);
|
||||
},
|
||||
[change, fieldName, handleClose, onChange]
|
||||
[]
|
||||
);
|
||||
|
||||
const actions: ModalButtonProps[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
text: MODAL_LOCALIZATION.SELECT,
|
||||
onClick: () => {
|
||||
change(fieldName, organizationId);
|
||||
onChange?.(organizationId!);
|
||||
handleClose();
|
||||
},
|
||||
dataAction: 'select',
|
||||
variant: 'primary',
|
||||
shape: 'default',
|
||||
},
|
||||
],
|
||||
[change, fieldName, handleClose, onChange, organizationId]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -51,28 +76,28 @@ const Organizations = ({ textBefore, fieldName, title, onChange }: Props) => {
|
||||
)}
|
||||
</S.Subtitle>
|
||||
{isTablet || isMobile ? (
|
||||
<Drawer header={title} isOpen={isOpen} onClose={handleClose}>
|
||||
<Drawer isFixedActions actions={actions} header={title} isOpen={isOpen} onClose={handleClose}>
|
||||
<Dropdown isEmbedded dataName="organizations">
|
||||
{organizationOptions.map(org => (
|
||||
<Option
|
||||
key={org.id}
|
||||
hasActiveSub={activeOrganizations.some(finedOrg => finedOrg.id === org.id)}
|
||||
org={org}
|
||||
selected={org.id === values[fieldName]}
|
||||
selected={org.id === organizationId}
|
||||
onClick={onOptionClick(org.id)}
|
||||
/>
|
||||
))}
|
||||
</Dropdown>
|
||||
</Drawer>
|
||||
) : (
|
||||
<Modal header={title} isOpen={isOpen} onClose={handleClose}>
|
||||
<Modal actions={actions} header={title} isOpen={isOpen} onClose={handleClose}>
|
||||
<Dropdown dataName="organizations">
|
||||
{organizationOptions.map(org => (
|
||||
<Option
|
||||
key={org.id}
|
||||
hasActiveSub={activeOrganizations.some(finedOrg => finedOrg.id === org.id)}
|
||||
org={org}
|
||||
selected={org.id === values[fieldName]}
|
||||
selected={org.id === organizationId}
|
||||
onClick={onOptionClick(org.id)}
|
||||
/>
|
||||
))}
|
||||
|
||||
+2
-1
@@ -20,7 +20,8 @@ const reportMetadataParamsFromFields = (values: FormProps): ReportParams => {
|
||||
offset: 0,
|
||||
},
|
||||
sort: {
|
||||
direction: SORT_DIRECTION.ASC,
|
||||
// Несоответствие типов сортировки с ЭКО
|
||||
direction: SORT_DIRECTION.ASC.toUpperCase() as SORT_DIRECTION,
|
||||
field: 'reportNumber',
|
||||
},
|
||||
},
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ const mapDataToRequestParams = (values: FormValues): GenerateParams => {
|
||||
orgId: organizations,
|
||||
};
|
||||
|
||||
if (organizationsSearch) {
|
||||
if (organizationsSearch && inn && ogrn) {
|
||||
requestParams.partnerName = organizationsSearch;
|
||||
requestParams.inn = inn;
|
||||
requestParams.ogrn = ogrn;
|
||||
|
||||
+7
-3
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import type { ReportItem } from '@msb/http';
|
||||
import { queryClient } from '@msb/http';
|
||||
import { useDialog } from '@msb/shared';
|
||||
import { useDialog, useRedirect } from '@msb/shared';
|
||||
import type { AxiosError } from 'axios';
|
||||
import { useForm, useFormState } from 'react-final-form';
|
||||
import { MODAL_EMPTY_LOCALIZATION, MODAL_ERROR_LOCALIZATION } from '../../constants';
|
||||
@@ -24,6 +24,8 @@ const useActions = ({ clearForm }: UseActionsProps) => {
|
||||
const { setReport } = useReportContext();
|
||||
const { showDialog } = useDialog();
|
||||
|
||||
const goBack = useRedirect('b');
|
||||
|
||||
const handleCheck = useCallback(async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
@@ -53,6 +55,7 @@ const useActions = ({ clearForm }: UseActionsProps) => {
|
||||
okButtonText: MODAL_EMPTY_LOCALIZATION.BUTTON,
|
||||
hideCancelButton: true,
|
||||
type: 'warning',
|
||||
onClose: () => queryClient.invalidateQueries([QUERY_KEY_REPORT_INFINITE]),
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -62,14 +65,15 @@ const useActions = ({ clearForm }: UseActionsProps) => {
|
||||
cancelButtonText: MODAL_ERROR_LOCALIZATION.CANCEL,
|
||||
message: MODAL_ERROR_LOCALIZATION.DESCRIPTION,
|
||||
onOk: handleCheck,
|
||||
onCancel: goBack,
|
||||
type: 'error',
|
||||
});
|
||||
}).catch(() => queryClient.invalidateQueries([QUERY_KEY_REPORT_INFINITE]));
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [errors, values, clearForm, setReport, restart, initialValues, showDialog]);
|
||||
}, [errors, values, clearForm, setReport, restart, initialValues, showDialog, goBack]);
|
||||
|
||||
return { handleCheck, isLoading };
|
||||
};
|
||||
|
||||
-1
@@ -74,7 +74,6 @@ const SearchPartnerContainer = ({ clearForm, ReportCard }: Props) => {
|
||||
</S.PartnerBlockForm>
|
||||
</>
|
||||
)}
|
||||
subscription={{ values: true }}
|
||||
validate={validate}
|
||||
onSubmit={emptyFn}
|
||||
/>
|
||||
|
||||
+16
-2
@@ -16,7 +16,7 @@ const useValidate = () => {
|
||||
|
||||
return useCallback(
|
||||
async (values: FormValues) => {
|
||||
const { organizations, organizationsSearch, showInputField, handleInput } = values;
|
||||
const { organizations, organizationsSearch, showInputField, handleInput, inn, ogrn } = values;
|
||||
|
||||
const clientAuthorities = userAuthorities?.data.clientAuthorities || {};
|
||||
|
||||
@@ -51,12 +51,26 @@ const useValidate = () => {
|
||||
};
|
||||
}
|
||||
|
||||
if ((organizationsSearch as string)?.length > MAX_LENGTH) {
|
||||
if (organizationsSearch?.length && organizationsSearch.length > MAX_LENGTH) {
|
||||
errors[FIELDS.ORGANIZATIONS_SEARCH] = {
|
||||
error: ERROR_LOCALIZATION[FIELDS.ORGANIZATIONS_SEARCH].MAX_LENGTH,
|
||||
};
|
||||
}
|
||||
|
||||
// Для проверки, что именно кликнули в dropdown по организации
|
||||
if (!showInputField && !inn) {
|
||||
errors[FIELDS.INN] = {
|
||||
error: 'required',
|
||||
};
|
||||
}
|
||||
|
||||
// Для проверки, что именно кликнули в dropdown по организации
|
||||
if (!showInputField && !ogrn) {
|
||||
errors[FIELDS.OGRN] = {
|
||||
error: 'required',
|
||||
};
|
||||
}
|
||||
|
||||
if (showInputField && !handleInput) {
|
||||
errors[FIELDS.HANDLE_INPUT] = {
|
||||
error: ERROR_LOCALIZATION[FIELDS.HANDLE_INPUT].REQUIRED,
|
||||
|
||||
Reference in New Issue
Block a user