fixes-front-sort-order #39
@ -134,6 +134,11 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
||||
return () => document.removeEventListener('mousedown', handleDocumentClick);
|
||||
}, [selectedColumnId]);
|
||||
|
||||
const handleCellUpdateError = useCallback((rowId, columnId, error) => {
|
||||
console.error(`Error updating cell ${rowId}_${columnId}:`, error);
|
||||
toast.error('Ошибка обновления ячейки');
|
||||
}, []);
|
||||
|
||||
const columns = useMemo(() => {
|
||||
if (!columnsConfig || !columnsConfig.columns) return [];
|
||||
try {
|
||||
@ -143,128 +148,160 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
||||
columnsConfig,
|
||||
onCellUpdate: handleUpdateCell,
|
||||
onCellNumberClick: handleClickRowCell,
|
||||
onCellUpdateError: (rowId, columnId, error) => {
|
||||
console.error(`Error updating cell ${rowId}_${columnId}:`, error);
|
||||
toast.error('Ошибка обновления ячейки')
|
||||
}
|
||||
onCellUpdateError: handleCellUpdateError,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error creating columns:', error);
|
||||
return [];
|
||||
}
|
||||
}, [columnsConfig, handleUpdateCell, handleClickRowCell]);
|
||||
}, [columnsConfig, handleUpdateCell, handleClickRowCell, handleCellUpdateError]);
|
||||
|
||||
const selectedColumnIdRef = useRef(selectedColumnId);
|
||||
|
||||
useEffect(() => {
|
||||
selectedColumnIdRef.current = selectedColumnId;
|
||||
}, [selectedColumnId]);
|
||||
|
||||
const tableMeta = useMemo(() => ({
|
||||
updateCell: handleUpdateCell,
|
||||
selectedColumnId,
|
||||
}), [handleUpdateCell, selectedColumnId]);
|
||||
getSelectedColumnId: () => selectedColumnIdRef.current,
|
||||
}), [handleUpdateCell]);
|
||||
|
||||
// Конфигурация таблицы
|
||||
const tableConfig = useMemo(
|
||||
() => ({
|
||||
...BASE_TABLE_CONFIG,
|
||||
columns,
|
||||
data: data,
|
||||
enableRowVirtualization: true,
|
||||
enableColumnVirtualization: true,
|
||||
rowVirtualizerInstanceRef: rowVirtualizerRef,
|
||||
rowVirtualizerOptions: {
|
||||
overscan: 30,
|
||||
scrollPaddingStart: 0,
|
||||
scrollPaddingEnd: 0,
|
||||
estimateSize: () => TABLE_ROW_HEIGHT,
|
||||
measureElement: (el) => el?.offsetHeight || TABLE_ROW_HEIGHT,
|
||||
},
|
||||
onEditingCellChange: (cell) => {
|
||||
if (cell) {
|
||||
if (editingCell) return;
|
||||
contextStartEditing?.(cell.row, cell.column);
|
||||
const ROW_VIRTUALIZER_OPTIONS = {
|
||||
overscan: 30,
|
||||
scrollPaddingStart: 0,
|
||||
scrollPaddingEnd: 0,
|
||||
estimateSize: () => TABLE_ROW_HEIGHT,
|
||||
measureElement: (el) => el?.offsetHeight || TABLE_ROW_HEIGHT,
|
||||
};
|
||||
|
||||
const createTableConfig = ({
|
||||
columns,
|
||||
data,
|
||||
columnSizing,
|
||||
columnPinning,
|
||||
columnVisibility,
|
||||
globalFilter,
|
||||
showColumnFilters,
|
||||
rowSelection,
|
||||
containerRef,
|
||||
tableMeta,
|
||||
setColumnSizing,
|
||||
setColumnPinning,
|
||||
editingCell,
|
||||
contextStartEditing,
|
||||
}) => ({
|
||||
...BASE_TABLE_CONFIG,
|
||||
columns,
|
||||
data,
|
||||
enableRowVirtualization: true,
|
||||
enableColumnVirtualization: true,
|
||||
rowVirtualizerInstanceRef: rowVirtualizerRef,
|
||||
rowVirtualizerOptions: ROW_VIRTUALIZER_OPTIONS,
|
||||
onEditingCellChange: (cell) => {
|
||||
if (cell && !editingCell) {
|
||||
contextStartEditing?.(cell.row, cell.column);
|
||||
}
|
||||
},
|
||||
columnVirtualizerOptions: ({ table }) => ({
|
||||
overscan: 10,
|
||||
measureElement: (el) => {
|
||||
if (!el) return 150;
|
||||
const index = Number(el?.getAttribute?.('data-index'));
|
||||
const isPinned = Boolean(el?.getAttribute?.('data-pinned'));
|
||||
if (isPinned) {
|
||||
const colId = table.getState().columnPinning.left[index];
|
||||
const column = table.getColumn(colId);
|
||||
return column?.getSize() ?? 150;
|
||||
}
|
||||
},
|
||||
columnVirtualizerOptions: ({ table }) => ({
|
||||
overscan: 10,
|
||||
measureElement: (el) => {
|
||||
if (!el) return 150;
|
||||
const index = Number(el?.getAttribute?.('data-index'));
|
||||
const isPinned = Boolean(el?.getAttribute?.('data-pinned'));
|
||||
if (isPinned) {
|
||||
const colId = table.getState().columnPinning.left[index];
|
||||
const column = table.getColumn(colId);
|
||||
return column?.getSize() ?? 150;
|
||||
}
|
||||
const allCols = [...table.getLeftVisibleLeafColumns(), ...table.getCenterVisibleLeafColumns()]
|
||||
return allCols[index]?.getSize() ?? 150;
|
||||
|
||||
},
|
||||
}),
|
||||
enableRowSelection: true,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onColumnSizingChange: setColumnSizing,
|
||||
onColumnPinningChange: setColumnPinning,
|
||||
onGlobalFilterChange: handleGlobalFilterChange,
|
||||
state: {
|
||||
columnSizing,
|
||||
columnPinning,
|
||||
columnVisibility,
|
||||
globalFilter,
|
||||
showColumnFilters,
|
||||
rowSelection,
|
||||
editingCell,
|
||||
},
|
||||
initialState: {
|
||||
expanded: true,
|
||||
},
|
||||
meta: tableMeta,
|
||||
muiTableHeadCellProps: {
|
||||
sx: { boxSizing: 'border-box' },
|
||||
},
|
||||
muiTableBodyCellProps: getTableBodyCellProps,
|
||||
muiTableHeadProps: {
|
||||
sx: {
|
||||
display: 'table-header-group',
|
||||
height: '1px',
|
||||
minHeight: '1px',
|
||||
maxHeight: '1px',
|
||||
visibility: 'hidden',
|
||||
'& svg': {
|
||||
height: '1px',
|
||||
minHeight: '1px',
|
||||
maxHeight: '1px',
|
||||
visibility: 'hidden',
|
||||
}
|
||||
},
|
||||
},
|
||||
muiTablePaperProps: getTablePaperStyles(),
|
||||
muiTableContainerProps: {
|
||||
ref: containerRef,
|
||||
sx: {
|
||||
position: 'relative',
|
||||
contain: 'layout',
|
||||
minHeight: '100%',
|
||||
'& .MuiTable-root': { position: 'relative' },
|
||||
},
|
||||
},
|
||||
muiTableHeadCellFilterTextFieldProps: {
|
||||
placeholder: 'Поиск...',
|
||||
size: 'small',
|
||||
const allCols = [...table.getLeftVisibleLeafColumns(), ...table.getCenterVisibleLeafColumns()]
|
||||
return allCols[index]?.getSize() ?? 150;
|
||||
},
|
||||
}),
|
||||
[
|
||||
columns,
|
||||
data,
|
||||
setColumnSizing,
|
||||
setColumnPinning,
|
||||
enableRowSelection: true,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onColumnSizingChange: setColumnSizing,
|
||||
onColumnPinningChange: setColumnPinning,
|
||||
onGlobalFilterChange: handleGlobalFilterChange,
|
||||
state: {
|
||||
columnSizing,
|
||||
columnPinning,
|
||||
columnVisibility,
|
||||
globalFilter,
|
||||
showColumnFilters,
|
||||
containerRef,
|
||||
tableMeta,
|
||||
rowSelection,
|
||||
editingCell
|
||||
],
|
||||
);
|
||||
editingCell,
|
||||
},
|
||||
initialState: {
|
||||
expanded: true,
|
||||
},
|
||||
meta: tableMeta,
|
||||
muiTableHeadCellProps: {
|
||||
sx: { boxSizing: 'border-box' },
|
||||
},
|
||||
muiTableBodyCellProps: getTableBodyCellProps,
|
||||
muiTableHeadProps: {
|
||||
sx: {
|
||||
display: 'table-header-group',
|
||||
height: '1px',
|
||||
minHeight: '1px',
|
||||
maxHeight: '1px',
|
||||
visibility: 'hidden',
|
||||
'& svg': {
|
||||
height: '1px',
|
||||
minHeight: '1px',
|
||||
maxHeight: '1px',
|
||||
visibility: 'hidden',
|
||||
}
|
||||
},
|
||||
},
|
||||
muiTablePaperProps: getTablePaperStyles(),
|
||||
muiTableContainerProps: {
|
||||
ref: containerRef,
|
||||
sx: {
|
||||
position: 'relative',
|
||||
contain: 'layout',
|
||||
minHeight: '100%',
|
||||
'& .MuiTable-root': { position: 'relative' },
|
||||
},
|
||||
},
|
||||
muiTableHeadCellFilterTextFieldProps: {
|
||||
placeholder: 'Поиск...',
|
||||
size: 'small',
|
||||
},
|
||||
});
|
||||
|
||||
// Конфигурация таблицы
|
||||
const tableConfig = useMemo(() => createTableConfig({
|
||||
columns,
|
||||
data,
|
||||
columnSizing,
|
||||
columnPinning,
|
||||
columnVisibility,
|
||||
globalFilter,
|
||||
showColumnFilters,
|
||||
rowSelection,
|
||||
containerRef,
|
||||
tableMeta,
|
||||
setColumnSizing,
|
||||
setColumnPinning,
|
||||
editingCell,
|
||||
contextStartEditing,
|
||||
}), [
|
||||
columns,
|
||||
data,
|
||||
columnSizing,
|
||||
columnPinning,
|
||||
columnVisibility,
|
||||
globalFilter,
|
||||
showColumnFilters,
|
||||
rowSelection,
|
||||
containerRef,
|
||||
tableMeta,
|
||||
setColumnSizing,
|
||||
setColumnPinning,
|
||||
editingCell,
|
||||
]);
|
||||
|
||||
const table = useMaterialReactTable(tableConfig);
|
||||
|
||||
@ -342,6 +379,17 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
||||
setRowSelection({});
|
||||
}, [rowSelection, table])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setData([]);
|
||||
setRowSelection({});
|
||||
setEditingCell(null);
|
||||
if (rowVirtualizerRef.current) {
|
||||
rowVirtualizerRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsPanel
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user