Описание проблемы
В TinSettings в поле поиска (tin или counteryName), при вводе нового символа или удаления  происходит перерендер, если нет совпадений выводится 'Данные не найдены' курсор «прыгает» при удалении символов пока входное значение не  найдет совпадение, как только найдено совпадение курсор при удалении стабилизируется. Сделать чтоб курсор не слетал
В FilterForm поисковый ввод работает корректно, без проблем с фокусировкой курсора , при вводе нового символа или удаления  происходит перерендер, но курсор остаётся в поле ввода. Нужно проанализировать код в  FilterForm/index.ts и понять в чем причина сброса курсора в TinSettings, 

___________________________________________
FilterForm/types.ts 
...
export enum FilterModule {
  DEALS = 'deals',
  ANALYTICS = 'analytics',
}

export interface FormInputProps {
  type?: FormInputTypeEnum;
  value: TEMPORARY_ANY;
  values: Record<string, TEMPORARY_ANY>;
  onChange: (value: TEMPORARY_ANY) => void;
  name: string;
  setFieldValue: (name: string, value: TEMPORARY_ANY) => void;
  placeholder?: string;
}

export interface AnalyticsFilter {
  updatedDate_from: string;
  updatedDate_to: string;
  [key: string]: string;
}

export interface DealsFilter {
  tradeDate_from: string;
  tradeDate_to: string;
  [key: string]: string;
}
export type FilterValues = AnalyticsFilter | DealsFilter;

export type FilterFormValues = Record<string, string>;

export enum FormInputTypeEnum {
  DEFAULT = 'default',
  STATUS = 'status',
  DATE = 'date',
  INT_NUMBER = 'intNumber',
  NUMBER = 'number',
  DATE_RANGE = 'dateRange',
  BOOLEAN = 'boolean',
  DOCUMENT_STATUS = 'documentStatus',
  DEAL_TYPE = 'dealType',
  OPERATION_TYPE = 'operationType',
  FIXED_NUMBER = 'fixedNumber',
  DATE_TIME_RANGE = 'dateTimeRange',
  CURRENCY_CODE = 'currencyCode',
}
___________________________________________
FilterForm/FormInput/index.ts 

