import { Box, IconButton, Stack, Typography } from '@mui/material'; import { MaterialReactTable, useMaterialReactTable } from 'material-react-table'; import { memo, useMemo, useRef } from 'react'; import { useAuth } from '../../../app/context/AuthProvider'; import { PrimaryButton, PrimaryOutlinedButton } from '../../../components/common/Buttons/Buttons'; import { EditPenSvg } from '../../../components/common/icons/icons'; import { ROLES_NAME_ID } from '../../../constants/constants'; import { filterVspBySsp } from '../utils/filterVspBySsp'; const ROW_ESTIMATED_HEIGHT = 54; const TableDictVsp = ({ data, onEditClick, onAddClick, onExportClick, loading = false, selectedSsp }) => { const { user } = useAuth(); const tableContainerRef = useRef(null); const filteredData = useMemo(() => filterVspBySsp(data, selectedSsp), [data, selectedSsp]); const columns = useMemo( () => [ { accessorKey: 'index', header: '№', size: 60, minSize: 50, maxSize: 70, enableColumnActions: false, enableSorting: false, Cell: ({ row }) => ( {row.index + 1} ), }, { accessorKey: 'system_code', header: 'Код РФ', size: 110, minSize: 90, maxSize: 140, Cell: ({ cell }) => ( {cell.getValue() || '-'} ), enableColumnActions: false, enableSorting: false, }, { accessorKey: 'registration_number', header: 'Регистрационный номер ВСП', size: 250, minSize: 200, maxSize: 300, Cell: ({ cell }) => ( {cell.getValue() || '-'} ), enableColumnActions: false, enableSorting: false, }, { accessorKey: 'regional_branch', header: 'Региональный филиал/ССП', size: 230, minSize: 180, maxSize: 300, Cell: ({ cell }) => {cell.getValue() || '-'}, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'vsp_type', header: 'Тип ВСП', size: 120, minSize: 100, maxSize: 150, Cell: ({ cell }) => {cell.getValue() || '-'}, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'address', header: 'Адрес объекта', size: 300, minSize: 200, maxSize: 500, Cell: ({ cell }) => {cell.getValue() || '-'}, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'approved_format', header: 'Утверждённый формат', size: 190, minSize: 160, maxSize: 240, Cell: ({ cell }) => {cell.getValue() || '-'}, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'open_date', header: 'Дата открытия ВСП', size: 180, minSize: 150, maxSize: 220, Cell: ({ cell }) => { const date = cell.getValue(); return {date ? new Date(date).toLocaleDateString('ru-RU') : '-'}; }, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'close_date', header: 'Дата закрытия ВСП', size: 180, minSize: 150, maxSize: 220, Cell: ({ cell }) => { const date = cell.getValue(); return {date ? new Date(date).toLocaleDateString('ru-RU') : '-'}; }, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'placement_type', header: 'Форма расположения ВСП', size: 220, minSize: 180, maxSize: 260, Cell: ({ cell }) => {cell.getValue() || '-'}, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'staff_count', header: 'Штатная численность ВСП', size: 230, minSize: 190, maxSize: 270, Cell: ({ cell }) => { const value = cell.getValue(); return {value !== undefined && value !== null ? value : '-'}; }, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'area', header: 'Площадь', size: 100, minSize: 80, maxSize: 120, Cell: ({ cell }) => {cell.getValue() || '-'}, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'rent_contract_num', header: 'Номер договора', size: 150, minSize: 130, maxSize: 200, Cell: ({ cell }) => {cell.getValue() || '-'}, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'rent_end_date', header: 'Дата окончания договора', size: 230, minSize: 190, maxSize: 270, Cell: ({ cell }) => { const date = cell.getValue(); return {date ? new Date(date).toLocaleDateString('ru-RU') : '-'}; }, enableColumnActions: false, enableSorting: false, }, { accessorKey: 'notes', header: 'Примечания', size: 300, minSize: 200, maxSize: 500, Cell: ({ cell }) => ( {cell.getValue() || '-'} ), enableColumnActions: false, enableSorting: false, }, ], [], ); const table = useMaterialReactTable({ columns, data: filteredData, enableEditing: true, enableRowActions: true, enableTopToolbar: true, enableColumnFilters: false, enableGlobalFilter: false, enableSorting: false, enablePagination: false, enableRowVirtualization: true, // Высоту строк MRT измеряет сам (по умолчанию): «Примечания» многострочные (pre-wrap). rowVirtualizerOptions: { overscan: 5, estimateSize: () => ROW_ESTIMATED_HEIGHT }, positionActionsColumn: 'last', // Включаем изменение размера колонок для лучшего UX при горизонтальном скролле // enableColumnResizing: true, columnResizeMode: 'onChange', enableToolbarInternalActions: false, initialState: { columnPinning: { left: ['index', 'system_code', 'registration_number'], right: ['mrt-row-actions'], }, }, renderTopToolbar: () => ( Справочник объектов Экспортировать {user.role_id == ROLES_NAME_ID.admin && + Добавить объект} ), muiTopToolbarProps: { sx: { backgroundColor: '#F9FAFB', minHeight: 'auto', padding: '1rem 1rem 0 1rem', position: 'sticky', top: 0, zIndex: 10, '& .MuiToolbar-root': { padding: 0, minHeight: 'auto', width: '100%', }, }, }, displayColumnDefOptions: { 'mrt-row-actions': { header: 'Действия', size: 80, muiTableHeadCellProps: { align: 'center', }, muiTableBodyCellProps: { align: 'center', }, }, }, renderRowActions: ({ row }) => ( <> onEditClick(row.original)} sx={{ padding: '4px', '&:hover': { backgroundColor: 'rgba(0, 0, 0, 0.04)', }, }} title='Редактировать'> ), state: { isLoading: loading, }, muiTablePaperProps: { sx: { borderRadius: '.63rem', border: '1px solid #f2f2f2', boxShadow: 'none', overflow: 'hidden', position: 'relative', padding: '20px', width: '100%', }, }, muiTableContainerProps: { ref: tableContainerRef, sx: { maxHeight: 'calc(100vh - 450px)', minHeight: '40rem', width: '100%', marginTop: '1.5rem', overflowX: 'auto', // Включаем горизонтальный скролл overflowY: 'auto', // Вертикальный скролл position: 'relative', // Добавляем индикатор скролла для лучшего UX '&::-webkit-scrollbar': { height: '8px', width: '8px', }, '&::-webkit-scrollbar-track': { backgroundColor: '#f1f1f1', borderRadius: '4px', }, '&::-webkit-scrollbar-thumb': { backgroundColor: '#c1c1c1', borderRadius: '4px', '&:hover': { backgroundColor: '#a8a8a8', }, }, }, }, // Обеспечиваем минимальную ширину таблицы для скролла muiTableProps: { sx: { minWidth: 'max-content', // Таблица будет занимать минимум необходимую ширину width: '100%', }, }, muiTableBodyRowProps: { sx: { '& .MuiTableCell-root': { padding: '0.75rem', }, '&:hover': { backgroundColor: 'white !important', }, '&:hover td::after': { opacity: '0 !important', backgroundColor: 'transparent !important', }, '&:hover .MuiTableCell-root': { backgroundColor: 'white !important', }, }, }, muiTableHeadProps: { sx: { position: 'sticky', top: 0, zIndex: 10, }, }, muiTableHeadRowProps: { sx: { position: 'sticky', backgroundColor: '#F9FAFB', color: '#4A5565', fontSize: '0.88rem', '& .MuiTableCell-root': { padding: '1rem 0.75rem', fontWeight: 'bold', backgroundColor: '#F9FAFB', whiteSpace: 'nowrap', // Заголовки тоже не переносим }, '& .Mui-TableHeadCell-Content': { '& .Mui-TableHeadCell-Content-Labels': { overflow: 'visible', }, '& .MuiSvgIcon-root': { fontSize: '1.2rem', marginLeft: '8px', overflow: 'visible !important', }, }, }, }, muiTableBodyCellProps: { sx: { padding: '0.75rem', fontSize: '0.75rem', lineHeight: '150%', color: '#364153', whiteSpace: 'nowrap', // Предотвращаем перенос текста }, }, muiTableHeadCellProps: { sx: { padding: '1rem 0.75rem', fontSize: 'inherit', fontWeight: 'bold', whiteSpace: 'nowrap', // Заголовки не переносим '& .MuiSvgIcon-root': { fontSize: '1.2rem', marginLeft: '4px', flexShrink: 0, }, }, }, muiBottomToolbarProps: { sx: { display: 'none', }, }, localization: { noRecordsToDisplay: 'Нет данных для отображения', }, }); return ( ); }; export default memo(TableDictVsp);