2023-12-13 14:32:57 +03:00
|
|
|
|
'use client';
|
|
|
|
|
|
2023-12-15 17:34:50 +03:00
|
|
|
|
import clsx from 'clsx';
|
2023-12-08 19:24:08 +03:00
|
|
|
|
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
|
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '@/components/DataTable';
|
2023-12-13 14:32:57 +03:00
|
|
|
|
import ConstituentaBadge from '@/components/Shared/ConstituentaBadge';
|
|
|
|
|
import { useConceptTheme } from '@/context/ThemeContext';
|
|
|
|
|
import useWindowSize from '@/hooks/useWindowSize';
|
|
|
|
|
import { IConstituenta } from '@/models/rsform';
|
|
|
|
|
import { isMockCst } from '@/models/rsformAPI';
|
|
|
|
|
import { prefixes } from '@/utils/constants';
|
|
|
|
|
import { describeConstituenta } from '@/utils/labels';
|
2023-12-08 19:24:08 +03:00
|
|
|
|
|
|
|
|
|
interface ConstituentsTableProps {
|
2023-12-28 14:04:44 +03:00
|
|
|
|
items: IConstituenta[];
|
|
|
|
|
activeID?: number;
|
|
|
|
|
onOpenEdit: (cstID: number) => void;
|
|
|
|
|
denseThreshold?: number;
|
|
|
|
|
maxHeight: string;
|
2023-12-08 19:24:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const columnHelper = createColumnHelper<IConstituenta>();
|
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
|
function ConstituentsTable({ items, activeID, onOpenEdit, maxHeight, denseThreshold = 9999 }: ConstituentsTableProps) {
|
2023-12-08 19:24:08 +03:00
|
|
|
|
const { colors } = useConceptTheme();
|
|
|
|
|
const windowSize = useWindowSize();
|
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({ expression: true });
|
2023-12-08 19:24:08 +03:00
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
|
useLayoutEffect(() => {
|
2023-12-08 19:24:08 +03:00
|
|
|
|
setColumnVisibility(prev => {
|
|
|
|
|
const newValue = (windowSize.width ?? 0) >= denseThreshold;
|
|
|
|
|
if (newValue === prev['expression']) {
|
|
|
|
|
return prev;
|
|
|
|
|
} else {
|
2023-12-28 14:04:44 +03:00
|
|
|
|
return { expression: newValue };
|
2023-12-08 19:24:08 +03:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}, [windowSize, denseThreshold]);
|
|
|
|
|
|
|
|
|
|
const handleRowClicked = useCallback(
|
2023-12-28 14:04:44 +03:00
|
|
|
|
(cst: IConstituenta) => {
|
|
|
|
|
if (!isMockCst(cst)) {
|
|
|
|
|
onOpenEdit(cst.id);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
[onOpenEdit]
|
|
|
|
|
);
|
2023-12-08 19:24:08 +03:00
|
|
|
|
|
|
|
|
|
const columns = useMemo(
|
2023-12-28 14:04:44 +03:00
|
|
|
|
() => [
|
|
|
|
|
columnHelper.accessor('alias', {
|
|
|
|
|
id: 'alias',
|
|
|
|
|
header: 'Имя',
|
|
|
|
|
size: 65,
|
|
|
|
|
minSize: 65,
|
|
|
|
|
footer: undefined,
|
|
|
|
|
cell: props => (
|
|
|
|
|
<ConstituentaBadge theme={colors} value={props.row.original} prefixID={prefixes.cst_side_table} />
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor(cst => describeConstituenta(cst), {
|
|
|
|
|
id: 'description',
|
|
|
|
|
header: 'Описание',
|
|
|
|
|
size: 1000,
|
|
|
|
|
minSize: 250,
|
|
|
|
|
maxSize: 1000,
|
|
|
|
|
cell: props => (
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
color: isMockCst(props.row.original) ? colors.fgWarning : undefined
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{props.getValue()}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor('definition_formal', {
|
|
|
|
|
id: 'expression',
|
|
|
|
|
header: 'Выражение',
|
|
|
|
|
size: 2000,
|
|
|
|
|
minSize: 0,
|
|
|
|
|
maxSize: 2000,
|
|
|
|
|
enableHiding: true,
|
|
|
|
|
cell: props => (
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
color: isMockCst(props.row.original) ? colors.fgWarning : undefined
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{props.getValue()}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
],
|
|
|
|
|
[colors]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const conditionalRowStyles = useMemo(
|
2023-12-08 19:24:08 +03:00
|
|
|
|
(): IConditionalStyle<IConstituenta>[] => [
|
|
|
|
|
{
|
|
|
|
|
when: (cst: IConstituenta) => cst.id === activeID,
|
|
|
|
|
style: {
|
|
|
|
|
backgroundColor: colors.bgSelected
|
2023-12-28 14:04:44 +03:00
|
|
|
|
}
|
2023-12-08 19:24:08 +03:00
|
|
|
|
}
|
2023-12-28 14:04:44 +03:00
|
|
|
|
],
|
|
|
|
|
[activeID, colors]
|
|
|
|
|
);
|
2023-12-08 19:24:08 +03:00
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
|
return (
|
|
|
|
|
<DataTable
|
|
|
|
|
dense
|
|
|
|
|
noFooter
|
|
|
|
|
className='overflow-y-auto text-sm select-none overscroll-none'
|
|
|
|
|
style={{ maxHeight: maxHeight }}
|
|
|
|
|
data={items}
|
|
|
|
|
columns={columns}
|
|
|
|
|
conditionalRowStyles={conditionalRowStyles}
|
|
|
|
|
headPosition='0'
|
|
|
|
|
enableHiding
|
|
|
|
|
columnVisibility={columnVisibility}
|
|
|
|
|
onColumnVisibilityChange={setColumnVisibility}
|
|
|
|
|
noDataComponent={
|
|
|
|
|
<div className={clsx('min-h-[5rem]', 'p-2', 'text-center', 'select-none')}>
|
|
|
|
|
<p>Список конституент пуст</p>
|
|
|
|
|
<p>Измените параметры фильтра</p>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
onRowClicked={handleRowClicked}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2023-12-08 19:24:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-28 14:04:44 +03:00
|
|
|
|
export default ConstituentsTable;
|