PotapovaA cf42e23fcb fix
2026-08-13 16:49:38 +03:00

288 lines
6.8 KiB
JavaScript

import { Box, Checkbox, Typography, styled } from '@mui/material';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { ROLES_NAME_ID } from '../../../../constants/constants';
import { ROLES_ID_RUSSIAN_NAME_ARRAY as ROLES, ROLES_ID_NAME } from '../../../../constants/constants';
import { CheckIcon, CheckedIcon, IndeterminateIcon } from '../../IconsForTable/icons';
import SelectWithOptions from '../../components/SelectWithOptions';
import StyledTable from '../../components/StyledTable/StyledTable';
import { createFilterData } from '../../utils/filters';
import DepartmentCell from './DepartmentCell';
import RowActionsMenu from './RowActionMenu';
const StyledCheckbox = styled(Checkbox)({
padding: '0',
svg: {
width: '1rem',
height: '1rem',
},
});
const UserTable = ({
data = [],
onEdit,
onEditSsp,
onDelete,
filterString,
ssp,
roleId,
onRoleChange,
onSelectedUsers,
selectedUsersId,
// Пропсы высоты
maxHeight = 'calc(100vh - 17rem)',
loading = false,
}) => {
const [selectedUsers, setSelectedUsers] = useState(new Set());
useEffect(() => {
setSelectedUsers(selectedUsersId);
}, [selectedUsersId]);
const filteredData = useMemo(() => {
const filterFunc = createFilterData({
search: filterString,
ssp_id: ssp?.id,
role_id: roleId,
});
return data.filter(filterFunc);
}, [data, filterString, ssp, roleId]);
const handleEditSsp = useCallback(
(user) => {
if (user) {
onEditSsp?.(user);
}
},
[onEditSsp],
);
const handleEdit = (user) => {
if (user) {
onEdit?.(user);
}
};
const handleDelete = (user) => {
if (user) {
onDelete?.(user);
}
};
const handleSelectUser = useCallback(
(userId) => {
const newSelectedUsers = new Set(selectedUsers);
if (newSelectedUsers.has(userId)) {
newSelectedUsers.delete(userId);
} else {
newSelectedUsers.add(userId);
}
setSelectedUsers(newSelectedUsers);
onSelectedUsers(newSelectedUsers);
},
[selectedUsers, onSelectedUsers],
);
const handleSelectAll = useCallback(() => {
if (selectedUsers.size === filteredData.length) {
setSelectedUsers(new Set());
onSelectedUsers(new Set());
} else {
const userIds = new Set(filteredData.map((user) => user.id));
setSelectedUsers(userIds);
onSelectedUsers(userIds);
}
}, [filteredData, selectedUsers.size]);
const handleRoleChange = useCallback(
(user, role) => {
user.role_id = ROLES_NAME_ID[role];
onRoleChange(user);
},
[onRoleChange],
);
const columns = useMemo(
() => [
{
id: 'selection',
header: (
<Box>
<StyledCheckbox
checked={selectedUsers.size === filteredData.length && filteredData.length > 0}
indeterminate={selectedUsers.size > 0 && selectedUsers.size < filteredData.length}
onChange={handleSelectAll}
size='small'
icon={<CheckIcon />}
checkedIcon={<CheckedIcon />}
indeterminateIcon={<IndeterminateIcon />}
/>
</Box>
),
Cell: ({ row }) => (
<Box>
<StyledCheckbox
checked={!!selectedUsers.has(row.original.id)}
onChange={() => handleSelectUser(row.original.id)}
size='16'
icon={<CheckIcon />}
checkedIcon={<CheckedIcon />}
/>
</Box>
),
muiTableHeadCellProps: {
sx: {
boxSizing: 'border-box',
width: '2.75rem',
minWidth: '2.75rem',
maxWidth: '2.75rem',
},
},
muiTableBodyCellProps: {
sx: {
boxSizing: 'border-box',
width: '2.75rem',
minWidth: '2.75rem',
maxWidth: '2.75rem',
},
},
enableEditing: false,
enableSorting: false,
enableColumnFilter: false,
enableColumnActions: false,
enableHiding: false,
},
{
accessorKey: 'id',
header: 'ID',
size: 50,
enableHiding: false,
enableEditing: false,
enableColumnActions: false,
},
{
accessorKey: 'user_info',
header: 'Пользователь',
muiTableHeadCellProps: {
sx: {
boxSizing: 'border-box',
width: '26.75rem',
minWidth: '26.75rem',
maxWidth: '26.75rem',
},
},
muiTableBodyCellProps: {
sx: {
boxSizing: 'border-box',
width: '26.75rem',
minWidth: '26.75rem',
maxWidth: '26.75rem',
},
},
Cell: ({ row }) => (
<Box sx={{ display: 'flex', gap: '.5rem', flexDirection: 'column' }}>
<Typography variant='body2' component='div' sx={{ fontWeight: 'medium' }}>
{row.original.full_name}
</Typography>
<Typography
variant='body2'
component='div'
sx={{
fontSize: '0.75rem',
lineHeight: '150%',
color: '#4A5565',
}}>
{row.original.email}
</Typography>
</Box>
),
enableEditing: false,
enableColumnActions: false,
},
{
accessorKey: 'role_id',
header: 'Роль',
muiTableHeadCellProps: {
sx: {
boxSizing: 'border-box',
width: '18.75rem',
minWidth: '18.75rem',
maxWidth: '18.75rem',
},
},
muiTableBodyCellProps: {
sx: {
boxSizing: 'border-box',
width: '18.75rem',
minWidth: '18.75rem',
maxWidth: '18.75rem',
},
},
Cell: ({ cell, row }) => (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<SelectWithOptions
value={cell.getValue()}
options={ROLES}
width='11.25rem'
placeholder='Роль'
onChange={(selectedId) => {
handleRoleChange(row.original, ROLES_ID_NAME[selectedId]);
}}
/>
</Box>
),
enableColumnActions: false,
},
{
accessorKey: 'org_units',
header: 'Подразделения',
muiTableHeadCellProps: {
sx: {
boxSizing: 'border-box',
width: '40.75rem',
minWidth: '40.75rem',
maxWidth: '40.75rem',
},
},
muiTableBodyCellProps: {
sx: {
boxSizing: 'border-box',
width: '40.75rem',
minWidth: '40.75rem',
maxWidth: '40.75rem',
},
},
Cell: ({ cell, row }) => <DepartmentCell values={cell.getValue()} user={row.original} onEdit={handleEditSsp} />,
enableColumnActions: false,
},
],
[selectedUsers, filteredData.length, handleSelectAll, handleSelectUser, handleRoleChange, handleEditSsp],
);
return (
<StyledTable
columns={columns}
data={filteredData}
maxHeight={maxHeight}
containerHeight={maxHeight}
minHeight={maxHeight}
loading={loading}
enableRowActions={true}
renderRowActions={({ row }) => <RowActionsMenu row={row} onEditSsp={onEditSsp} onEdit={handleEdit} onDelete={handleDelete} />}
positionActionsColumn='last'
// Начальное состояние
initialState={{
columnVisibility: { id: false },
}}
tableOptions={{
displayColumnDefOptions: {
'mrt-row-actions': {
header: '',
},
},
}}
/>
);
};
export default UserTable;