optimization navigationProjectPage
This commit is contained in:
parent
b51b8dc0a5
commit
d9d67a2410
@ -9,7 +9,7 @@ import FormsPage from '../pages/FormsPage';
|
|||||||
import LoginPage from '../pages/LoginPage';
|
import LoginPage from '../pages/LoginPage';
|
||||||
import NewFormTablePage from '../pages/NewFormTablePage.jsx';
|
import NewFormTablePage from '../pages/NewFormTablePage.jsx';
|
||||||
import NewTablePage from '../pages/NewTablePage.jsx';
|
import NewTablePage from '../pages/NewTablePage.jsx';
|
||||||
import SummaryPage from '../pages/ProjectPages/SummaryPage.jsx';
|
import NavigationProjectPage from '../pages/ProjectPages/NavigationProjectPage.jsx';
|
||||||
import ProjectsPage from '../pages/ProjectsPage/ProjectsPage.jsx';
|
import ProjectsPage from '../pages/ProjectsPage/ProjectsPage.jsx';
|
||||||
import SvodPage from '../pages/SvodPage/SvodPage.jsx';
|
import SvodPage from '../pages/SvodPage/SvodPage.jsx';
|
||||||
import TablePage from '../pages/TablePage';
|
import TablePage from '../pages/TablePage';
|
||||||
@ -39,7 +39,7 @@ export const AppRoutes = () => {
|
|||||||
<Route element={<PrivateRoute />}>
|
<Route element={<PrivateRoute />}>
|
||||||
<Route path='/' element={<TasksPage />} />
|
<Route path='/' element={<TasksPage />} />
|
||||||
<Route path='/tasks' element={<TasksPage />} />
|
<Route path='/tasks' element={<TasksPage />} />
|
||||||
<Route path='/projects' element={<SummaryPage />} />
|
<Route path='/projects' element={<NavigationProjectPage />} />
|
||||||
<Route path='/forms' element={<FormsPage />} />
|
<Route path='/forms' element={<FormsPage />} />
|
||||||
<Route path='/task/:taskId' element={<TaskPage />} />
|
<Route path='/task/:taskId' element={<TaskPage />} />
|
||||||
<Route path='/project/:projectId' element={<TaskPage />} />
|
<Route path='/project/:projectId' element={<TaskPage />} />
|
||||||
@ -54,7 +54,7 @@ export const AppRoutes = () => {
|
|||||||
<Route path='/tables-new' element={<TablesTest />} />
|
<Route path='/tables-new' element={<TablesTest />} />
|
||||||
<Route path='/tables/:form/:sheetName' element={<NewFormTablePage />} />
|
<Route path='/tables/:form/:sheetName' element={<NewFormTablePage />} />
|
||||||
<Route path='/table/form/:formId/form-type/:formType/:sheetName/:direction/:year' element={<NewFormTablePage />} />
|
<Route path='/table/form/:formId/form-type/:formType/:sheetName/:direction/:year' element={<NewFormTablePage />} />
|
||||||
<Route path='/project-mock-summary' element={<SummaryPage />} />
|
<Route path='/project-mock-summary' element={<NavigationProjectPage />} />
|
||||||
<Route path='/svod' element={<SvodPage />} />
|
<Route path='/svod' element={<SvodPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { Box, CircularProgress, Paper, Typography } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
import { MaterialReactTable, useMaterialReactTable } from 'material-react-table';
|
|
||||||
import { useEffect, useMemo, useState, useCallback } from 'react';
|
import { useEffect, useMemo, useState, useCallback } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
@ -11,14 +10,15 @@ import { WhitePlus } from '../../components/common/icons/icons';
|
|||||||
import Modal from '../../components/common/Modal/Modal';
|
import Modal from '../../components/common/Modal/Modal';
|
||||||
import { DEFAULT_PROJECT_CONFIG } from '../../constants/projectConfig';
|
import { DEFAULT_PROJECT_CONFIG } from '../../constants/projectConfig';
|
||||||
import { ModalCreateProject } from '../ProjectsPage/ModalCreateProject';
|
import { ModalCreateProject } from '../ProjectsPage/ModalCreateProject';
|
||||||
import { createFirstColumns, secondColumns } from './columns';
|
|
||||||
import EditModal from './components/EditModal/EditModal';
|
import EditModal from './components/EditModal/EditModal';
|
||||||
|
import ProjectsTable from './components/ProjectsTable/ProjectsTable';
|
||||||
|
import ProjectSummaryTable from './components/ProjectSummaryTable/ProjectSummaryTable';
|
||||||
import TableFilters from './components/TableFilters/TableFilters'; // Импортируем компонент фильтров
|
import TableFilters from './components/TableFilters/TableFilters'; // Импортируем компонент фильтров
|
||||||
import { handleNavigateClick } from './utils/tableHandlers';
|
import { handleNavigateClick } from './utils/tableHandlers';
|
||||||
import { useAuth } from '../../app/context/AuthProvider';
|
import { useAuth } from '../../app/context/AuthProvider';
|
||||||
import { ROLES_NAME_ID } from '../../constants/constants';
|
import { ROLES_NAME_ID } from '../../constants/constants';
|
||||||
|
|
||||||
const SummaryPage = () => {
|
const NavigationProjectPage = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [selectedRow, setSelectedRow] = useState(null);
|
const [selectedRow, setSelectedRow] = useState(null);
|
||||||
@ -216,7 +216,7 @@ const SummaryPage = () => {
|
|||||||
};
|
};
|
||||||
}, [selectedRow?.original?.id]);
|
}, [selectedRow?.original?.id]);
|
||||||
|
|
||||||
const getFilteredData = () => {
|
const filteredData = useMemo(() => {
|
||||||
if (isArchiveMode) {
|
if (isArchiveMode) {
|
||||||
return archivedData;
|
return archivedData;
|
||||||
}
|
}
|
||||||
@ -225,6 +225,8 @@ const SummaryPage = () => {
|
|||||||
return tableData;
|
return tableData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const query = searchQuery.toLowerCase().trim();
|
||||||
|
|
||||||
return tableData
|
return tableData
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
if (selectedStatus && item.status !== selectedStatus) {
|
if (selectedStatus && item.status !== selectedStatus) {
|
||||||
@ -237,15 +239,10 @@ const SummaryPage = () => {
|
|||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
if (!searchQuery) {
|
if (!query) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = searchQuery.toLowerCase().trim();
|
|
||||||
|
|
||||||
// Проверяем, совпадает ли родитель
|
|
||||||
const parentMatches = (item.name || '').toLowerCase().includes(query);
|
|
||||||
|
|
||||||
// Фильтруем дочерние элементы - оставляем только те, что совпадают с поиском
|
// Фильтруем дочерние элементы - оставляем только те, что совпадают с поиском
|
||||||
const filteredSubRows = item.sub_rows?.filter((subItem) => (subItem.project || '').toLowerCase().includes(query)) || [];
|
const filteredSubRows = item.sub_rows?.filter((subItem) => (subItem.project || '').toLowerCase().includes(query)) || [];
|
||||||
|
|
||||||
@ -256,32 +253,18 @@ const SummaryPage = () => {
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
if (!searchQuery) {
|
if (!query) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = searchQuery.toLowerCase().trim();
|
|
||||||
const parentMatches = (item.name || '').toLowerCase().includes(query);
|
const parentMatches = (item.name || '').toLowerCase().includes(query);
|
||||||
const hasMatchingChildren = item.sub_rows && item.sub_rows.length > 0;
|
const hasMatchingChildren = item.sub_rows && item.sub_rows.length > 0;
|
||||||
|
|
||||||
return parentMatches || hasMatchingChildren;
|
return parentMatches || hasMatchingChildren;
|
||||||
});
|
});
|
||||||
};
|
}, [archivedData, isArchiveMode, searchQuery, selectedBranch, selectedStatus, tableData]);
|
||||||
const filteredData = getFilteredData();
|
|
||||||
|
|
||||||
const handleRowClick = (row) => {
|
const onEdit = useCallback((row) => {
|
||||||
if (row.depth === 0 && row) {
|
|
||||||
setSelectedRow(row);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const isChildOfSelectedRow = (row) => {
|
|
||||||
if (!selectedRow) return false;
|
|
||||||
const parentRowId = row.parentId;
|
|
||||||
return parentRowId === selectedRow.id;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEdit = (row) => {
|
|
||||||
const isSmeta = row.depth > 0;
|
const isSmeta = row.depth > 0;
|
||||||
const parentProject = isSmeta ? row.getParentRow()?.original : row.original;
|
const parentProject = isSmeta ? row.getParentRow()?.original : row.original;
|
||||||
const projectId = parentProject?.id;
|
const projectId = parentProject?.id;
|
||||||
@ -292,11 +275,11 @@ const SummaryPage = () => {
|
|||||||
_projectFundingByKoDecision: parentProject?.funding_by_ko_decision,
|
_projectFundingByKoDecision: parentProject?.funding_by_ko_decision,
|
||||||
});
|
});
|
||||||
setEditModalOpen(true);
|
setEditModalOpen(true);
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const onNavigate = (row) => {
|
const onNavigate = useCallback((row) => {
|
||||||
handleNavigateClick(row, navigate);
|
handleNavigateClick(row, navigate);
|
||||||
};
|
}, [navigate]);
|
||||||
|
|
||||||
const handleDeleteProject = async () => {
|
const handleDeleteProject = async () => {
|
||||||
if (!projectToDelete?.id) return;
|
if (!projectToDelete?.id) return;
|
||||||
@ -362,243 +345,6 @@ const SummaryPage = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const firstColumns = useMemo(
|
|
||||||
() => createFirstColumns({ onDelete: setProjectToDelete, onEdit, onNavigate, orgUnitNames }),
|
|
||||||
[orgUnitNames],
|
|
||||||
);
|
|
||||||
|
|
||||||
const tableHeadCellStyles = {
|
|
||||||
fontWeight: 700,
|
|
||||||
fontSize: '12px',
|
|
||||||
lineHeight: 1.15,
|
|
||||||
textAlign: 'left',
|
|
||||||
backgroundColor: 'rgb(248, 249, 250)',
|
|
||||||
borderRight: '1px solid #e0e0e0',
|
|
||||||
'&:last-child': {
|
|
||||||
borderRight: 'none',
|
|
||||||
},
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
position: 'sticky',
|
|
||||||
top: 0,
|
|
||||||
boxShadow: 'none',
|
|
||||||
padding: '0.5rem 1rem',
|
|
||||||
'& .MuiTableSortLabel-icon': {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
},
|
|
||||||
'& .MuiTableSortLabel-iconDirectionDesc': {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
},
|
|
||||||
'& .MuiTableSortLabel-iconDirectionAsc': {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const projectsTableOptions = {
|
|
||||||
enableColumnActions: false,
|
|
||||||
enableColumnFilters: false,
|
|
||||||
enablePagination: isArchiveMode,
|
|
||||||
manualPagination: isArchiveMode,
|
|
||||||
enableSorting: true,
|
|
||||||
enableBottomToolbar: isArchiveMode,
|
|
||||||
enableTopToolbar: false,
|
|
||||||
enableExpanding: true,
|
|
||||||
getSubRows: (row) => row.sub_rows,
|
|
||||||
muiTableHeadCellProps: {
|
|
||||||
sx: tableHeadCellStyles,
|
|
||||||
},
|
|
||||||
muiExpandButtonProps: {
|
|
||||||
sx: {
|
|
||||||
width: '1.5rem',
|
|
||||||
height: '1.5rem',
|
|
||||||
minWidth: '1.5rem',
|
|
||||||
'& .MuiSvgIcon-root': {
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
muiTableBodyRowProps: ({ row }) => {
|
|
||||||
const isSelected = selectedRow && row.id === selectedRow.id;
|
|
||||||
const isChild = isChildOfSelectedRow(row);
|
|
||||||
|
|
||||||
return {
|
|
||||||
sx: {
|
|
||||||
backgroundColor: '#ffffff',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'rgb(248, 250, 252)',
|
|
||||||
},
|
|
||||||
'&:hover td::after': {
|
|
||||||
backgroundColor: 'transparent !important',
|
|
||||||
},
|
|
||||||
...(row.depth > 0 && {
|
|
||||||
backgroundColor: 'rgb(252, 252, 253)',
|
|
||||||
}),
|
|
||||||
...((isSelected || isChild) && {
|
|
||||||
backgroundColor: 'rgb(234, 247, 236)',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'rgb(225, 242, 229) !important',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
onClick: () => handleRowClick(row),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
muiTableBodyCellProps: ({ row, column }) => ({
|
|
||||||
sx: {
|
|
||||||
borderRight: '1px solid #e0e0e0',
|
|
||||||
'&:last-child': {
|
|
||||||
borderRight: 'none',
|
|
||||||
},
|
|
||||||
'&:hover td::after': {
|
|
||||||
backgroundColor: 'transparent !important',
|
|
||||||
},
|
|
||||||
textAlign: 'left',
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
padding: '0.5rem 1rem',
|
|
||||||
...(column.id === 'mrt-row-expand' && {
|
|
||||||
width: '1.5rem',
|
|
||||||
maxWidth: '1.5rem',
|
|
||||||
minWidth: '1.5rem',
|
|
||||||
padding: '0.5rem 0.25rem',
|
|
||||||
}),
|
|
||||||
...(column.id === 'project' &&
|
|
||||||
row.depth > 0 && {
|
|
||||||
pl: `${2 + row.depth * 0.5}rem`,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
muiTablePaperProps: {
|
|
||||||
elevation: 0,
|
|
||||||
sx: {
|
|
||||||
border: '1px solid #e0e0e0',
|
|
||||||
borderRadius: '1rem',
|
|
||||||
overflow: 'hidden',
|
|
||||||
height: isArchiveMode ? 'auto' : '45vh',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
muiTableContainerProps: {
|
|
||||||
sx: {
|
|
||||||
flex: 1,
|
|
||||||
overflowX: 'auto',
|
|
||||||
overflowY: isArchiveMode ? 'visible' : 'auto',
|
|
||||||
'& thead': {
|
|
||||||
position: 'sticky',
|
|
||||||
top: 0,
|
|
||||||
zIndex: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const summaryProjectTableOptions = {
|
|
||||||
enableColumnActions: false,
|
|
||||||
enableColumnFilters: false,
|
|
||||||
enablePagination: false,
|
|
||||||
enableSorting: true,
|
|
||||||
enableBottomToolbar: false,
|
|
||||||
enableTopToolbar: false,
|
|
||||||
enableExpanding: false,
|
|
||||||
muiTableBodyRowProps: ({ row }) => ({
|
|
||||||
sx: {
|
|
||||||
backgroundColor: '#ffffff',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'rgb(248, 250, 252)',
|
|
||||||
},
|
|
||||||
'&:hover td::after': {
|
|
||||||
backgroundColor: 'transparent !important',
|
|
||||||
},
|
|
||||||
boxShadow: 'none',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
muiTableHeadCellProps: {
|
|
||||||
sx: tableHeadCellStyles,
|
|
||||||
},
|
|
||||||
muiTableBodyCellProps: ({ column }) => ({
|
|
||||||
sx: {
|
|
||||||
borderRight: '1px solid #e0e0e0',
|
|
||||||
'&:last-child': {
|
|
||||||
borderRight: 'none',
|
|
||||||
},
|
|
||||||
textAlign: 'left',
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
padding: '0.5rem 1rem',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
muiTablePaperProps: {
|
|
||||||
elevation: 0,
|
|
||||||
sx: {
|
|
||||||
border: '1px solid #e0e0e0',
|
|
||||||
borderRadius: '0 0 1rem 1rem',
|
|
||||||
overflow: 'hidden',
|
|
||||||
height: '100%',
|
|
||||||
minHeight: 0,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
muiTableContainerProps: {
|
|
||||||
sx: {
|
|
||||||
flex: 1,
|
|
||||||
overflow: 'auto',
|
|
||||||
'& thead': {
|
|
||||||
position: 'sticky',
|
|
||||||
top: 0,
|
|
||||||
zIndex: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
initialState: {
|
|
||||||
columnPinning: { left: ['project'] },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const projectsTable = useMaterialReactTable({
|
|
||||||
columns: firstColumns,
|
|
||||||
data: filteredData,
|
|
||||||
...projectsTableOptions,
|
|
||||||
localization: {
|
|
||||||
expand: 'Раскрыть',
|
|
||||||
expandAll: 'Раскрыть все',
|
|
||||||
collapse: 'Свернуть',
|
|
||||||
collapseAll: 'Свернуть все',
|
|
||||||
noRecordsToDisplay: 'Нет данных для отображения',
|
|
||||||
},
|
|
||||||
initialState: {
|
|
||||||
columnPinning: { right: ['actions'], left: ['mrt-row-expand', 'project'] },
|
|
||||||
},
|
|
||||||
...(isArchiveMode ? {
|
|
||||||
rowCount: archivedTotalCount,
|
|
||||||
onPaginationChange: setArchivedPagination,
|
|
||||||
} : {}),
|
|
||||||
state: {
|
|
||||||
isLoading: isLoading || isProjectsLoading,
|
|
||||||
...(isArchiveMode ? { pagination: archivedPagination } : {}),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const summaryProjectTable = useMaterialReactTable({
|
|
||||||
columns: secondColumns,
|
|
||||||
data: summaryData,
|
|
||||||
...summaryProjectTableOptions,
|
|
||||||
localization: {
|
|
||||||
noRecordsToDisplay: 'Нет данных для отображения',
|
|
||||||
rowsPerPage: 'Строк на странице',
|
|
||||||
of: 'из',
|
|
||||||
},
|
|
||||||
initialState: {
|
|
||||||
columnPinning: { left: ['data.header.name'] },
|
|
||||||
},
|
|
||||||
state: { isLoading: isSummaryLoading },
|
|
||||||
});
|
|
||||||
|
|
||||||
const getSelectedProjectTitle = () => {
|
|
||||||
if (selectedRow?.original.name) {
|
|
||||||
return selectedRow.original.name;
|
|
||||||
}
|
|
||||||
return 'Проект не выбран';
|
|
||||||
};
|
|
||||||
|
|
||||||
// Обработчики фильтров
|
// Обработчики фильтров
|
||||||
const handleBranchChange = (value) => {
|
const handleBranchChange = (value) => {
|
||||||
setSelectedRow(null);
|
setSelectedRow(null);
|
||||||
@ -668,61 +414,26 @@ const SummaryPage = () => {
|
|||||||
</PrimaryButton>
|
</PrimaryButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Первая таблица */}
|
<ProjectsTable
|
||||||
<Paper
|
data={filteredData}
|
||||||
sx={{
|
isLoading={isLoading || isProjectsLoading}
|
||||||
mb: '2rem',
|
isArchiveMode={isArchiveMode}
|
||||||
overflow: 'hidden',
|
archivedTotalCount={archivedTotalCount}
|
||||||
flex: isArchiveMode ? '0 0 auto' : '0 0 45vh',
|
archivedPagination={archivedPagination}
|
||||||
borderRadius: '1rem',
|
onPaginationChange={setArchivedPagination}
|
||||||
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.1)',
|
selectedRow={selectedRow}
|
||||||
}}>
|
onRowSelect={setSelectedRow}
|
||||||
<MaterialReactTable table={projectsTable} />
|
onDelete={setProjectToDelete}
|
||||||
</Paper>
|
onEdit={onEdit}
|
||||||
|
onNavigate={onNavigate}
|
||||||
|
orgUnitNames={orgUnitNames}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Вторая таблица */}
|
<ProjectSummaryTable
|
||||||
<Paper
|
data={summaryData}
|
||||||
sx={{
|
isLoading={isSummaryLoading}
|
||||||
overflow: 'hidden',
|
selectedRow={selectedRow}
|
||||||
flex: '0 0 35vh',
|
/>
|
||||||
borderRadius: '1rem',
|
|
||||||
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.1)',
|
|
||||||
}}>
|
|
||||||
<Typography
|
|
||||||
variant='subtitle1'
|
|
||||||
sx={{
|
|
||||||
p: '0.75rem 1.5rem',
|
|
||||||
backgroundColor: 'white',
|
|
||||||
borderBottom: '1px solid #e0e0e0',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
flexShrink: 0,
|
|
||||||
fontSize: '1.25rem',
|
|
||||||
}}>
|
|
||||||
{getSelectedProjectTitle()}
|
|
||||||
</Typography>
|
|
||||||
{selectedRow ? (
|
|
||||||
<Box sx={{ height: 'calc(35vh - 3rem)' }}>
|
|
||||||
{isSummaryLoading && !summaryData.length ? (
|
|
||||||
<Box sx={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
||||||
<CircularProgress size={32} />
|
|
||||||
</Box>
|
|
||||||
) : <MaterialReactTable table={summaryProjectTable} />}
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
color: 'rgb(152, 162, 179)',
|
|
||||||
fontSize: '1rem',
|
|
||||||
fontWeight: 600,
|
|
||||||
}}>
|
|
||||||
Разверните или выберите проект в верхней таблице
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
{/* Модалка редактирования */}
|
{/* Модалка редактирования */}
|
||||||
<EditModal open={editModalOpen} onClose={() => setEditModalOpen(false)} rowData={selectedRowData} onSave={onSaveEdit} isSaving={isSaving} orgUnitNames={orgUnitNames} />
|
<EditModal open={editModalOpen} onClose={() => setEditModalOpen(false)} rowData={selectedRowData} onSave={onSaveEdit} isSaving={isSaving} orgUnitNames={orgUnitNames} />
|
||||||
@ -757,4 +468,4 @@ const SummaryPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SummaryPage;
|
export default NavigationProjectPage;
|
||||||
@ -0,0 +1,148 @@
|
|||||||
|
import { Box, CircularProgress, Paper, Typography } from '@mui/material';
|
||||||
|
import { MaterialReactTable, useMaterialReactTable } from 'material-react-table';
|
||||||
|
import { secondColumns } from '../../columns';
|
||||||
|
|
||||||
|
const tableHeadCellStyles = {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '12px',
|
||||||
|
lineHeight: 1.15,
|
||||||
|
textAlign: 'left',
|
||||||
|
backgroundColor: 'rgb(248, 249, 250)',
|
||||||
|
borderRight: '1px solid #e0e0e0',
|
||||||
|
'&:last-child': {
|
||||||
|
borderRight: 'none',
|
||||||
|
},
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
boxShadow: 'none',
|
||||||
|
padding: '0.5rem 1rem',
|
||||||
|
'& .MuiTableSortLabel-icon': {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
'& .MuiTableSortLabel-iconDirectionDesc': {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
'& .MuiTableSortLabel-iconDirectionAsc': {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProjectSummaryTable = ({ data, isLoading, selectedRow }) => {
|
||||||
|
const table = useMaterialReactTable({
|
||||||
|
columns: secondColumns,
|
||||||
|
data,
|
||||||
|
enableColumnActions: false,
|
||||||
|
enableColumnFilters: false,
|
||||||
|
enablePagination: false,
|
||||||
|
enableSorting: true,
|
||||||
|
enableBottomToolbar: false,
|
||||||
|
enableTopToolbar: false,
|
||||||
|
enableExpanding: false,
|
||||||
|
muiTableBodyRowProps: {
|
||||||
|
sx: {
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgb(248, 250, 252)',
|
||||||
|
},
|
||||||
|
'&:hover td::after': {
|
||||||
|
backgroundColor: 'transparent !important',
|
||||||
|
},
|
||||||
|
boxShadow: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
muiTableHeadCellProps: {
|
||||||
|
sx: tableHeadCellStyles,
|
||||||
|
},
|
||||||
|
muiTableBodyCellProps: {
|
||||||
|
sx: {
|
||||||
|
borderRight: '1px solid #e0e0e0',
|
||||||
|
'&:last-child': {
|
||||||
|
borderRight: 'none',
|
||||||
|
},
|
||||||
|
textAlign: 'left',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
padding: '0.5rem 1rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
muiTablePaperProps: {
|
||||||
|
elevation: 0,
|
||||||
|
sx: {
|
||||||
|
border: '1px solid #e0e0e0',
|
||||||
|
borderRadius: '0 0 1rem 1rem',
|
||||||
|
overflow: 'hidden',
|
||||||
|
height: '100%',
|
||||||
|
minHeight: 0,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
muiTableContainerProps: {
|
||||||
|
sx: {
|
||||||
|
flex: 1,
|
||||||
|
overflow: 'auto',
|
||||||
|
'& thead': {
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
zIndex: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
localization: {
|
||||||
|
noRecordsToDisplay: 'Нет данных для отображения',
|
||||||
|
},
|
||||||
|
initialState: {
|
||||||
|
columnPinning: { left: ['data.header.name'] },
|
||||||
|
},
|
||||||
|
state: { isLoading },
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
sx={{
|
||||||
|
overflow: 'hidden',
|
||||||
|
flex: '0 0 35vh',
|
||||||
|
borderRadius: '1rem',
|
||||||
|
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.1)',
|
||||||
|
}}>
|
||||||
|
<Typography
|
||||||
|
variant='subtitle1'
|
||||||
|
sx={{
|
||||||
|
p: '0.75rem 1.5rem',
|
||||||
|
backgroundColor: 'white',
|
||||||
|
borderBottom: '1px solid #e0e0e0',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
flexShrink: 0,
|
||||||
|
fontSize: '1.25rem',
|
||||||
|
}}>
|
||||||
|
{selectedRow?.original.name || 'Проект не выбран'}
|
||||||
|
</Typography>
|
||||||
|
{selectedRow ? (
|
||||||
|
<Box sx={{ height: 'calc(35vh - 3rem)' }}>
|
||||||
|
{isLoading && !data.length ? (
|
||||||
|
<Box sx={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
<CircularProgress size={32} />
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<MaterialReactTable table={table} />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
color: 'rgb(152, 162, 179)',
|
||||||
|
fontSize: '1rem',
|
||||||
|
fontWeight: 600,
|
||||||
|
}}>
|
||||||
|
Разверните или выберите проект в верхней таблице
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectSummaryTable;
|
||||||
@ -0,0 +1,189 @@
|
|||||||
|
import { Paper } from '@mui/material';
|
||||||
|
import { MaterialReactTable, useMaterialReactTable } from 'material-react-table';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { createFirstColumns } from '../../columns';
|
||||||
|
|
||||||
|
const tableHeadCellStyles = {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '12px',
|
||||||
|
lineHeight: 1.15,
|
||||||
|
textAlign: 'left',
|
||||||
|
backgroundColor: 'rgb(248, 249, 250)',
|
||||||
|
borderRight: '1px solid #e0e0e0',
|
||||||
|
'&:last-child': {
|
||||||
|
borderRight: 'none',
|
||||||
|
},
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
boxShadow: 'none',
|
||||||
|
padding: '0.5rem 1rem',
|
||||||
|
'& .MuiTableSortLabel-icon': {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
'& .MuiTableSortLabel-iconDirectionDesc': {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
'& .MuiTableSortLabel-iconDirectionAsc': {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProjectsTable = ({
|
||||||
|
data,
|
||||||
|
isLoading,
|
||||||
|
isArchiveMode,
|
||||||
|
archivedTotalCount,
|
||||||
|
archivedPagination,
|
||||||
|
onPaginationChange,
|
||||||
|
selectedRow,
|
||||||
|
onRowSelect,
|
||||||
|
onDelete,
|
||||||
|
onEdit,
|
||||||
|
onNavigate,
|
||||||
|
orgUnitNames,
|
||||||
|
}) => {
|
||||||
|
const columns = useMemo(
|
||||||
|
() => createFirstColumns({ onDelete, onEdit, onNavigate, orgUnitNames }),
|
||||||
|
[onDelete, onEdit, onNavigate, orgUnitNames],
|
||||||
|
);
|
||||||
|
|
||||||
|
const table = useMaterialReactTable({
|
||||||
|
columns,
|
||||||
|
data,
|
||||||
|
enableColumnActions: false,
|
||||||
|
enableColumnFilters: false,
|
||||||
|
enablePagination: isArchiveMode,
|
||||||
|
manualPagination: isArchiveMode,
|
||||||
|
enableSorting: true,
|
||||||
|
enableBottomToolbar: isArchiveMode,
|
||||||
|
enableTopToolbar: false,
|
||||||
|
enableExpanding: true,
|
||||||
|
getSubRows: (row) => row.sub_rows,
|
||||||
|
muiTableHeadCellProps: {
|
||||||
|
sx: tableHeadCellStyles,
|
||||||
|
},
|
||||||
|
muiExpandButtonProps: {
|
||||||
|
sx: {
|
||||||
|
width: '1.5rem',
|
||||||
|
height: '1.5rem',
|
||||||
|
minWidth: '1.5rem',
|
||||||
|
'& .MuiSvgIcon-root': {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
muiTableBodyRowProps: ({ row }) => {
|
||||||
|
const isSelected = selectedRow && row.id === selectedRow.id;
|
||||||
|
const isChild = selectedRow && row.parentId === selectedRow.id;
|
||||||
|
|
||||||
|
return {
|
||||||
|
sx: {
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgb(248, 250, 252)',
|
||||||
|
},
|
||||||
|
'&:hover td::after': {
|
||||||
|
backgroundColor: 'transparent !important',
|
||||||
|
},
|
||||||
|
...(row.depth > 0 && {
|
||||||
|
backgroundColor: 'rgb(252, 252, 253)',
|
||||||
|
}),
|
||||||
|
...((isSelected || isChild) && {
|
||||||
|
backgroundColor: 'rgb(234, 247, 236)',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgb(225, 242, 229) !important',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if (row.depth === 0) onRowSelect(row);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
muiTableBodyCellProps: ({ row, column }) => ({
|
||||||
|
sx: {
|
||||||
|
borderRight: '1px solid #e0e0e0',
|
||||||
|
'&:last-child': {
|
||||||
|
borderRight: 'none',
|
||||||
|
},
|
||||||
|
'&:hover td::after': {
|
||||||
|
backgroundColor: 'transparent !important',
|
||||||
|
},
|
||||||
|
textAlign: 'left',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
padding: '0.5rem 1rem',
|
||||||
|
...(column.id === 'mrt-row-expand' && {
|
||||||
|
width: '1.5rem',
|
||||||
|
maxWidth: '1.5rem',
|
||||||
|
minWidth: '1.5rem',
|
||||||
|
padding: '0.5rem 0.25rem',
|
||||||
|
}),
|
||||||
|
...(column.id === 'project' &&
|
||||||
|
row.depth > 0 && {
|
||||||
|
pl: `${2 + row.depth * 0.5}rem`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
muiTablePaperProps: {
|
||||||
|
elevation: 0,
|
||||||
|
sx: {
|
||||||
|
border: '1px solid #e0e0e0',
|
||||||
|
borderRadius: '1rem',
|
||||||
|
overflow: 'hidden',
|
||||||
|
height: isArchiveMode ? 'auto' : '45vh',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
muiTableContainerProps: {
|
||||||
|
sx: {
|
||||||
|
flex: 1,
|
||||||
|
overflowX: 'auto',
|
||||||
|
overflowY: isArchiveMode ? 'visible' : 'auto',
|
||||||
|
'& thead': {
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
zIndex: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
localization: {
|
||||||
|
expand: 'Раскрыть',
|
||||||
|
expandAll: 'Раскрыть все',
|
||||||
|
collapse: 'Свернуть',
|
||||||
|
collapseAll: 'Свернуть все',
|
||||||
|
noRecordsToDisplay: 'Нет данных для отображения',
|
||||||
|
rowsPerPage: 'Строк на странице',
|
||||||
|
of: 'из',
|
||||||
|
},
|
||||||
|
initialState: {
|
||||||
|
columnPinning: { right: ['actions'], left: ['mrt-row-expand', 'project'] },
|
||||||
|
},
|
||||||
|
...(isArchiveMode
|
||||||
|
? {
|
||||||
|
rowCount: archivedTotalCount,
|
||||||
|
onPaginationChange,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
state: {
|
||||||
|
isLoading,
|
||||||
|
...(isArchiveMode ? { pagination: archivedPagination } : {}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
sx={{
|
||||||
|
mb: '2rem',
|
||||||
|
overflow: 'hidden',
|
||||||
|
flex: isArchiveMode ? '0 0 auto' : '0 0 45vh',
|
||||||
|
borderRadius: '1rem',
|
||||||
|
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.1)',
|
||||||
|
}}>
|
||||||
|
<MaterialReactTable table={table} />
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectsTable;
|
||||||
Loading…
x
Reference in New Issue
Block a user