import { useMemo, useState, useRef } from 'react';
import {
MaterialReactTable,
useMaterialReactTable,
} from 'material-react-table';
import { Box, Typography, IconButton, Button, Stack } from '@mui/material';
import { EditPenSvg } from '../../../components/common/icons/icons';
import ModalEditAddVsp from './Modals/ModalEditAddVsp';
import {
PrimaryButton,
PrimaryOutlinedButton,
} from '../../../components/common/Buttons/Buttons';
import { useAuth } from '../../../app/context/AuthProvider';
import { ROLES_NAME_ID } from '../../../constants';
import ModalExport from './Modals/ModalExport';
const TableDictVsp = ({
data,
onEdit,
onDelete,
onAdd,
loading = false,
ssps,
selectedSsp,
}) => {
const { user } = useAuth();
const [modalOpen, setModalOpen] = useState(false);
const [modalExportOpen, setModalExportOpen] = useState(false);
const [editingItem, setEditingItem] = useState(null);
const [saveLoading, setSaveLoading] = useState(false);
const tableContainerRef = useRef(null);
const filteredData = useMemo(() => {
if (!selectedSsp) {
return data;
}
return data.filter((item) => item.ssp_id === selectedSsp.id);
}, [data, selectedSsp]);
const handleEdit = (item) => {
setEditingItem(item);
setModalOpen(true);
};
const handleAdd = () => {
setEditingItem(null);
setModalOpen(true);
};
const handleExport = () => [setModalExportOpen(true)];
const handleSave = async (formData) => {
setSaveLoading(true);
try {
if (editingItem) {
await onEdit?.({ ...formData, id: editingItem.id });
} else {
await onAdd?.(formData);
}
setModalOpen(false);
} catch (error) {
console.error('Error saving:', error);
} finally {
setSaveLoading(false);
}
};
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: 180,
minSize: 50,
maxSize: 100,
Cell: ({ cell }) => (
{cell.getValue() || '-'}
),
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'registration_number',
header: 'Регистрационный номер ВСП',
size: 180,
minSize: 150,
maxSize: 200,
Cell: ({ cell }) => (
{cell.getValue() || '-'}
),
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'ssp_id',
header: 'Региональный филиал/ССП',
size: 120,
minSize: 100,
maxSize: 150,
Cell: ({ cell }) => (
{cell.getValue()
? ssps.find((s) => s.id == cell.getValue())?.title
: '-'}
),
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: 250,
minSize: 200,
maxSize: 350,
Cell: ({ cell }) => (
{cell.getValue() || '-'}
),
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'approved_format',
header: 'Утверждённый формат',
size: 150,
minSize: 120,
maxSize: 180,
Cell: ({ cell }) => (
{cell.getValue() || '-'}
),
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'open_date',
header: 'Дата открытия ВСП',
size: 130,
minSize: 110,
maxSize: 150,
Cell: ({ cell }) => {
const date = cell.getValue();
return (
{date ? new Date(date).toLocaleDateString('ru-RU') : '-'}
);
},
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'close_date',
header: 'Дата закрытия ВСП',
size: 130,
minSize: 110,
maxSize: 150,
Cell: ({ cell }) => {
const date = cell.getValue();
return (
{date ? new Date(date).toLocaleDateString('ru-RU') : '-'}
);
},
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'location_form',
header: 'Форма расположения ВСП',
size: 170,
minSize: 140,
maxSize: 200,
Cell: ({ cell }) => (
{cell.getValue() || '-'}
),
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'numbers',
header: 'Штатная численность ВСП',
size: 170,
minSize: 140,
maxSize: 200,
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: 130,
minSize: 110,
maxSize: 160,
Cell: ({ cell }) => (
{cell.getValue() || '-'}
),
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'rent_end_date',
header: 'Дата окончания договора',
size: 150,
minSize: 130,
maxSize: 170,
Cell: ({ cell }) => {
const date = cell.getValue();
return (
{date ? new Date(date).toLocaleDateString('ru-RU') : '-'}
);
},
enableColumnActions: false,
enableSorting: false,
},
{
accessorKey: 'notes',
header: 'Примечания',
size: 200,
minSize: 150,
maxSize: 300,
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,
positionActionsColumn: 'last',
// Включаем изменение размера колонок для лучшего UX при горизонтальном скролле
// enableColumnResizing: true,
columnResizeMode: 'onChange',
enableToolbarInternalActions: false,
initialState: {
columnPinning: {
left: ['index', 'system_code', 'registration_number'],
right: ['mrt-row-actions'],
},
},
renderTopToolbarCustomActions: () => (
Справочник объектов
Экспортировать
{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',
},
},
},
displayColumnDefOptions: {
'mrt-row-actions': {
header: 'Действия',
size: 80,
muiTableHeadCellProps: {
align: 'center',
},
muiTableBodyCellProps: {
align: 'center',
},
},
},
renderRowActions: ({ row }) => (
<>
handleEdit(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',
padding: 0,
boxShadow: 'none',
overflow: 'hidden',
position: 'relative',
},
},
muiTableContainerProps: {
ref: tableContainerRef,
sx: {
maxHeight: 'calc(100vh - 450px)',
minHeight: '50rem',
maxWidth: '100rem',
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',
},
},
});
return (
<>
setModalOpen(false)}
onSave={handleSave}
onDelete={onDelete}
initialData={editingItem}
loading={saveLoading}
ssps={ssps}
/>
setModalExportOpen(false)}
ssps={ssps}
/>
>
);
};
export default TableDictVsp;