AURORA-1989: номер статьи, сортировка и поиск в окне выбора расхода
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
321943db56
commit
b87b12f980
@ -5,6 +5,7 @@ import { ExpenseItemApi } from '../../../api/expense-item';
|
||||
import { DangerOutlinedButton, PrimaryButton } from '../../common/Buttons/Buttons';
|
||||
import { HeaderContainer, ModalBackdrop, ModalContainer, ModalTitle } from '../../common/Modal/ModalStyled';
|
||||
import { Cancel } from '../../common/icons/icons';
|
||||
import { compareExpenseItems, getExpenseItemLabel } from '../utils/expenseItemOptions';
|
||||
|
||||
const SelectExpenseItemModalComponent = ({ isOpen, onClose, onSelect, formId, title = '', isSaving = false, sheet }) => {
|
||||
const [selectedValue, setSelectedValue] = useState('');
|
||||
@ -14,7 +15,7 @@ const SelectExpenseItemModalComponent = ({ isOpen, onClose, onSelect, formId, ti
|
||||
if (!isOpen || formId == null) return;
|
||||
ExpenseItemApi.getAll({ r_start: true, sheet: sheet }).then((data) => {
|
||||
if (data.success) {
|
||||
setExpenseItemOption(data.result);
|
||||
setExpenseItemOption([...data.result].sort(compareExpenseItems));
|
||||
return;
|
||||
}
|
||||
toast.error('Ошибка получения статья расходов');
|
||||
@ -69,7 +70,7 @@ const SelectExpenseItemModalComponent = ({ isOpen, onClose, onSelect, formId, ti
|
||||
size='small'
|
||||
options={expenseItemOptions}
|
||||
noOptionsText='Не найдено'
|
||||
getOptionLabel={(option) => option.name || ''}
|
||||
getOptionLabel={getExpenseItemLabel}
|
||||
getOptionKey={(option) => option.id}
|
||||
value={selectedValue}
|
||||
onChange={(_event, newValue) => {
|
||||
|
||||
22
web/src/components/RealtimeTable/utils/expenseItemOptions.js
Normal file
22
web/src/components/RealtimeTable/utils/expenseItemOptions.js
Normal file
@ -0,0 +1,22 @@
|
||||
const getItemCode = (option) => {
|
||||
const code = option?.item_id;
|
||||
if (code == null) return '';
|
||||
return String(code).trim();
|
||||
};
|
||||
|
||||
export const getExpenseItemLabel = (option) => {
|
||||
if (!option || typeof option !== 'object') return '';
|
||||
const code = getItemCode(option);
|
||||
const name = option.name || '';
|
||||
if (code && name) return `${code} — ${name}`;
|
||||
return code || name;
|
||||
};
|
||||
|
||||
export const compareExpenseItems = (a, b) => {
|
||||
const codeA = getItemCode(a);
|
||||
const codeB = getItemCode(b);
|
||||
if (!codeA && !codeB) return 0;
|
||||
if (!codeA) return 1;
|
||||
if (!codeB) return -1;
|
||||
return codeA.localeCompare(codeB, 'ru', { numeric: true });
|
||||
};
|
||||
@ -0,0 +1,27 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { compareExpenseItems, getExpenseItemLabel } from './expenseItemOptions.js';
|
||||
|
||||
const sorted = (ids) =>
|
||||
ids
|
||||
.map((item_id) => ({ item_id, name: 'x' }))
|
||||
.sort(compareExpenseItems)
|
||||
.map((o) => o.item_id);
|
||||
|
||||
test('AURORA-1989: подпись варианта', () => {
|
||||
assert.equal(getExpenseItemLabel({ item_id: '3.01.', name: 'Связь' }), '3.01. — Связь');
|
||||
assert.equal(getExpenseItemLabel({ item_id: null, name: 'Связь' }), 'Связь');
|
||||
assert.equal(getExpenseItemLabel({ name: '' }), '');
|
||||
assert.equal(getExpenseItemLabel(''), '');
|
||||
});
|
||||
|
||||
test('AURORA-1989: сортировка с учётом числовых частей, без кода — в конце', () => {
|
||||
assert.deepEqual(sorted(['3.10.', '3.2.', '10', '2']), ['2', '3.2.', '3.10.', '10']);
|
||||
assert.deepEqual(sorted([null, '1.', '']), ['1.', null, '']);
|
||||
});
|
||||
|
||||
test('AURORA-1989: поиск по подписи находит номер и название', () => {
|
||||
const label = getExpenseItemLabel({ item_id: '3.01.', name: 'Связь' });
|
||||
assert.ok(label.includes('3.01'));
|
||||
assert.ok(label.includes('Связь'));
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user