export const FormInput: React.FC<FormInputProps> - ({
type,
onChange,
placeholder = '',
value,
values,
name,
setFieldValue,
}) => {
const [tooltipInView, setTooltipInView] - useState(false);
const isDateRange = type === FormInputTypeEnum.DATE_RANGE || type === FormInputTypeEnum.DATE_TIME
const component = useMemo(() => {
switch (type) {
case FormInputTypeEnum.STATUS:
case FormInputTypeEnum.BOOLEAN:
case FormInputTypeEnum.DOCUMENT_STATUS:
case FormInputTypeEnum.DEAL_TYPE:
case FormInputTypeEnum.OPERATION_TYPE:
case FormInputTypeEnum.CURRENCY_CODE:
return (
);
<SelectNew
dropHeight={'150px'}
>
placeholder={placeholder}
onSelect={onChange}
selected={value}
type="single"
size={SIZE_VARIANT.XSMALL}
options={OPTIONS_BY_TYPE[type]}
case FormInputTypeEnum.DATE:
return (
<DateInput
size={SIZE_VARIANT.XSMALL}
placeholder={placeholder}
value={value}
// control={
//
<Link type="neutral" onClick={() => onChange('')} iconLeft={value ? ClearIcon: ur
//
{''}
//
</Link>
// }
onChange={onChange}
/>
);
case FormInputTypeEnum.DATE_RANGE:
case FormInputTypeEnum.DATE_TIME_RANGE:
return (
<DatePicker
type="range"
size={SIZE_VARIANT.XSMALL}
startDate={values[name + '_from'] ? parseDateString(values[name + '_from']) : undefined}
endDate={values[name + '_to'] ? parseDateString(values[name + '_to']) : undefined}
onStartDayChange={(value) => setFieldValue(name + '_from', value ? formatDateToString(value) : undefined)}
onEndDayChange={(value) => setFieldValue(name + '_to', value ? formatDateToString(value) : undefined)}
/>
);
case FormInputTypeEnum.DATE:
return (
<DatePicker
type="single"
size={SIZE_VARIANT.XSMALL}
placeholder={placeholder}
startDate={value}
onDateChange={onChange}
/>
);


___________________________________________

import { SIZE_VARIANT } from '../../../types/props';
import { BasicInput } from '../../Basics';
export interface ICurrencyItem {
id: string;
symbol: string;
}
declare type IBasicInputProps - Omit<React.ComponentProps<typeof BasicInput>, 'size' | 'onChange' | 'type' | 'nonce' | 'onResize' | 'onResizeCapture' | 'ref'>;
export interface InputSizeProps {
size?: SIZE_VARIANT;
}
export interface InputErrorSecProps {
hasError?: boolean;
hasSuccess?: boolean;
}
export interface InputProps extends IBasicInputProps, InputSizeProps, InputErrorSecProps
{
hasNoIcons?: boolean;
disabled?: boolean;
labelText?: string;
inlineLabel?: boolean;
isValueEmpty?: boolean;
captionText?: string;
control?: React.ReactElement;
onChange?: (val: string) => void;
onFocus?: (e: unknown) => void;
onBlur?: (e: unknown) => void;
}
export interface ICurrencyInputProps extends Omit<IInputProps, 'onSelect'> {
onSelect?: ({ id, symbol }: ICurrencyItem) => void;
currency: ICurrencyItem;
currencyItems?: ICurrencyItem[];
inputProps?: {
[key: string]: any;
};
}
....


import React from 'react';
import INPUTS from './constants';
export declare type InputTypes = 'simple' | 'masked' | 'currency' | 'counter' | 'date' |
'dateRange' | 'email' | 'clear' | 'number' | 'phone';
export interface InputProps<Type extends InputTypes> {
type?: Type;
ref?: React.Ref<HTMLInputElement>;
}

export declare type InputPropsType<Type extends InputTypes> = React.ComponentProps<(typeof INPUTS)[Type]>;
export declare type InputComponent<Type extends InputTypes = 'simple'>(props:
InputProps<InputType> & React.ComponentProps<(typeof INPUTS)[InputType]>) => JSX.Element;
export declare type InputType<T extends InputTypes 'simple'> = InputProps<T> & React.ComponentProps<(typeof INPUTS)[T]>;

___________________________________________
FilterForm/index.ts

export const FilterForm: React.FC<FilterFormProps> = ({
cols,
handleRefresh,
onFilterChange,
module = FilterModule.DEALS,
}) => {
const dispatch = useAppDispatch();
const { pageSizeSelector, filterSelector, setFilterAction, setPageSizeAction, resetAction, date field, placeholder = MODULE_CONFIG[module];

const pageSize = useSelector(pageSizeSelector);
const initialValues = useSelector(filterSelector);
const currentyPairsResponse = useSelector(currentyPairsSelector);

const currencyOptions = useMemo (() => {
if (!currentyPairsResponse || ! Array.isArray(currentyPairsResponse)) return []

return currentyPairsResponse.map((pair: string) =>({ label: pair, value: pair }))
}, [currentyPairsResponse])

const [selected, setSelected] = useState<Record<string, boolean>>({});
const isSomeSelected = Object.values(selected).some(Boolean);
const defaultonFilterChange = (value: Record<string, string>) => {
batch(() => {
dispatch(setFilterAction(value));
dispatch(resetData());
});
};

const currentTarget = useSelector (DealVarintSelector);
const target = currentTarget || '';

const sort = useSelector (SortSelector);
const isSorted = Object.values (sort [target] || {}).some(Boolean);

const handleSelect = (name: string) => {
setSelected((current) => ({
...current,
[name]: !current[name],
}));
};

const handleSubmit = useDebounced((values: Record<string, string>) => {
const submitingValues = { ...values };

Object.keys(submitingValues).forEach((key) => {
if (!submitingValues[key]) {
delete submitingValues[key];

return;
}

if (key.includes('date') || key.includes('Date')) {
if (submitingValues[key].length !== 10) {
delete submitingValues[key];
}
});
}

if (!isEqual(initialValues, submitingValues)) {
const filterChangeHandler = onFilterChange || defaultOnFilterChange;

filterChangeHandler(submitingValues);
}
}, 500);

const { values, setValues, setFieldValue } = useFormik({
initialValues,
onSubmit: handleSubmit,
enableReinitialize: true,
});

const handleSelectPageSize = (value: string | string[]) => {
if (pageSize !== +value) {
dispatch(setPageSizeAction({ size: +value }));
}
};

const handleDeleteFilters = () => {
dispatch(resetAction());
setValues({});
setSelected({});
};

useEffect(() => {
handleSubmit(values);
}, [values]);

return (
<Form>
<Flex gridGap="12px" justifyContent="space-between">
<Box row gridGap="12px">
<FormInput
key={dateField}
placeholder={placeholder}
type={FormInputTypeEnum.DATE_RANGE}
value={values[dateField] || ''}
values={values}
setFieldValue={setFieldValue}
name={dateField}
onChange={(value) => {
setFieldValue(dateField, value);
}}
/>

<DropdownBtn
list={cols}
selected={selected}
onChange={(name) => {
if (selected[name]) {
setFieldValue(name, undefined);
}
handleSelect(name);
}}
>
<Button
type="button"
variation={BUTTON_VARIATION.TERTIARY}
size={SIZE_VARIANT.SMALL}
iconRight={Icon.AdjustHorizontalAlt}
>
Параметры поиска
</Button>
</DropdownBtn>
{isSomeSelected && (
<Button
variation={BUTTON_VARIATION.GHOST}
iconLeft={Icon.Bin}
size={SIZE_VARIANT.SMALL}
type="button"
onClick={handleDeleteFilters}
>
Удалить фильтры
</Button>
)}
{isSorted && (
<Button
variation={BUTTON_VARIATION.GHOST}
iconLeft={Icon.Reload}
size={SIZE_VARIANT.SMALL}
type="button"
onclick={() => {
dispatch(resetSort(target));
}}
>
Сбросить сортировку
</Button>
)}
</Box>
<Select
width="80px"
size={SIZE_VARIANT.XSMALL}
dropHeight={'150px"}
selected={pageSize + ''}
onChange={handleSelectPageSize}
options={[
{ label: '50', value: '50' },
{ label: '100', value: '100' },
{ label: '500', value: '500' },
]}
/>
<Button
variation={BUTTON_VARIATION.GHOST}
type="button"
onClick={handleRefresh}
size={SIZE_VARIANT.SMALL}
icon={Icon.Refresh}
/>
</Flex>
<Flex pt="16px" pb="16px" flexWrap="wrap" gridGap={'16px'}>
{Object.keys(selected).map((name) => {
if (!selected[name]) {
return null;
}

const col = cols.find((col) => col.name === name);

return (
<FormInput
key={name}
placeholder={col?.label}
type={col?.type || FormInputTypeEnum.DEFAULT}
value={values[col?.name || '']}
values={values}
setFieldValue={setFieldValue}
name={name}
onChange={(value) => {
setFieldValue(name, value);
options={col?.type === FormInputTypeEnum.CURRENCY_CODE ? currencyOptions : undefined}
module={module}
}}
/>
);
})}
</Flex>
</From>
);
};

__________________________________________
src/pages/TinSettings/Row.tsx 

type Props = { rowData: TinSettingData; index: number; onDelete: () => void };

export const TinRow: FC<Props> = ({ rowData, onDelete }) => {
const dispatch = useAppDispatch();
const { data: activeData, isEditing } = useSelector(selectActiveForm);
const isCurrentEdit - isEditing && activeData?.id === rowData.id;
if (isCurrentEdit) {
return 
<Editing
data={rowData}
toggleEditin={() => dispatch(cancelEditing())}
isNew={false}
/>
}

return (
<Reading
data={rowData}
onEdit={() => {
dispatch(cancelEditing ());
dispatch(startEditing({...rowData}));
});

onDelete={onDelete)
/>
);
};

___________________________________________
src/pages/TinSettings/TinSettings.tsx 

export const TinSettings = () => {
  const dispatch = useAppDispatch();
  const isAdmin = useSelector(isAdminSelector);
  const isLoading = useSelector(getIsPending(getTinSettings));
  const error = useSelector(getError(getTinSettings));
  const currencyPairs = useSelector(CurrencyPairsSelector);
  const content = useSelector(TinSettingDataSelector);
 const searchString = useSelector(tinSearchStringSelector);
  const pageInfo = useSelector(PageInfoSelector);
  const sort = useSelector(tinSortStringSelector);
  
const formik = useFormik({
initialValues: searchString,
onSubmit: (values) => {
dispatch(setSearchString(values));
},
enableReinitialize: true,
});

const updateReduxFiltersDebounced = useCallback(
useDebounced((filters: typeof searchString) => {
dispatch(setSearchString(filters));
}, 500),
[dispatch]
);

const handleFilterChange = useCallback(
(key: keyof typeof searchString, value?: string) => {
formik.setFieldValue(key, value);
updateReduxFiltersDebounced({ ...formik.values, [key]: value });
},[formik, updateReduxFiltersDebounced]);

const getData = useCallback(() => dispatch(getTinSettings()), [dispatch]);

useEffect(() => {
getData();
}, [sort, searchString, pageInfo.number, getData]);

useEffect(() => {
dispatch(getCurrencyPairs());
}, []);

const resetFilter = useCallback(() => {
const defaultFilters = { active: 'true' };

formik.setValues(defaultFilters);
dispatch(setSearchString(defaultFilters));
}, [dispatch, formik]);

  const setSort = useCallback ((key: string) => {
    let newSort: typeof sort = null;

    if (!sort || sort.key !== key) {
      newSort = { key, value: 'asc' };
    } else if (sort?.value === 'asc' && sort.key === key) {
      newSort = { key, value: 'desc' };
    }
    dispatch(setSortString(newSort));
  }, [sort]);

 const { data: activeData, isEditing } = useSelector(selectActiveForm);

  const onMoreClick = useCallback(() => {
    dispatch(changePageNumber({}));
  }, []);

  const onDelete = useCallback(async (id: string) => {
    await dispatch(deleteTinSetting([id]));
  }, []);
};

const renderSortIcon = (key: string) => {
if (!sort) {
return null;
}
if (key == sort.key) {
return sort.value === 'asc'? <Icon.ArrowUpSmall /> : <Icon.ArrowDownSmall />;
}
return null;
};

const currencyOptions = useMemo (() => currencyPairs.map((pair) => ({ label: pair,
value: pair })), [currencyPairs]);
const handleFilter = (key: string, value?: string) => {
};

if (!content.length && isLoading) {
return <Loader />;
}

return (
<Flex pt="24px" gridGap={'24px'} flexDirection="column">
<Flex zIndex={20} gridGap="12px">
<Input
key='tin-input'
value={formik.values.tin || ''}
width="258px"
size={SIZE_VARIANT.XSMALL}
inlineLabel
labelText="ИНН"
type="number"
allowLeadingZeroes
maxLength={12}
onChange={(value) => handleFilterChange('tin', value)}
/>
<Input
key='counterpartyName-input'
value={formik.values.counterpartyName || ''}
width="258px"
size={SIZE_VARIANT.XSMALL]
inlineLabel
labelText="Контрагент"
onChange={(value) => handleFilterChange('counterpartyName', value)}
/>
<SelectNew
inlineLabel
width="258px"
labelText="Валютная пара"
type="search-single"
size-{SIZE_VARIANT.XSMALL}
selected={formik.vales.currencyPair || ''}
options={currencyOptions}
onSelect={(value) => {
handleFilterChange('currencyPair', value as string);
}}
/>
<Switch
label="Только активные"
isActive={formik.values.active === 'true'}
onChange={(value) => handleFilterChange('active', value ? 'true' : undefined)}
isText={false}
/>
<Button
iconRight={Icon.Refresh}
disabled={isEditing}
type="button"
marginLeft="auto"
variation={BUTTON_VARIATION.GHOST}
onClick={resetFilter}
>
Очистить фильтры
</Button>
{isAdmin && (
<Button
iconRight={Icon.Plus}
disabled={isEditing} 
type="button"
marginLeft="auto"
variation-{BUTTON_VARIATION.GHOST}
onClick={() => {
dispatch(resetFormData());
dispatch(startEditing());
}
>
Добавить запись 
</Button>
)}
</Flex>

<Flex
flexDirection="column"
borderRadius="md"
height="100%"
border="1px solid"
borderColor="table-cell-border--default"
<Header cols={20}>
<Cell col={TEMPLATE_COLS.active} alignSelf-"center">
<Typography
Typography>
</Cell>
variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM)>Активно</
<HeaderCell alignSelf="center" col={TEMPLATE_COLS.validUntil}>
<Flex onClick={() => setSort('validUntil')} justifyContent="space-between"
cursor="pointer" pr="12px">
<Typography variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM}>Действует
до</Typography>
{renderSortIcon('validUntil')}
</Flex>
</HeaderCell>
<HeaderCell alignSelf="center" col={TEMPLATE_COLS.tin}>
<Flex onClick={() => setSort('tin')} justifyContent="space-between"
cursor="pointer" pr="12px">
<Typography
variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM)>ИНН</
Typography>
{renderSortIcon('tin')}
</Flex>
</HeaderCell>
<HeaderCell alignSelf="center" col={TEMPLATE_COLS.counterpartyName}>
<Flex onClick={() => setSort('counterpartyName')}
justifyContent="space-between" cursor="pointer" pr="12px">
<Typography variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM} >Контрагент</
Typography>
{renderSortIcon('counterpartyName')}
</Flex>
</HeaderCell>
<Cell alignSelf="center" col={TEMPLATE_COLS.description}>
<Typography variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM}>Доп.
информация</Typography>
</Cell>
<Cell alignSelf="center" col={TEMPLATE_COLS.currencyPair}>
<Typography variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM} >Валютная
пара</Typography>
</Cell>
<Cell alignSelf="center" col-{TEMPLATE_COLS.minAmount}>
<Typography variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM}>Мин. сумма</
Typography>
</Cell>
<Cell alignSelf="center" col-{TEMPLATE_COLS.maxAmount}>
<Typography
Typography>
</Cell>
variant={TYPOGRAPHY_VARIANT.TABLE_HEADER_MEDIUM}>Макс. сумма</
<Cell col={2}></Cell>
</Header>

{isEditing && !activeData?.id && <Editing key="new" toggleEditing={() => dispatch (cancelEditing())} isNew />}
{content.map((data, index) => (
<TinRow key={data.id} rowData={data} index={index} onDelete={() => onDelete
(data.id)} />
))}
{content.length === 0 && !isEditing && (
)}
<ErrorNotification isPositive={lerror} details={error || 'Данные не
найдены'} />
<Box backgroundColor="table-cell-fill--default" position="sticky" bottom="0">
<LoadMoreButton
/>
handleClickMore={onMoreClick}
currentPage={pageInfo.number}
isLoading={isLoading}
isLast={pageInfo.last}
totalElements={pageInfo.totalElements}
</Box>
</Flex>
</Flex>
);
};
______________________________________
src/pages/TinSettings/Editing.tsx

type Props =
| { data: TinSettingData; toggleEditing: () => void; isNew?: false }
| { isNew: true; data?: TinSettingData; toggleEditing: () => void };

export const Editing: FC<Props> = ({ data, toggleEditing, isNew }) => {
const dispatch = useAppDispatch();
const currencyPairs = useSelector (CurrencyPairsSelector);
const isLoading = useSelector(getIsPending (changeTinSetting));

const handleClose = useCallback (()=>{
onFinishCrmlegalClientSession();
formik.resetForm();
dispatch(resetFormData ());
dispatch(cancelEditing ());
toggleEditing();
}, []);

const onSubmit = async (values: TinSettingData) => {
const req = await dispatch(
changeTinSetting({
...values,
counterpartyName: values.counterpartyName | undefined,
validUntil: values.validUntil || undefined,
currencyPair: values.currencyPair || undefined,
description: values.description || undefined,
minAmount: values.minAmount?.replace(/\D/g, '') || undefined,
maxAmount: values.maxAmount?.replace(/\D/g, '') || undefined,
globalId: values.globalId || '',
})
);

(req.meta.requestStatus === 'fulfilled') {
handleClose();
};

const formik = useFormik({
initialValues: isNew ? ({ active: true } as TinSettingData): data,
onSubmit,
validate: (values) => {
const errorobj = {} as Record<keyof TinSettingData, string | undefined>;

if (!values.tin || (values.tin.length !== 10 && values.tin.length !==
12)) {
errorobj.tin = 'Укажите корректный ИНН';
}

if (values.validUntil && Number(values?.validUntil?.length) !== 10) {
errorobj.validUntil = 'Укажите корректную дату';
}

  if (values.validUntil && !isBeforeDate(new Date(), parseDateString(values.validUntil))) {
  }
  errorObj.validUntil = 'Дата не должна быть из прошлого';

  if (values.minAmount && values.maxAmount) {
    if (Number(values.minAmount.replace(/\D/g, '')) > Number(values.maxAmount.replace(/\D/g,''))) {
      errorObj.minAmount = 'Сумма мин. не может быть больше суммы макс.';
    }
  }
  return errorObj;
},
validateOnBlur: true,
enableReinitialize: true,
});

const { values, errors, dirty, touched, isValid, setFieldValue,
handleSubmit } = formik;

useEffect(
() => () => {
  dispatch(resetActionsStatuses());
},
[]
);

useEffect(() => {
  document.onkeydown = (e: KeyboardEvent) => {
    const { ctrlKey, code } = e;

    if (ctrlKey && code === 'Enter') {
e.preventDefault();
handleSubmit();
return;
}
};
return () => {
document.onkeydown = () => {
//
};
document.onkeyup = () => {
//
};
};
}, []);

const currencyOptions = useMemo (
() => { label: '', value: ''}].concat(currencyPairs.map((pair) => ({
label: pair, value: pair }))),
[currencyPairs]
);

useEffect (()=>{
const subscriber = subscribe((client: LegalClient) => {
if (client && isNew === true) {
formik.setValues({
... formik.values,
tin: client.inn,
counterpartyName: client.shortName,
globalId: client.unifiedId,
})
}
}, 'crmLegalClient.crmLegalClient');
return subscriber
}, []);

const handleClientSearch = () =>{
navigateTo(PLATFORM_APPS.LEGAL_CLIENT_SEARCH)
}


return (
<Row cols={20}>
<Cell col={TEMPLATE_COLS.active) alignSelf="self-start">
<Switch
isText={false}
isActive={values?.active}
onChange={(value: boolean) setFieldValue(`active`. value)
isActive={values?.active}
onChange={(value: boolean) => setFieldValue(`active`, value)}
/>
</Cell>
<Cell col={TEMPLATE_COLS.validUntil} alignSelf="self-start">
<DateInput
size={SIZE_VARIANT.XSMALL}
captionText={errors.validUntil}
hasError={touched.validUntil && !! errors.validUntil}
placeholder="Ввести дату до"
value={values.validUntil}
onChange={(value: string) => setFieldValue(`validUntil`, value)}
/>
</Cell>
<Cell col={TEMPLATE_COLS.tin} alignSelf="self-start">
<Flex gridGap="0" minWidth="120px" alignItems="flex-start"
width="inherit" justifyContent="space-around">
<Input
size={SIZE_VARIANT.XSMALL}
value={formik.values.tin}
captionText={errors.tin}
hasError={touched.tin && !! errors.tin}
type="number"
allowLeadingZeroes
maxLength={12}
onChange={(value: string) => setFieldValue(`tin`, value)}
readOnly
disabled={!!values.globalId}
/>
<Button width="30px" variation={BUTTON_VARIATION.GHOST} onClick=
{handleClientSearch}>
<Icon.Magnifier />
</Button>
</Flex>
</Cell>
<Cell col={TEMPLATE_COLS.counterpartyName} alignSelf="self-start">
<TextArea
size={SIZE_VARIANT.SMALL}
value={values.counterpartyName as string}
onChange={(value) => setFieldValue(`counterpartyName`, value)}
counter={false}
disabled={!!values.globalId}
/>
...
// Открытие формы редактирования 
<Button
disabled={disableSubmit}
icon={Icon.Save}
variation={BUTTON_VARIATION.TERTIARY}
onClick={() => {
handleSubmit();
}}
/>
// Закрытие формы редактирования 
<Button
icon={Icon.Close}
variation={BUTTON_VARIATION.TERTIARY}
onClick={() => {handleClose}
/>
{!isNew && (
<Button
disabled={isLoading}
icon={Icon.Bin}
variation={BUTTON_VARIATION.DANGER_SECONDRAY}
onClick={() => {
handleSubmit();
}}
/>
)}
</ButtonWrapper>
</Cell>
</Row>
);
};
__________________________________________
src/store/TinSettings/action.ts

export const getCurrencyPairs = createThunk('dictionaries/getCurrencyPairs', async () => {
const resData = await sendGetRequest<string[]>(`/setting/currency/currency-pairs`);

return resData;
});

export const getTinSettings = createThunk('dictionaries/getTinSettings', async(_, thunkApi) => {
const store = thunkApi.getState() as RootState;
const sortString = store.tinSettingSlice.sortString;
const search = store.tinSettingSlice.searchString;
const page = store.tinSettingSlice.pageInfo.number;
const size = store.tinSettingSlice.pageInfo.size;
const searchString = Object.entries(search)
    .map(([key, value]) => {
      if (!value) return '';
      // Для counterpartyName используем like-поиск
      if (key === 'counterpartyName') {
        return `${key}=like=%${value}%`;
      }
      // Для остальных полей оставляем точное сравнение
      return `${key}==${value}`;
    })
    .filter(Boolean)
    .join(',');


const resData = await sendGetRequest<PaginatedResponse<TinSettingData[]>>(
`/tin/list?page=${page}&size=${size}${
sortString
? `&sort=${sortString.key},${sortString.value}${
searchString ? `&search=${encodeURIComponent(searchString)}`: ''
}`
: searchString
? `&search=${encodeURIComponent(searchString)}`
: ''
}`
);

return resData;
});


export const changeTinSetting = createThunk('dictionaries/changeTinSetting', async (data: TinSettingData) => {
const resData = await sendPostRequest<TinSettingData[]>({ url: `/tin/update-all`, data:
[data] });

return resData;
});

export const deleteTinSetting = createThunk('dictionaries/deleteTinSetting', async (ids: string[]) => {
const resData = await sendPostRequest<TinSettingData>({ url: `/tin/delete-all`, data: ids });
return resData;
});
__________________________________________
src/store/TinSettings/slice.ts

export const emptyTinData: TinSettingData = {
id: '',
active: true,
tin: '',
counterpartyName: '',
validUntil: '',
currencyPair: '',
description: '',
maxAmount: '',
minAmount: '',
globalId: '',
};

const initialState: State = {
data: [],
searchString: { active: 'true' },
sortString: { key: 'validUntil', value: 'desc' },
currencyPairs: [],
pageInfo: {
last: true,
totalElements: 10,
totalPages: 1,
size: 10,
number: 0,
},
activeForm: {
data: null,
isEditing: false,
},
};

export const tinSettingsSlice = createSlice({
name: 'tinSettings',
initialState,
reducers: {
startEditing: (state, action: PayloadAction<TinSettingData | undefined>) => {
state.activeForm = {
data: action.payload ? { ...action.payload } : { ...emptyTinData },
isEditing: true,
};
},
cancelEditing: (state) => {
state.activeForm = initialState.activeForm;
},
changePageNumber: (state, { payload }: PayloadAction<{ number?: number }>) => {
const { number } = payload;
state.pageInfo.number = number ?? state.pageInfo.number + 1;
},
setSearchString: (state, { payload }) => {
state.searchString = payload;
state.pageInfo.number = 0;
},
setSortString: (state, { payload }) => {
state.pageInfo.number = 0;
state.sortString = payload;
},
resetData: (state) => {
state.data = [];
},
},
extraReducers: (builder) => {
builder.addCase(getCurrencyPairs.fulfilled, (state, { payload }) => {
state.currencyPairs = payload;
});
builder.addCase(deleteTinSetting.fulfilled, (state, { meta }) => {
state.data = state.data.filter((el) => !meta.arg.includes(el.id));
});
builder.addCase(changeTinSetting.fulfilled, (state, { payload, meta }) => {
if (meta.arg.id) {
const index = state.data.findIndex((element) => element.id === meta.arg.id);
state.data[index] = payload[0];
} else {
state.data = payload.concat(state.data);
}
state.activeForm = initialState.activeForm;
});
builder.addCase(getTinSettings.fulfilled, (state, { payload }) => {
if (payload.pageInfo.number === 0) {
state.data = payload.content;
} else {
state.data = state.data.concat(payload.content);
}
state.pageInfo.totalElements = payload.pageInfo.totalElements;
state.pageInfo.last = payload.pageInfo.last;
});
},
});

export const { startEditing, cancelEditing, changePageNumber, setSortString, setSearchString, resetData } = tinSettingsSlice.actions;
export default tinSettingsSlice.reducer;