ConceptPortal-public/rsconcept/frontend/src/pages/RSFormPage/ViewConstituents/ConstituentsTable.tsx

139 lines
3.7 KiB
TypeScript
Raw Normal View History

'use client';
import clsx from 'clsx';
2023-12-08 19:24:08 +03:00
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
import DataTable, { createColumnHelper,IConditionalStyle, VisibilityState } from '@/components/DataTable';
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 {
items: IConstituenta[]
activeID?: number
onOpenEdit: (cstID: number) => void
denseThreshold?: number
2023-12-17 20:19:28 +03:00
maxHeight: string
2023-12-08 19:24:08 +03:00
}
const columnHelper = createColumnHelper<IConstituenta>();
function ConstituentsTable({
items, activeID, onOpenEdit,
2023-12-17 20:19:28 +03:00
maxHeight,
2023-12-08 19:24:08 +03:00
denseThreshold = 9999
}: ConstituentsTableProps) {
const { colors } = useConceptTheme();
const windowSize = useWindowSize();
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({'expression': true});
useLayoutEffect(
() => {
setColumnVisibility(prev => {
const newValue = (windowSize.width ?? 0) >= denseThreshold;
if (newValue === prev['expression']) {
return prev;
} else {
return {'expression': newValue}
}
});
}, [windowSize, denseThreshold]);
const handleRowClicked = useCallback(
(cst: IConstituenta) => {
if (!isMockCst(cst)) {
onOpenEdit(cst.id);
}
}, [onOpenEdit]);
const columns = useMemo(
() => [
columnHelper.accessor('alias', {
id: 'alias',
header: 'Имя',
size: 65,
minSize: 65,
footer: undefined,
cell: props =>
<ConstituentaBadge
theme={colors}
value={props.row.original}
prefixID={prefixes.cst_sidetable}
2023-12-08 19:24:08 +03:00
/>
}),
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(
(): IConditionalStyle<IConstituenta>[] => [
{
when: (cst: IConstituenta) => cst.id === activeID,
style: {
backgroundColor: colors.bgSelected
},
}
], [activeID, colors]);
return (
<DataTable dense noFooter
2023-12-17 20:19:28 +03:00
className='overflow-y-auto text-sm select-none overscroll-none'
style={{maxHeight : maxHeight}}
2023-12-08 19:24:08 +03:00
data={items}
columns={columns}
conditionalRowStyles={conditionalRowStyles}
headPosition='0'
enableHiding
columnVisibility={columnVisibility}
onColumnVisibilityChange={setColumnVisibility}
noDataComponent={
<div className={clsx(
'min-h-[5rem]',
2023-12-17 20:19:28 +03:00
'p-2',
'text-center',
'select-none'
)}>
2023-12-08 19:24:08 +03:00
<p>Список конституент пуст</p>
<p>Измените параметры фильтра</p>
</div>
2023-12-08 19:24:08 +03:00
}
onRowClicked={handleRowClicked}
/>);
}
export default ConstituentsTable;