diff --git a/web/src/api/projects.js b/web/src/api/projects.js
index 9d92132..c3f0f44 100644
--- a/web/src/api/projects.js
+++ b/web/src/api/projects.js
@@ -38,6 +38,12 @@ export const ProjectsApi = {
getSummary: (id) => {
return api.get(`/projects/${id}/summary`).then((r) => r.data);
},
+ getAggregateSummary: (kind, year, branchIds = [], projectType = '') => {
+ const params = { year };
+ if (branchIds.length) params.branch_id = branchIds.join(',');
+ if (projectType) params.project_type = projectType;
+ return api.get(`/projects/${kind}-summary`, { params }).then((r) => r.data);
+ },
export: (id, year, sheetName) => {
return api.get(`/export/project/${id}/report/${year}/${sheetName}`, {
responseType: 'blob',
diff --git a/web/src/app/Routes.jsx b/web/src/app/Routes.jsx
index c4cbdfc..1cf7196 100644
--- a/web/src/app/Routes.jsx
+++ b/web/src/app/Routes.jsx
@@ -9,6 +9,7 @@ import DictsNavigatorPage from '../pages/DictsNavigatorPage/DictsNavigatorPage.j
import LoginPage from '../pages/LoginPage';
import NewFormTablePage from '../pages/NewFormTablePage.jsx';
import NavigationProjectPage from '../pages/ProjectPages/NavigationProjectPage.jsx';
+import ProjectSummariesPage from '../pages/ProjectPages/ProjectSummariesPage.jsx';
import Svod2Page from '../pages/Svod2Page/Svod2Page.jsx';
import { SvodProvider } from '../pages/SvodPage/SvodContext.jsx';
import SvodPage from '../pages/SvodPage/SvodPage.jsx';
@@ -38,6 +39,7 @@ export const AppRoutes = () => {
} />
} />
} />
+ } />
} />
} />
} />
diff --git a/web/src/pages/ProjectPages/NavigationProjectPage.jsx b/web/src/pages/ProjectPages/NavigationProjectPage.jsx
index b303ec7..29c29f2 100644
--- a/web/src/pages/ProjectPages/NavigationProjectPage.jsx
+++ b/web/src/pages/ProjectPages/NavigationProjectPage.jsx
@@ -462,9 +462,16 @@ const NavigationProjectPage = () => {
selectedStatus={selectedStatus}
onStatusChange={handleStatusChange}
/>
- setCreateModalOpen(true)} startIcon={} sx={{ height: '2.5rem' }}>
- Создать проект
-
+
+ navigate(branchIdsParam ? `/projects/summaries?branch_ids=${branchIdsParam}` : '/projects/summaries')}
+ sx={{ height: '2.5rem', whiteSpace: 'nowrap' }}>
+ Перейти к сводам
+
+ setCreateModalOpen(true)} startIcon={} sx={{ height: '2.5rem', whiteSpace: 'nowrap' }}>
+ Создать проект
+
+
{
+ if (value === null || value === undefined || value === '') return '—';
+ const numericValue = typeof value === 'number' ? value : Number(value);
+ if (numericValue === 0) return '-';
+ return Number.isNaN(numericValue) ? value : numberFormatter.format(numericValue);
+};
+const valueColumn = (id, header, getValue) => ({
+ id,
+ header,
+ accessorFn: getValue,
+ Cell: ({ cell }) => formatValue(cell.getValue()),
+ size: 112,
+ muiTableBodyCellProps: { align: 'right' },
+ muiTableHeadCellProps: { align: 'right' },
+});
+const headerColumns = [
+ { id: 'section_code', header: '№ п/п', accessorFn: (row) => row.data?.header?.section_code, size: 92 },
+ {
+ id: 'name',
+ header: 'Перечень расходов и затрат',
+ accessorFn: (row) => row.data?.header?.name,
+ size: 330,
+ Cell: ({ cell, row }) => (
+
+ {cell.getValue() || 'Без названия'}
+
+ ),
+ },
+];
+const metricColumns = (metric, label, periods) => ({
+ id: metric,
+ header: label,
+ columns: [
+ { key: 'limit', label: 'Лимит' },
+ { key: 'current', label: 'Текущие расходы' },
+ { key: 'total', label: 'Итого' },
+ ].map((group) => ({
+ id: `${metric}.${group.key}`,
+ header: group.label,
+ columns: periods.map((period) =>
+ valueColumn(
+ `${metric}.${group.key}.${period.key}`,
+ period.label,
+ (row) => row.data?.[metric]?.[group.key]?.[period.key],
+ ),
+ ),
+ })),
+});
+const createColumns = (sheet) => {
+ if (sheet === 'plan') {
+ return [
+ ...headerColumns,
+ metricColumns('base', 'Базовый план', QUARTERS),
+ metricColumns('correction', 'Корректировка плана', QUARTERS.filter(({ key }) => key !== 'q1')),
+ ];
+ }
+ if (sheet === 'fact') {
+ return [...headerColumns, metricColumns('fact', 'Факт', QUARTERS)];
+ }
+ return [
+ ...headerColumns,
+ ...QUARTERS.filter(({ key }) => key !== 'year').map((quarter) => ({
+ id: `detail.${quarter.key}`,
+ header: quarter.label,
+ columns: DETAIL_FIELDS.map((field) =>
+ valueColumn(
+ `detail.${quarter.key}.${field.key}`,
+ field.label,
+ (row) => row.data?.detail?.[quarter.key]?.[field.key],
+ ),
+ ),
+ })),
+ valueColumn('detail.year', 'Факт за год', (row) => row.data?.detail?.year),
+ ];
+};
+const parseBranchIds = (value) =>
+ value
+ .split(',')
+ .map(Number)
+ .filter((id) => Number.isInteger(id) && id > 0);
+const COLUMNS_BY_SHEET = Object.fromEntries(SHEETS.map(({ value }) => [value, createColumns(value)]));
+const EMPTY_SUMMARY = { rows: [], tree: [] };
+const createCacheKey = (year, branchIds, projectType) => JSON.stringify([year, branchIds.map(String).sort(), projectType]);
+const getSheetCache = (cache, sheet) => {
+ if (!cache.has(sheet)) cache.set(sheet, new Map());
+ return cache.get(sheet);
+};
+
+export default function ProjectSummariesPage() {
+ const [searchParams] = useSearchParams();
+ const initialBranchIds = useMemo(() => parseBranchIds(searchParams.get('branch_ids') || ''), [searchParams]);
+ const { organizations } = useSummaryOrganizations();
+ const [sheet, setSheet] = useState('plan');
+ const [filters, setFilters] = useState({
+ year: new Date().getFullYear(),
+ selectedOrganizations: [],
+ search: '',
+ });
+ const [projectType, setProjectType] = useState('');
+ const [summary, setSummary] = useState(EMPTY_SUMMARY);
+ const { rows, tree } = summary;
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState('');
+ const requestRef = useRef(0);
+ const summaryCacheRef = useRef(new Map());
+ const initialBranchesAppliedRef = useRef(false);
+ const { year, selectedOrganizations, search } = filters;
+ const branchIds = useMemo(
+ () => selectedOrganizations.map(({ id }) => id),
+ [selectedOrganizations],
+ );
+ const updateFilters = useCallback((changes) => setFilters((current) => ({ ...current, ...changes })), []);
+
+ useEffect(
+ () => () => {
+ summaryCacheRef.current.clear();
+ },
+ [],
+ );
+
+ useEffect(() => {
+ if (initialBranchesAppliedRef.current || !organizations.length) return;
+ initialBranchesAppliedRef.current = true;
+ if (initialBranchIds.length) {
+ setFilters((current) => ({
+ ...current,
+ selectedOrganizations: organizations.filter(({ id }) => initialBranchIds.includes(id)),
+ }));
+ }
+ }, [initialBranchIds, organizations]);
+
+ const getSummary = useCallback((kind, selectedYear, selectedBranchIds, selectedProjectType) => {
+ const sheetCache = getSheetCache(summaryCacheRef.current, kind);
+ const cacheKey = createCacheKey(selectedYear, selectedBranchIds, selectedProjectType);
+ const cachedRequest = sheetCache.get(cacheKey);
+ if (cachedRequest) return cachedRequest;
+
+ const request = ProjectsApi.getAggregateSummary(kind, selectedYear, selectedBranchIds, selectedProjectType)
+ .then((response) => {
+ const rows = [...(response.result || [])].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
+ const preparedSummary = { rows, tree: buildSummaryTree(rows) };
+ if (sheetCache.get(cacheKey) === request) sheetCache.set(cacheKey, Promise.resolve(preparedSummary));
+ return preparedSummary;
+ })
+ .catch((requestError) => {
+ if (sheetCache.get(cacheKey) === request) sheetCache.delete(cacheKey);
+ throw requestError;
+ });
+
+ sheetCache.set(cacheKey, request);
+ return request;
+ }, []);
+
+ const loadSummary = useCallback(async () => {
+ const requestId = ++requestRef.current;
+ setLoading(true);
+ setError('');
+ try {
+ const requestedBranchIds = initialBranchesAppliedRef.current ? branchIds : initialBranchIds;
+ const response = await getSummary(sheet, year, requestedBranchIds, projectType);
+ if (requestId !== requestRef.current) return;
+ setSummary(response);
+ } catch (requestError) {
+ if (requestId !== requestRef.current) return;
+ setSummary(EMPTY_SUMMARY);
+ setError(requestError.response?.data?.detail || 'Не удалось загрузить свод проектов. Попробуйте ещё раз.');
+ } finally {
+ if (requestId === requestRef.current) setLoading(false);
+ }
+ }, [sheet, year, branchIds, initialBranchIds, projectType, getSummary]);
+
+ const refreshSummary = useCallback(() => {
+ const requestedBranchIds = initialBranchesAppliedRef.current ? branchIds : initialBranchIds;
+ summaryCacheRef.current.get(sheet)?.delete(createCacheKey(year, requestedBranchIds, projectType));
+ loadSummary();
+ }, [sheet, year, branchIds, initialBranchIds, projectType, loadSummary]);
+
+ useEffect(() => {
+ loadSummary();
+ return () => { requestRef.current += 1; };
+ }, [loadSummary]);
+
+ const filteredRows = useMemo(() => {
+ const query = search.trim().toLowerCase();
+ return query ? filterSummaryTree(tree, query) : tree;
+ }, [tree, search]);
+ const columns = COLUMNS_BY_SHEET[sheet];
+ const filteredCount = useMemo(() => countSummaryTree(filteredRows), [filteredRows]);
+
+ return (
+
+
+
+ setSheet(value)} sx={{ px: '0.5rem', minHeight: '3rem', borderBottom: '0.0625rem solid #edf0f2' }}>
+ {SHEETS.map(({ value, label }) => )}
+
+ setProjectType('')}
+ searchPlaceholder='Код или статья расходов'
+ additionalFilters={
+ setProjectType(event.target.value)} sx={{ minWidth: '13rem' }}>
+
+ {PROJECT_TYPES.map((type) => )}
+
+ }
+ >
+ {!loading && filteredCount !== rows.length && (
+
+ {`Найдено ${filteredCount.toLocaleString('ru-RU')} из ${rows.length.toLocaleString('ru-RU')} строк`}
+
+ )}
+ } disabled={loading} onClick={refreshSummary} sx={{ ml: 'auto', height: '2.5rem', flexShrink: 0 }}>
+ Обновить
+
+
+
+ {error ? (
+ Повторить}>{error}
+ ) : (
+
+ )}
+
+ );
+}
diff --git a/web/src/pages/SvodPage/SummaryTable.jsx b/web/src/pages/SvodPage/SummaryTable.jsx
new file mode 100644
index 0000000..a88c357
--- /dev/null
+++ b/web/src/pages/SvodPage/SummaryTable.jsx
@@ -0,0 +1,163 @@
+import { MaterialReactTable, useMaterialReactTable } from 'material-react-table';
+import { memo } from 'react';
+import { blueColumn } from '../../components/RealtimeTable/constants/columnColors';
+import { sectionCodeColor } from '../../components/RealtimeTable/constants/columnConfig';
+
+const tableSize = (rem) => rem * 16;
+const ROW_VIRTUALIZER_OPTIONS = {
+ overscan: 8,
+ estimateSize: () => 37,
+ measureElement: (element) => element?.offsetHeight || 37,
+};
+
+const getSummaryRowColor = (row) => {
+ const rowType = row.original?.row_type || row.row_type;
+ const sectionCodeValue = row.original?.data?.section_code ?? row.original?.data?.header?.section_code;
+ if (sectionCodeValue === null || sectionCodeValue === undefined || sectionCodeValue === '') return undefined;
+ const sectionCode = String(sectionCodeValue)[0];
+ return (sectionCodeColor[sectionCode] || blueColumn)[rowType];
+};
+
+const getTextColor = (backgroundColor) => {
+ if (!backgroundColor?.startsWith('#') || backgroundColor.length !== 7) return '#000';
+ const red = Number.parseInt(backgroundColor.slice(1, 3), 16);
+ const green = Number.parseInt(backgroundColor.slice(3, 5), 16);
+ const blue = Number.parseInt(backgroundColor.slice(5, 7), 16);
+ return 0.299 * red + 0.587 * green + 0.114 * blue < 128 ? '#fff' : '#000';
+};
+
+export const buildSummaryTree = (sourceRows) => {
+ const roots = [];
+ const parents = [];
+
+ for (const [index, sourceRow] of sourceRows.entries()) {
+ const row = {
+ ...sourceRow,
+ _rowId: `${sourceRow.sort_order ?? index}-${sourceRow.data?.section_code ?? sourceRow.data?.header?.section_code ?? index}`,
+ subRows: [],
+ };
+
+ while (parents.length > row.depth) parents.pop();
+ if (row.depth > 0 && parents[row.depth - 1]) parents[row.depth - 1].subRows.push(row);
+ else roots.push(row);
+
+ parents[row.depth] = row;
+ parents.length = row.depth + 1;
+ }
+
+ return roots;
+};
+
+export const filterSummaryTree = (tree, query) =>
+ tree.flatMap((row) => {
+ const matches = [row.data?.section_code, row.data?.name, row.data?.header?.section_code, row.data?.header?.name].some((value) =>
+ String(value || '')
+ .toLowerCase()
+ .includes(query),
+ );
+
+ if (matches) return [row];
+
+ const subRows = filterSummaryTree(row.subRows, query);
+ return subRows.length ? [{ ...row, subRows }] : [];
+ });
+
+export const countSummaryTree = (tree) => tree.reduce((count, row) => count + 1 + countSummaryTree(row.subRows), 0);
+
+export const SummaryTable = memo(function SummaryTable({ columns, data, loading }) {
+ const table = useMaterialReactTable({
+ columns,
+ data,
+ enableExpanding: true,
+ enableExpandAll: true,
+ getSubRows: (row) => row.subRows,
+ getRowId: (row) => row._rowId,
+ enableColumnActions: false,
+ enableColumnFilters: false,
+ enableDensityToggle: false,
+ enableFullScreenToggle: false,
+ enableHiding: false,
+ enablePagination: false,
+ enableRowVirtualization: true,
+ rowVirtualizerOptions: ROW_VIRTUALIZER_OPTIONS,
+ enableTopToolbar: false,
+ enableBottomToolbar: false,
+ enableSorting: false,
+ displayColumnDefOptions: {
+ 'mrt-row-expand': {
+ size: tableSize(3.75),
+ minSize: tableSize(3.75),
+ maxSize: tableSize(3.75),
+ grow: false,
+ },
+ },
+ state: { isLoading: loading },
+ initialState: { columnPinning: { left: ['mrt-row-expand', 'section_code', 'name'] }, expanded: true },
+ muiTablePaperProps: {
+ elevation: 0,
+ sx: {
+ border: '0.0625rem solid #e5e7eb',
+ borderRadius: '0.75rem',
+ overflow: 'hidden',
+ flex: 1,
+ minHeight: 0,
+ width: '100%',
+ display: 'flex',
+ flexDirection: 'column',
+ },
+ },
+ muiTableContainerProps: {
+ sx: {
+ flex: 1,
+ overflow: 'auto',
+ minHeight: 0,
+ height: '100%',
+ '& thead': {
+ position: 'sticky',
+ top: 0,
+ zIndex: 10,
+ },
+ },
+ },
+ muiTableHeadCellProps: {
+ sx: {
+ position: 'sticky',
+ top: 0,
+ boxShadow: 'none',
+ backgroundColor: '#f8f9fa',
+ borderRight: '0.0625rem solid #e5e7eb',
+ color: '#4a5565',
+ fontSize: '0.75rem',
+ fontWeight: 700,
+ lineHeight: 1.2,
+ px: '0.75rem',
+ py: '0.5rem',
+ whiteSpace: 'nowrap',
+ },
+ },
+ muiTableHeadRowProps: {
+ sx: {
+ boxShadow: 'none',
+ },
+ },
+ muiTableBodyCellProps: ({ row, column }) => {
+ const backgroundColor = getSummaryRowColor(row);
+ return {
+ sx: {
+ backgroundColor,
+ borderRight: '0.0625rem solid #edf0f2',
+ color: getTextColor(backgroundColor),
+ fontSize: '0.8125rem',
+ px: column.id === 'mrt-row-expand' ? '0.25rem' : '0.75rem',
+ py: column.id === 'mrt-row-expand' ? 0 : '0.5rem',
+ whiteSpace: 'nowrap',
+ textAlign: ['section_code', 'name'].includes(column.id) ? 'left' : 'right',
+ },
+ };
+ },
+ muiExpandButtonProps: { sx: { width: '1.25rem', height: '1.25rem', p: 0, '& .MuiSvgIcon-root': { fontSize: '1.125rem' } } },
+ localization: { noRecordsToDisplay: 'Нет данных для выбранных параметров' },
+ });
+
+ return ;
+});
diff --git a/web/src/pages/SvodPage/SvodFilters.jsx b/web/src/pages/SvodPage/SvodFilters.jsx
index 3a149c2..59c3811 100644
--- a/web/src/pages/SvodPage/SvodFilters.jsx
+++ b/web/src/pages/SvodPage/SvodFilters.jsx
@@ -53,6 +53,8 @@ export function SvodFilters({
searchPlaceholder = 'Код или статья расходов',
emptyOrganizationsPlaceholder = 'Все доступные',
allowSelectAll = false,
+ onReset,
+ additionalFilters,
children,
}) {
const { organizations, organizationsLoading } = useSummaryOrganizations();
@@ -147,10 +149,12 @@ export function SvodFilters({
},
}}
/>
+ {additionalFilters}
{
setSearchInput('');
onChange({ year: new Date().getFullYear(), selectedOrganizations: [], search: '' });
+ onReset?.();
}}
/>
{children}
diff --git a/web/src/pages/SvodPage/SvodPage.jsx b/web/src/pages/SvodPage/SvodPage.jsx
index 48c036c..e98cbd0 100644
--- a/web/src/pages/SvodPage/SvodPage.jsx
+++ b/web/src/pages/SvodPage/SvodPage.jsx
@@ -1,14 +1,12 @@
import RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';
import { Alert, Box, Button, Paper, Tab, Tabs, Typography } from '@mui/material';
-import { MaterialReactTable, useMaterialReactTable } from 'material-react-table';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { HeaderSwitch } from '../../components/HeaderMenu/HeaderSwitch';
-import { blueColumn } from '../../components/RealtimeTable/constants/columnColors';
-import { sectionCodeColor } from '../../components/RealtimeTable/constants/columnConfig';
+import { PrimaryButton, PrimaryOutlinedButton } from '../../components/common/Buttons/Buttons';
+import { SummaryTable, buildSummaryTree, countSummaryTree, filterSummaryTree } from './SummaryTable';
import { useSvod } from './SvodContext';
import { SvodFilters } from './SvodFilters';
-import { PrimaryButton, PrimaryOutlinedButton } from '../../components/common/Buttons/Buttons';
const SHEETS = [
{ value: 'MAIN', label: 'Общий свод' },
@@ -162,60 +160,6 @@ const createColumns = (sheet) => {
];
};
-const getSummaryRowColor = (row) => {
- const rowType = row.original?.row_type || row.row_type;
- const sectionCodeValue = row.original?.data?.section_code ?? row.original?.data?.header?.section_code;
- if (sectionCodeValue === null || sectionCodeValue === undefined || sectionCodeValue === '') return undefined;
- const sectionCode = String(sectionCodeValue)[0];
- return (sectionCodeColor[sectionCode] || blueColumn)[rowType];
-};
-
-const getTextColor = (backgroundColor) => {
- if (!backgroundColor?.startsWith('#') || backgroundColor.length !== 7) return '#000';
- const red = Number.parseInt(backgroundColor.slice(1, 3), 16);
- const green = Number.parseInt(backgroundColor.slice(3, 5), 16);
- const blue = Number.parseInt(backgroundColor.slice(5, 7), 16);
- return 0.299 * red + 0.587 * green + 0.114 * blue < 128 ? '#fff' : '#000';
-};
-
-const buildSummaryTree = (sourceRows) => {
- const roots = [];
- const parents = [];
-
- for (const [index, sourceRow] of sourceRows.entries()) {
- const row = {
- ...sourceRow,
- _rowId: `${sourceRow.sort_order ?? index}-${sourceRow.data?.section_code ?? index}`,
- subRows: [],
- };
-
- while (parents.length > row.depth) parents.pop();
- if (row.depth > 0 && parents[row.depth - 1]) parents[row.depth - 1].subRows.push(row);
- else roots.push(row);
-
- parents[row.depth] = row;
- parents.length = row.depth + 1;
- }
-
- return roots;
-};
-
-const filterSummaryTree = (tree, query) =>
- tree.flatMap((row) => {
- const matches = [row.data?.section_code, row.data?.name].some((value) =>
- String(value || '')
- .toLowerCase()
- .includes(query),
- );
-
- if (matches) return [row];
-
- const subRows = filterSummaryTree(row.subRows, query);
- return subRows.length ? [{ ...row, subRows }] : [];
- });
-
-const countSummaryTree = (tree) => tree.reduce((count, row) => count + 1 + countSummaryTree(row.subRows), 0);
-
export default function SvodPage() {
const navigate = useNavigate();
const { getSheetFilters, updateSheetFilters, getSummary, invalidateSummary } = useSvod();
@@ -286,104 +230,13 @@ export default function SvodPage() {
navigate(query ? `/projects?${query}` : '/projects');
}, [navigate, selectedOrganizations]);
+ const tree = useMemo(() => buildSummaryTree(rows), [rows]);
const filteredRows = useMemo(() => {
const normalizedSearch = search.trim().toLowerCase();
- const tree = buildSummaryTree(rows);
return normalizedSearch ? filterSummaryTree(tree, normalizedSearch) : tree;
- }, [rows, search]);
+ }, [tree, search]);
const columns = useMemo(() => createColumns(sheet), [sheet]);
const filteredRowsCount = useMemo(() => countSummaryTree(filteredRows), [filteredRows]);
- const table = useMaterialReactTable({
- columns,
- data: filteredRows,
- enableExpanding: true,
- enableExpandAll: true,
- getSubRows: (row) => row.subRows,
- getRowId: (row) => row._rowId,
- enableColumnActions: false,
- enableColumnFilters: false,
- enableDensityToggle: false,
- enableFullScreenToggle: false,
- enableHiding: false,
- enablePagination: false,
- enableTopToolbar: false,
- enableBottomToolbar: false,
- enableSorting: false,
- displayColumnDefOptions: {
- 'mrt-row-expand': {
- size: tableSize(3.75),
- minSize: tableSize(3.75),
- maxSize: tableSize(3.75),
- grow: false,
- },
- },
- state: { isLoading: loading },
- initialState: { columnPinning: { left: ['mrt-row-expand', 'section_code', 'name'] }, expanded: true },
- muiTablePaperProps: {
- elevation: 0,
- sx: {
- border: '0.0625rem solid #e5e7eb',
- borderRadius: '0.75rem',
- overflow: 'hidden',
- flex: 1,
- minHeight: 0,
- width: '100%',
- display: 'flex',
- flexDirection: 'column',
- },
- },
- muiTableContainerProps: {
- sx: {
- flex: 1,
- overflow: 'auto',
- minHeight: 0,
- height: '100%',
- '& thead': {
- position: 'sticky',
- top: 0,
- zIndex: 10,
- },
- },
- },
- muiTableHeadCellProps: {
- sx: {
- position: 'sticky',
- top: 0,
- boxShadow: 'none',
- backgroundColor: '#f8f9fa',
- borderRight: '0.0625rem solid #e5e7eb',
- color: '#4a5565',
- fontSize: '0.75rem',
- fontWeight: 700,
- lineHeight: 1.2,
- px: '0.75rem',
- py: '0.5rem',
- whiteSpace: 'nowrap',
- },
- },
- muiTableHeadRowProps: {
- sx: {
- boxShadow: 'none',
- },
- },
- muiTableBodyCellProps: ({ row, column }) => {
- const backgroundColor = getSummaryRowColor(row);
- return {
- sx: {
- backgroundColor,
- borderRight: '0.0625rem solid #edf0f2',
- color: getTextColor(backgroundColor),
- fontSize: '0.8125rem',
- px: column.id === 'mrt-row-expand' ? '0.25rem' : '0.75rem',
- py: column.id === 'mrt-row-expand' ? 0 : '0.5rem',
- whiteSpace: 'nowrap',
- textAlign: ['section_code', 'name'].includes(column.id) ? 'left' : 'right',
- },
- };
- },
- muiExpandButtonProps: { sx: { width: '1.25rem', height: '1.25rem', p: 0, '& .MuiSvgIcon-root': { fontSize: '1.125rem' } } },
- localization: { noRecordsToDisplay: 'Нет данных для выбранных параметров' },
- });
return (
) : (
-
+
)}
);