2024-03-24 19:25:42 +03:00
|
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
import { useCallback, useMemo, useState } from 'react';
|
|
|
|
|
|
|
|
|
|
import ConstituentaBadge from '@/components/info/ConstituentaBadge';
|
|
|
|
|
import ConstituentaSelector from '@/components/select/ConstituentaSelector';
|
|
|
|
|
import DataTable, { createColumnHelper } from '@/components/ui/DataTable';
|
|
|
|
|
import Label from '@/components/ui/Label';
|
|
|
|
|
import MiniButton from '@/components/ui/MiniButton';
|
2024-04-01 19:07:20 +03:00
|
|
|
|
import { useConceptOptions } from '@/context/OptionsContext';
|
2024-03-24 19:25:42 +03:00
|
|
|
|
import { IConstituenta, IRSForm, ISubstitution } from '@/models/rsform';
|
|
|
|
|
import { describeConstituenta } from '@/utils/labels';
|
|
|
|
|
|
2024-05-02 19:13:54 +03:00
|
|
|
|
import {
|
|
|
|
|
IconKeepAliasOff,
|
|
|
|
|
IconKeepAliasOn,
|
|
|
|
|
IconKeepTermOff,
|
|
|
|
|
IconKeepTermOn,
|
|
|
|
|
IconPageFirst,
|
|
|
|
|
IconPageLast,
|
|
|
|
|
IconPageLeft,
|
|
|
|
|
IconPageRight,
|
|
|
|
|
IconRemove,
|
|
|
|
|
IconReplace
|
|
|
|
|
} from '../Icons';
|
2024-04-03 21:05:53 +03:00
|
|
|
|
|
2024-03-24 19:25:42 +03:00
|
|
|
|
interface SubstitutionsPickerProps {
|
|
|
|
|
prefixID: string;
|
|
|
|
|
rows?: number;
|
|
|
|
|
|
|
|
|
|
schema1?: IRSForm;
|
|
|
|
|
schema2?: IRSForm;
|
|
|
|
|
filter1?: (cst: IConstituenta) => boolean;
|
|
|
|
|
filter2?: (cst: IConstituenta) => boolean;
|
|
|
|
|
|
|
|
|
|
items: ISubstitution[];
|
|
|
|
|
setItems: React.Dispatch<React.SetStateAction<ISubstitution[]>>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SubstitutionIcon({ item }: { item: ISubstitution }) {
|
|
|
|
|
if (item.deleteRight) {
|
|
|
|
|
if (item.takeLeftTerm) {
|
2024-05-02 19:13:54 +03:00
|
|
|
|
return <IconPageRight size='1.2rem' />;
|
2024-03-24 19:25:42 +03:00
|
|
|
|
} else {
|
2024-05-02 19:13:54 +03:00
|
|
|
|
return <IconPageLast size='1.2rem' />;
|
2024-03-24 19:25:42 +03:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (item.takeLeftTerm) {
|
2024-05-02 19:13:54 +03:00
|
|
|
|
return <IconPageFirst size='1.2rem' />;
|
2024-03-24 19:25:42 +03:00
|
|
|
|
} else {
|
2024-05-02 19:13:54 +03:00
|
|
|
|
return <IconPageLeft size='1.2rem' />;
|
2024-03-24 19:25:42 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const columnHelper = createColumnHelper<ISubstitution>();
|
|
|
|
|
|
|
|
|
|
function SubstitutionsPicker({
|
|
|
|
|
items,
|
|
|
|
|
schema1,
|
|
|
|
|
schema2,
|
|
|
|
|
filter1,
|
|
|
|
|
filter2,
|
|
|
|
|
rows,
|
|
|
|
|
setItems,
|
|
|
|
|
prefixID
|
|
|
|
|
}: SubstitutionsPickerProps) {
|
2024-04-01 19:07:20 +03:00
|
|
|
|
const { colors } = useConceptOptions();
|
2024-03-24 19:25:42 +03:00
|
|
|
|
|
|
|
|
|
const [leftCst, setLeftCst] = useState<IConstituenta | undefined>(undefined);
|
|
|
|
|
const [rightCst, setRightCst] = useState<IConstituenta | undefined>(undefined);
|
|
|
|
|
const [deleteRight, setDeleteRight] = useState(true);
|
|
|
|
|
const [takeLeftTerm, setTakeLeftTerm] = useState(true);
|
|
|
|
|
|
|
|
|
|
const toggleDelete = () => setDeleteRight(prev => !prev);
|
|
|
|
|
const toggleTerm = () => setTakeLeftTerm(prev => !prev);
|
|
|
|
|
|
|
|
|
|
function addSubstitution() {
|
|
|
|
|
if (!leftCst || !rightCst) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const newSubstitution: ISubstitution = {
|
|
|
|
|
leftCst: leftCst,
|
|
|
|
|
rightCst: rightCst,
|
|
|
|
|
deleteRight: deleteRight,
|
|
|
|
|
takeLeftTerm: takeLeftTerm
|
|
|
|
|
};
|
|
|
|
|
setItems([
|
|
|
|
|
newSubstitution,
|
|
|
|
|
...items.filter(
|
|
|
|
|
item =>
|
|
|
|
|
(!item.deleteRight && item.leftCst.id !== leftCst.id) ||
|
|
|
|
|
(item.deleteRight && item.rightCst.id !== rightCst.id)
|
|
|
|
|
)
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleDeleteRow = useCallback(
|
|
|
|
|
(row: number) => {
|
|
|
|
|
setItems(prev => {
|
|
|
|
|
const newItems: ISubstitution[] = [];
|
|
|
|
|
prev.forEach((item, index) => {
|
|
|
|
|
if (index !== row) {
|
|
|
|
|
newItems.push(item);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return newItems;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
[setItems]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const columns = useMemo(
|
|
|
|
|
() => [
|
|
|
|
|
columnHelper.accessor(item => describeConstituenta(item.leftCst), {
|
|
|
|
|
id: 'left_text',
|
|
|
|
|
header: 'Описание',
|
|
|
|
|
size: 1000,
|
|
|
|
|
cell: props => <div className='text-xs text-ellipsis'>{props.getValue()}</div>
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor(item => item.leftCst.alias, {
|
|
|
|
|
id: 'left_alias',
|
|
|
|
|
header: 'Имя',
|
|
|
|
|
size: 65,
|
|
|
|
|
cell: props => (
|
|
|
|
|
<ConstituentaBadge theme={colors} value={props.row.original.leftCst} prefixID={`${prefixID}_1_`} />
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.display({
|
|
|
|
|
id: 'status',
|
|
|
|
|
header: '',
|
|
|
|
|
size: 40,
|
|
|
|
|
cell: props => <SubstitutionIcon item={props.row.original} />
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor(item => item.rightCst.alias, {
|
|
|
|
|
id: 'right_alias',
|
|
|
|
|
header: 'Имя',
|
|
|
|
|
size: 65,
|
|
|
|
|
cell: props => (
|
|
|
|
|
<ConstituentaBadge theme={colors} value={props.row.original.rightCst} prefixID={`${prefixID}_2_`} />
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor(item => describeConstituenta(item.rightCst), {
|
|
|
|
|
id: 'right_text',
|
|
|
|
|
header: 'Описание',
|
2024-04-03 19:31:26 +03:00
|
|
|
|
minSize: 1000,
|
2024-03-25 19:17:18 +03:00
|
|
|
|
cell: props => <div className='text-xs text-ellipsis text-pretty'>{props.getValue()}</div>
|
2024-03-24 19:25:42 +03:00
|
|
|
|
}),
|
|
|
|
|
columnHelper.display({
|
|
|
|
|
id: 'actions',
|
|
|
|
|
cell: props => (
|
|
|
|
|
<MiniButton
|
|
|
|
|
noHover
|
|
|
|
|
title='Удалить'
|
2024-04-03 21:05:53 +03:00
|
|
|
|
icon={<IconRemove size='1rem' className='icon-red' />}
|
2024-03-24 19:25:42 +03:00
|
|
|
|
onClick={() => handleDeleteRow(props.row.index)}
|
|
|
|
|
/>
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
],
|
|
|
|
|
[handleDeleteRow, colors, prefixID]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return (
|
2024-03-27 22:54:24 +03:00
|
|
|
|
<div className='flex flex-col w-full'>
|
2024-03-24 19:25:42 +03:00
|
|
|
|
<div className='flex items-end gap-3 justify-stretch'>
|
|
|
|
|
<div className='flex-grow basis-1/2'>
|
|
|
|
|
<div className='flex items-center justify-between'>
|
2024-03-27 22:54:24 +03:00
|
|
|
|
<Label text={schema1 !== schema2 ? schema1?.alias ?? 'Схема 1' : ''} />
|
2024-04-03 19:31:26 +03:00
|
|
|
|
<div className='cc-icons'>
|
2024-03-24 19:25:42 +03:00
|
|
|
|
<MiniButton
|
|
|
|
|
title='Сохранить конституенту'
|
|
|
|
|
noHover
|
|
|
|
|
onClick={toggleDelete}
|
|
|
|
|
icon={
|
|
|
|
|
deleteRight ? (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepAliasOn size='1rem' className='clr-text-green' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
) : (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepAliasOff size='1rem' className='clr-text-red' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<MiniButton
|
|
|
|
|
title='Сохранить термин'
|
|
|
|
|
noHover
|
|
|
|
|
onClick={toggleTerm}
|
|
|
|
|
icon={
|
|
|
|
|
takeLeftTerm ? (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepTermOn size='1rem' className='clr-text-green' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
) : (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepTermOff size='1rem' className='clr-text-red' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<ConstituentaSelector
|
|
|
|
|
items={schema1?.items.filter(cst => !filter1 || filter1(cst))}
|
|
|
|
|
value={leftCst}
|
|
|
|
|
onSelectValue={setLeftCst}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<MiniButton
|
|
|
|
|
noHover
|
|
|
|
|
title='Добавить в таблицу отождествлений'
|
|
|
|
|
className='mb-[0.375rem] grow-0'
|
2024-04-03 21:05:53 +03:00
|
|
|
|
icon={<IconReplace size='1.5rem' className='icon-primary' />}
|
2024-04-03 19:31:26 +03:00
|
|
|
|
disabled={!leftCst || !rightCst || leftCst === rightCst}
|
2024-03-24 19:25:42 +03:00
|
|
|
|
onClick={addSubstitution}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div className='flex-grow basis-1/2'>
|
|
|
|
|
<div className='flex items-center justify-between'>
|
2024-03-27 22:54:24 +03:00
|
|
|
|
<Label text={schema1 !== schema2 ? schema2?.alias ?? 'Схема 2' : ''} />
|
2024-04-03 19:31:26 +03:00
|
|
|
|
<div className='cc-icons'>
|
2024-03-24 19:25:42 +03:00
|
|
|
|
<MiniButton
|
|
|
|
|
title='Сохранить конституенту'
|
|
|
|
|
noHover
|
|
|
|
|
onClick={toggleDelete}
|
|
|
|
|
icon={
|
|
|
|
|
!deleteRight ? (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepAliasOn size='1rem' className='clr-text-green' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
) : (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepAliasOff size='1rem' className='clr-text-red' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<MiniButton
|
|
|
|
|
title='Сохранить термин'
|
|
|
|
|
noHover
|
|
|
|
|
onClick={toggleTerm}
|
|
|
|
|
icon={
|
|
|
|
|
!takeLeftTerm ? (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepTermOn size='1rem' className='clr-text-green' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
) : (
|
2024-05-02 19:13:54 +03:00
|
|
|
|
<IconKeepTermOff size='1rem' className='clr-text-red' />
|
2024-03-24 19:25:42 +03:00
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<ConstituentaSelector
|
|
|
|
|
items={schema2?.items.filter(cst => !filter2 || filter2(cst))}
|
|
|
|
|
value={rightCst}
|
|
|
|
|
onSelectValue={setRightCst}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<DataTable
|
|
|
|
|
dense
|
2024-03-27 22:54:24 +03:00
|
|
|
|
noHeader
|
2024-03-24 19:25:42 +03:00
|
|
|
|
noFooter
|
2024-03-27 22:54:24 +03:00
|
|
|
|
className='w-full overflow-y-auto text-sm border select-none'
|
2024-03-24 19:25:42 +03:00
|
|
|
|
rows={rows}
|
|
|
|
|
contentHeight='1.3rem'
|
|
|
|
|
data={items}
|
|
|
|
|
columns={columns}
|
|
|
|
|
headPosition='0'
|
|
|
|
|
noDataComponent={
|
|
|
|
|
<span className='p-2 text-center min-h-[2rem]'>
|
|
|
|
|
<p>Список пуст</p>
|
|
|
|
|
<p>Добавьте отождествление</p>
|
|
|
|
|
</span>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default SubstitutionsPicker;
|