154 lines
4.0 KiB
JavaScript
154 lines
4.0 KiB
JavaScript
import React, { useEffect, useRef, useState } from 'react';
|
||
import { createPortal } from 'react-dom';
|
||
import { columns as mockColumns } from '../../mocks/mockTable';
|
||
import { config } from './constants/FORM_2/AHR';
|
||
import { useParams } from 'react-router';
|
||
|
||
function EditCellPortal({
|
||
cell,
|
||
table,
|
||
EditCell,
|
||
onSaveStart,
|
||
onSaveEnd,
|
||
onError,
|
||
isEditable
|
||
}) {
|
||
const { formId, formType, sheetName, direction } = useParams();
|
||
const tableKey = `${formId}_${formType}_${sheetName}_${direction}`;
|
||
const ref = useRef(null);
|
||
const [refTbody, setRefTbody] = useState(false);
|
||
const [isSaving, setIsSaving] = useState(false);
|
||
const isDisabled = false;
|
||
|
||
useEffect(() => {
|
||
if (ref.current) {
|
||
const tbodyRef = ref.current.offsetParent?.offsetParent?.offsetParent;
|
||
setRefTbody(tbodyRef);
|
||
}
|
||
}, []);
|
||
|
||
const handleChange = async (val) => {
|
||
table.setEditingCell(null);
|
||
try {
|
||
if (table.options.meta?.updateCell) {
|
||
const success = await table.options.meta.updateCell(
|
||
cell.row,
|
||
cell.column,
|
||
val
|
||
);
|
||
if (success) {
|
||
console.log('Cell updated successfully via WebSocket');
|
||
} else {
|
||
console.error('Failed to update cell via WebSocket');
|
||
const errorMsg = 'Не удалось сохранить изменение';
|
||
onError?.(errorMsg);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error updating cell:', error);
|
||
onError?.(error.message);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<div
|
||
ref={ref}
|
||
style={{
|
||
width: '100%',
|
||
height: '100%',
|
||
}}
|
||
/>
|
||
{refTbody && !isSaving &&
|
||
createPortal(
|
||
<EditCell
|
||
refCell={ref}
|
||
cell={cell}
|
||
value={cell.getValue()}
|
||
disabled={!isEditable}
|
||
onChange={handleChange}
|
||
tableId={tableKey}
|
||
cellId={cell.row.id + '_' + cell.column.id}
|
||
/>,
|
||
refTbody,
|
||
)}
|
||
{isSaving && (
|
||
createPortal(
|
||
<div style={{
|
||
position: 'absolute',
|
||
background: 'rgba(0,0,0,0.5)',
|
||
color: 'white',
|
||
padding: '4px 8px',
|
||
borderRadius: '4px',
|
||
fontSize: '12px',
|
||
zIndex: 1000
|
||
}}>
|
||
Saving...
|
||
</div>,
|
||
refTbody
|
||
)
|
||
)}
|
||
</>
|
||
);
|
||
}
|
||
|
||
export const getTableColumns = ({
|
||
Cell,
|
||
EditCell,
|
||
columnsConfig,
|
||
onCellUpdateError,
|
||
onCellNumberClick
|
||
}) => {
|
||
const columnColors = { ...columnsConfig.colors };
|
||
const columns = [...columnsConfig.columns];
|
||
|
||
const processColumns = (columns, EditCell, Cell) => {
|
||
columns.forEach((col) => {
|
||
col.Cell = ({ cell, table, column, row }) => (
|
||
<Cell
|
||
row={row}
|
||
column={column}
|
||
cell={cell}
|
||
globalFilter={
|
||
table.getState().globalFilter
|
||
}
|
||
isEditable={row.original?.row_type === 'INPUT' || false}
|
||
backgroundColor={columnColors[column.id]?.color_type?.[row.original?.row_type || row.row_type]}
|
||
color={columnColors[column.id]?.color_type?.['COLOR']}
|
||
isUpdating={table.options.meta?.updatingCells?.[`${row.id}_${column.id}`]}
|
||
/>
|
||
);
|
||
|
||
col.Edit = ({ cell, table, row, column }) => (
|
||
<EditCellPortal
|
||
cell={cell}
|
||
table={table}
|
||
EditCell={EditCell}
|
||
onError={onCellUpdateError}
|
||
isEditable={row.original?.row_type === 'INPUT' || false}
|
||
/>
|
||
);
|
||
|
||
// Рекурсивно обрабатываем вложенные колонки
|
||
if (col.columns?.length) {
|
||
processColumns(col.columns, EditCell, Cell);
|
||
}
|
||
});
|
||
};
|
||
|
||
processColumns(columns, EditCell, Cell);
|
||
|
||
const rowNumber = {
|
||
accessorKey: 'sort_order',
|
||
header: '#',
|
||
size: 50,
|
||
enableEditing: false,
|
||
Cell: ({ cell, row }) => {
|
||
return <button onClick={() => { onCellNumberClick(row.id) }}>
|
||
{cell.getValue() + ' '}
|
||
</button>
|
||
},
|
||
};
|
||
|
||
return [rowNumber, ...columns];
|
||
}; |