Compare commits
No commits in common. "ee545e96dc441518cca0a8a16b0895f12de67a32" and "1eb5959a50139bfa94a19a24c4f3b721aee563f1" have entirely different histories.
ee545e96dc
...
1eb5959a50
@ -18,7 +18,6 @@ import NewTablePage from '../pages/NewTablePage.jsx';
|
||||
import TablesTest from '../pages/TablesTest.jsx';
|
||||
import NewFormTablePage from '../pages/NewFormTablePage.jsx'
|
||||
import ProjectsPage from '../pages/ProjectsPage/ProjectsPage.jsx';
|
||||
import SummaryPage from '../pages/ProjectPages/SummaryPage.jsx';
|
||||
|
||||
export const PrivateRoute = () => {
|
||||
const { isAuthenticated, loading } = useAuth();
|
||||
@ -54,7 +53,6 @@ export const AppRoutes = () => {
|
||||
<Route path="/tables-new" element={<TablesTest />} />
|
||||
<Route path="/tables/:form/:sheetName" element={<NewFormTablePage />} />
|
||||
<Route path="/table/form/:formId/form-type/:formType/:sheetName/:direction/:year" element={<NewFormTablePage />} />
|
||||
<Route path="/project-mock-summary" element={<SummaryPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
|
||||
@ -1,409 +0,0 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import {
|
||||
useMaterialReactTable,
|
||||
MaterialReactTable,
|
||||
} from 'material-react-table';
|
||||
import {
|
||||
Box,
|
||||
Paper,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { firstTableData, secondTableData } from "./mockData";
|
||||
import { createFirstColumns, secondColumns } from "./columns";
|
||||
import EditModal from "./components/EditModal/EditModal";
|
||||
import TableFilters from "./components/TableFilters/TableFilters"; // Импортируем компонент фильтров
|
||||
import { handleEditClick, handleNavigateClick, handleSaveEdit } from "./utils/tableHandlers";
|
||||
|
||||
const SummaryPage = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [selectedRow, setSelectedRow] = useState(null);
|
||||
const [editModalOpen, setEditModalOpen] = useState(false);
|
||||
const [selectedRowData, setSelectedRowData] = useState(null);
|
||||
const [tableData, setTableData] = useState(firstTableData);
|
||||
|
||||
// Состояния для фильтров
|
||||
const [selectedBranch, setSelectedBranch] = useState('');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const getFilteredData = () => {
|
||||
if (!selectedBranch && !searchQuery) {
|
||||
return tableData;
|
||||
}
|
||||
|
||||
return tableData
|
||||
.filter(item => {
|
||||
// Фильтр по филиалу (только для корневых)
|
||||
if (selectedBranch) {
|
||||
return item.org_unit_id === selectedBranch.id;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map(item => {
|
||||
if (!searchQuery) {
|
||||
return item;
|
||||
}
|
||||
|
||||
const query = searchQuery.toLowerCase().trim();
|
||||
|
||||
// Проверяем, совпадает ли родитель
|
||||
const parentMatches = item.project.toLowerCase().includes(query);
|
||||
|
||||
// Фильтруем дочерние элементы - оставляем только те, что совпадают с поиском
|
||||
const filteredSubRows = item.subRows?.filter(subItem =>
|
||||
subItem.project.toLowerCase().includes(query)
|
||||
) || [];
|
||||
|
||||
// Возвращаем элемент с отфильтрованными дочерними элементами
|
||||
return {
|
||||
...item,
|
||||
subRows: filteredSubRows
|
||||
};
|
||||
})
|
||||
.filter(item => {
|
||||
if (!searchQuery) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const query = searchQuery.toLowerCase().trim();
|
||||
const parentMatches = item.project.toLowerCase().includes(query);
|
||||
const hasMatchingChildren = item.subRows && item.subRows.length > 0;
|
||||
|
||||
return parentMatches || hasMatchingChildren;
|
||||
});
|
||||
};
|
||||
const filteredData = getFilteredData();
|
||||
|
||||
const handleRowClick = (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) => {
|
||||
handleEditClick(row, setEditModalOpen, setSelectedRowData);
|
||||
};
|
||||
|
||||
const onNavigate = (row) => {
|
||||
handleNavigateClick(row, navigate);
|
||||
};
|
||||
|
||||
const onSaveEdit = (formData) => {
|
||||
handleSaveEdit(formData, updateTableData);
|
||||
};
|
||||
|
||||
const updateTableData = (updatedData) => {
|
||||
setTableData(prevData =>
|
||||
prevData.map(item =>
|
||||
item.id === updatedData.id ? { ...item, ...updatedData } : item
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const firstColumns = useMemo(() =>
|
||||
createFirstColumns({ onEdit, onNavigate }),
|
||||
[onEdit, onNavigate]
|
||||
);
|
||||
|
||||
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 summaryProjectsTableOptions = {
|
||||
enableColumnActions: false,
|
||||
enableColumnFilters: false,
|
||||
enablePagination: false,
|
||||
enableSorting: true,
|
||||
enableBottomToolbar: false,
|
||||
enableTopToolbar: false,
|
||||
enableExpanding: true,
|
||||
getSubRows: (row) => row.subRows,
|
||||
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: "45vh",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
},
|
||||
},
|
||||
muiTableContainerProps: {
|
||||
sx: {
|
||||
flex: 1,
|
||||
overflow: "auto",
|
||||
"& thead": {
|
||||
position: "sticky",
|
||||
top: 0,
|
||||
zIndex: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const projectTableOptions = {
|
||||
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: "35vh",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
},
|
||||
},
|
||||
muiTableContainerProps: {
|
||||
sx: {
|
||||
flex: 1,
|
||||
overflow: "auto",
|
||||
"& thead": {
|
||||
position: "sticky",
|
||||
top: 0,
|
||||
zIndex: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
initialState: {
|
||||
columnPinning: { left: ['project'] }
|
||||
},
|
||||
};
|
||||
|
||||
const summaryProjectsTable = useMaterialReactTable({
|
||||
columns: firstColumns,
|
||||
data: filteredData,
|
||||
...summaryProjectsTableOptions,
|
||||
initialState: {
|
||||
columnPinning: { right: ['actions'], left: ["mrt-row-expand", 'project'] }
|
||||
},
|
||||
});
|
||||
|
||||
const projectTable = useMaterialReactTable({
|
||||
columns: secondColumns,
|
||||
data: selectedRow ? secondTableData[selectedRow.original.id] : [],
|
||||
...projectTableOptions,
|
||||
});
|
||||
|
||||
const getSelectedProjectTitle = () => {
|
||||
if (selectedRow && selectedRow.original.project) {
|
||||
return selectedRow.original.project;
|
||||
}
|
||||
return 'Проект не выбран';
|
||||
};
|
||||
|
||||
// Обработчики фильтров
|
||||
const handleBranchChange = (value) => {
|
||||
setSelectedBranch(value);
|
||||
};
|
||||
|
||||
const handleSearchChange = (value) => {
|
||||
setSearchQuery(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{
|
||||
p: "1.5rem",
|
||||
maxWidth: "1600px",
|
||||
mx: "auto",
|
||||
height: "100vh",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}>
|
||||
{/* Компонент фильтров */}
|
||||
<TableFilters
|
||||
data={tableData}
|
||||
onFilterChange={() => { }} // Можно использовать для дополнительной логики
|
||||
selectedBranch={selectedBranch}
|
||||
onBranchChange={handleBranchChange}
|
||||
searchQuery={searchQuery}
|
||||
onSearchChange={handleSearchChange}
|
||||
/>
|
||||
|
||||
{/* Первая таблица */}
|
||||
<Paper sx={{
|
||||
mb: "2rem",
|
||||
overflow: "hidden",
|
||||
flex: "0 0 45vh",
|
||||
borderRadius: "1rem",
|
||||
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.1)',
|
||||
}}>
|
||||
<MaterialReactTable table={summaryProjectsTable} />
|
||||
</Paper>
|
||||
|
||||
{/* Вторая таблица */}
|
||||
<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",
|
||||
}}
|
||||
>
|
||||
{getSelectedProjectTitle()}
|
||||
</Typography>
|
||||
{selectedRow ?
|
||||
<Box sx={{ height: "calc(35vh - 3rem)" }}>
|
||||
<MaterialReactTable table={projectTable} />
|
||||
</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}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default SummaryPage;
|
||||
@ -1,550 +0,0 @@
|
||||
import React from "react";
|
||||
import { Box, IconButton, Tooltip } from "@mui/material";
|
||||
import StatusBadge from "./components/StatusBadge/StatusBadge";
|
||||
import { Back, EditPenSvg } from "../../components/common/icons/icons";
|
||||
|
||||
export const createFirstColumns = (handlers) => {
|
||||
const { onEdit, onNavigate } = handlers;
|
||||
return [
|
||||
{
|
||||
accessorKey: "project",
|
||||
header: "Проект",
|
||||
size: 200,
|
||||
filterFn: "contains",
|
||||
filterVariant: "text",
|
||||
},
|
||||
{
|
||||
accessorKey: "status",
|
||||
header: "Статус",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => {
|
||||
const status = cell.getValue();
|
||||
return <StatusBadge status={status} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "techNumber",
|
||||
header: "Технический номер проекта",
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
accessorKey: "address",
|
||||
header: "Адрес объекта",
|
||||
size: 180,
|
||||
},
|
||||
{
|
||||
accessorKey: "vspNumber",
|
||||
header: "Порядковый номер ВСП",
|
||||
size: 150,
|
||||
Cell: ({ cell }) => cell.getValue() ?? "",
|
||||
},
|
||||
{
|
||||
accessorKey: "krfDate",
|
||||
header: "Дата решения КРФ",
|
||||
size: 120,
|
||||
},
|
||||
{
|
||||
accessorKey: "fkDate",
|
||||
header: "Дата решения ФК",
|
||||
size: 120,
|
||||
},
|
||||
{
|
||||
accessorKey: "boardDate",
|
||||
header: "Дата решения Правления",
|
||||
size: 130,
|
||||
},
|
||||
{
|
||||
accessorKey: "openMoveCloseDate",
|
||||
header: "Дата открытия / переезда / закрытия",
|
||||
size: 160,
|
||||
},
|
||||
{
|
||||
accessorKey: "implementationMonths",
|
||||
header: "Время реализации проекта в месяцах",
|
||||
size: 140,
|
||||
Cell: ({ cell }) => `${cell.getValue()} мес.`,
|
||||
},
|
||||
{
|
||||
accessorKey: "koFinancing",
|
||||
header: "Финансирование по решению КО",
|
||||
size: 150,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "baseYearEstimate",
|
||||
header: "В базовой смете года",
|
||||
size: 130,
|
||||
},
|
||||
{
|
||||
accessorKey: "correctedEstimateQ2",
|
||||
header: "В скоррект смете 2 кв",
|
||||
size: 140,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "correctedEstimateQ3",
|
||||
header: "В скоррект смете 3 кв",
|
||||
size: 140,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "correctedEstimateQ4",
|
||||
header: "В скоррект смете 4 кв",
|
||||
size: 140,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "developmentType",
|
||||
header: "Тип развития",
|
||||
size: 130,
|
||||
},
|
||||
{
|
||||
accessorKey: "developmentBlock",
|
||||
header: "Блок развития",
|
||||
size: 120,
|
||||
},
|
||||
{
|
||||
accessorKey: "reserveBankAXR",
|
||||
header: "Из резерва Банка в смету ПРРС АХР",
|
||||
size: 160,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "reserveBankKV",
|
||||
header: "Из резерва Банка в смету ПРРС КВ",
|
||||
size: 160,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actions",
|
||||
header: "",
|
||||
size: 120,
|
||||
enableSorting: false,
|
||||
Cell: ({ row }) => (
|
||||
<Box sx={{ display: "flex", gap: 0.5 }}>
|
||||
<Tooltip title="Редактировать">
|
||||
<IconButton
|
||||
variant="outlined"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onEdit(row);
|
||||
}}
|
||||
>
|
||||
<EditPenSvg />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
{row.depth == 0 && (
|
||||
<Tooltip title="Перейти">
|
||||
<IconButton
|
||||
variant="outlined"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onNavigate(row);
|
||||
}}
|
||||
>
|
||||
<Back style={{ transform: "scaleX(-1)" }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Box>
|
||||
),
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
// Колонки для второй таблицы с многоуровневыми заголовками
|
||||
export const secondColumns = [
|
||||
{
|
||||
accessorKey: "project",
|
||||
header: "Проект",
|
||||
size: 120,
|
||||
sticky: "left",
|
||||
},
|
||||
// Объем финансирования по контрольному листу
|
||||
{
|
||||
header: "Объем финансирования по контрольному листу",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "financingAXR",
|
||||
header: "АХР",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "financingAXRLimit",
|
||||
header: "АХР лимит",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "financingAXRCurrent",
|
||||
header: "АХР текущие",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "financingKV",
|
||||
header: "КВ",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
// Базовый период
|
||||
{
|
||||
header: "Базовый период 01.01 - 31.03",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "baseAXR",
|
||||
header: "АХР",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "baseAXRLimit",
|
||||
header: "АХР лимит",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "baseAXRCurrent",
|
||||
header: "АХР текущие",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "baseKV",
|
||||
header: "КВ",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
// Скорректированный период Q2
|
||||
{
|
||||
header: "Скорректированный период 01.04 - 30.06",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "q2AXR",
|
||||
header: "АХР",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q2AXRLimit",
|
||||
header: "АХР лимит",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q2AXRCurrent",
|
||||
header: "АХР текущие",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q2KV",
|
||||
header: "КВ",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
// Скорректированный период Q3
|
||||
{
|
||||
header: "Скорректированный период 01.07 - 30.09",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "q3AXR",
|
||||
header: "АХР",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q3AXRLimit",
|
||||
header: "АХР лимит",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q3AXRCurrent",
|
||||
header: "АХР текущие",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q3KV",
|
||||
header: "КВ",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
// Скорректированный период Q4
|
||||
{
|
||||
header: "Скорректированный период 01.10 - 31.12",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "q4AXR",
|
||||
header: "АХР",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q4AXRLimit",
|
||||
header: "АХР лимит",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q4AXRCurrent",
|
||||
header: "АХР текущие",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "q4KV",
|
||||
header: "КВ",
|
||||
size: 100,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
// Фактические расходы (АХР)
|
||||
{
|
||||
header: "Фактические расходы (АХР)",
|
||||
columns: [
|
||||
{
|
||||
header: "1 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualAXRQ1",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRLimitQ1",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRCurrentQ1",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
header: "2 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualAXRQ2",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRLimitQ2",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRCurrentQ2",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
header: "3 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualAXRQ3",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRLimitQ3",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRCurrentQ3",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
header: "4 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualAXRQ4",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRLimitQ4",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualAXRCurrentQ4",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// Фактические расходы (КВ)
|
||||
{
|
||||
header: "Фактические расходы (КВ)",
|
||||
columns: [
|
||||
{
|
||||
header: "1 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualKVQ1",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVLimitQ1",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVCurrentQ1",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
header: "2 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualKVQ2",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVLimitQ2",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVCurrentQ2",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
header: "3 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualKVQ3",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVLimitQ3",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVCurrentQ3",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
header: "4 квартал",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "actualKVQ4",
|
||||
header: "Фактические расходы",
|
||||
size: 120,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVLimitQ4",
|
||||
header: "Лимит",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "actualKVCurrentQ4",
|
||||
header: "Текущие",
|
||||
size: 80,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// Смета 2026
|
||||
{
|
||||
header: "Смета 2026",
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "includeInEstimate2026",
|
||||
header: "Вкл в смету 2026",
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
accessorKey: "developmentBlock2026",
|
||||
header: "Блок развития 2026",
|
||||
size: 120,
|
||||
},
|
||||
{
|
||||
accessorKey: "impactRentAXR",
|
||||
header: "Влияние на АХР подд АРЕНДА год",
|
||||
size: 160,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "impactOtherAXR",
|
||||
header: "Влияние на АХР подд ПРОЧЕЕ год",
|
||||
size: 160,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "sumEstimateAXR",
|
||||
header: "Сумма в смету 2026 года АХР",
|
||||
size: 150,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
{
|
||||
accessorKey: "sumEstimateKV",
|
||||
header: "Сумма в смету 2026 года КВ",
|
||||
size: 150,
|
||||
Cell: ({ cell }) => cell.getValue().toLocaleString(),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -1,202 +0,0 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
Button,
|
||||
TextField,
|
||||
Grid,
|
||||
Box,
|
||||
IconButton,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { DangerOutlinedButton, PrimaryButton } from '../../../../components/common/Buttons/Buttons';
|
||||
|
||||
const EditModal = ({ open, onClose, rowData, onSave }) => {
|
||||
const [formData, setFormData] = React.useState(rowData || {});
|
||||
|
||||
React.useEffect(() => {
|
||||
if (rowData) {
|
||||
setFormData(rowData);
|
||||
}
|
||||
}, [rowData]);
|
||||
|
||||
const handleChange = (field) => (event) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[field]: event.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
onSave(formData);
|
||||
onClose();
|
||||
};
|
||||
|
||||
if (!rowData) return null;
|
||||
|
||||
const leftColumnFields = [
|
||||
{ key: 'project', label: 'Проект', placeholder: 'Смета_2026' },
|
||||
{ key: 'techNumber', label: 'Технический номер проекта', placeholder: '2606_180801' },
|
||||
{ key: 'vspNumber', label: 'Порядковый номер ВСП', placeholder: '1808' },
|
||||
{ key: 'fkDate', label: 'Дата решения ФК', type: 'date', placeholder: '18.06.2026' },
|
||||
{ key: 'openMoveCloseDate', label: 'Дата открытия / переезда / закрытия', type: 'date' },
|
||||
{ key: 'koFinancing', label: 'Финансирование по решению КО', type: 'number' },
|
||||
{ key: 'prrsEstimate', label: 'Смета ПРРС' },
|
||||
{ key: 'correctedEstimateQ2', label: 'В скоррект смете 2 кв', type: 'number' },
|
||||
{ key: 'baseYearEstimate', label: 'В базовой смете года' },
|
||||
{ key: 'correctedEstimateQ3', label: 'В скоррект смете 3 кв', type: 'number' },
|
||||
];
|
||||
|
||||
const rightColumnFields = [
|
||||
{ key: 'correctedEstimateQ4', label: 'В скоррект смете 4 кв', type: 'number' },
|
||||
{ key: 'developmentBlock', label: 'Блок развития' },
|
||||
{ key: 'reserveBankKV', label: 'Из резерва Банка в смету ПРРС КВ', type: 'number' },
|
||||
{ key: 'status', label: 'Статус' },
|
||||
{ key: 'krfDate', label: 'Дата решения КРФ', type: 'date' },
|
||||
{ key: 'boardDate', label: 'Дата решения Правления', type: 'date' },
|
||||
{ key: 'implementationMonths', label: 'Время реализации проекта в месяцах', type: 'number' },
|
||||
{ key: 'developmentType', label: 'Тип развития', placeholder: 'Реновация ВСП' },
|
||||
{ key: 'reserveBankAXR', label: 'Из резерва Банка в смету ПРРС АХР', type: 'number' },
|
||||
{ key: 'address', label: 'Адрес объекта', multiline: true, rows: 2, placeholder: '658213, Алтайский кр., г. Рубцовск, ул. Дзержинского, д. 14' },
|
||||
];
|
||||
|
||||
// Компонент для поля ввода
|
||||
const renderField = (field) => (
|
||||
<Box key={field.key} sx={{ width: '390px', flexShrink: 0 }}>
|
||||
<Typography variant="caption" sx={{
|
||||
fontWeight: 600,
|
||||
color: '#666',
|
||||
display: 'block',
|
||||
mb: 0.5,
|
||||
fontSize: '0.75rem',
|
||||
}}>
|
||||
{field.label}
|
||||
</Typography>
|
||||
<TextField
|
||||
fullWidth
|
||||
value={formData[field.key] || ''}
|
||||
onChange={handleChange(field.key)}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
type={field.type || 'text'}
|
||||
placeholder={field.placeholder || ''}
|
||||
multiline={field.multiline || false}
|
||||
rows={field.rows || 1}
|
||||
InputLabelProps={field.type === 'date' ? { shrink: true } : undefined}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
bgcolor: 'transparent',
|
||||
'& fieldset': {
|
||||
borderColor: '#d0d0d0',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#b0b0b0',
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: '#1976d2',
|
||||
},
|
||||
...(field.multiline && {
|
||||
minHeight: '56px',
|
||||
}),
|
||||
},
|
||||
'& .MuiOutlinedInput-input': {
|
||||
bgcolor: 'transparent',
|
||||
},
|
||||
'& .MuiInputBase-input': {
|
||||
bgcolor: 'transparent',
|
||||
},
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
maxWidth={false}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
borderRadius: '12px',
|
||||
maxHeight: '90vh',
|
||||
height: 'auto',
|
||||
maxWidth: '820px',
|
||||
width: '100%',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{
|
||||
m: 0,
|
||||
p: '16px 24px',
|
||||
borderBottom: '1px solid #e0e0e0',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
bgcolor: '#f8f9fa',
|
||||
}}>
|
||||
<Typography variant="h6" fontWeight="600" fontSize="18px">
|
||||
Редактирование строки
|
||||
</Typography>
|
||||
<IconButton onClick={onClose} size="small">
|
||||
<CloseIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent sx={{
|
||||
pt: 3,
|
||||
pb: 2,
|
||||
px: 3,
|
||||
overflow: 'auto',
|
||||
}}>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
gap: '20px',
|
||||
justifyContent: 'space-between',
|
||||
}}>
|
||||
{/* Левая колонка */}
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
flex: '0 0 auto',
|
||||
}}>
|
||||
{leftColumnFields.map(renderField)}
|
||||
</Box>
|
||||
|
||||
{/* Правая колонка */}
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
flex: '0 0 auto',
|
||||
}}>
|
||||
{rightColumnFields.map(renderField)}
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions sx={{
|
||||
p: 2,
|
||||
px: 3,
|
||||
borderTop: '1px solid #e0e0e0',
|
||||
bgcolor: '#f8f9fa',
|
||||
justifyContent: 'flex-end',
|
||||
gap: 1,
|
||||
}}>
|
||||
<DangerOutlinedButton onClick={onClose}>
|
||||
Отмена
|
||||
</DangerOutlinedButton>
|
||||
|
||||
<PrimaryButton onClick={handleSave}>
|
||||
Сохранить
|
||||
</PrimaryButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditModal;
|
||||
@ -1,39 +0,0 @@
|
||||
import React from 'react';
|
||||
import styles from './StatusBadge.module.css';
|
||||
|
||||
const StatusBadge = ({ status, className = '', ...props }) => {
|
||||
const statusMap = {
|
||||
deleted: {
|
||||
class: styles.deleted,
|
||||
label: 'Удален',
|
||||
},
|
||||
approved: {
|
||||
class: styles.approved,
|
||||
label: 'Согласован',
|
||||
},
|
||||
archived: {
|
||||
class: styles.archived,
|
||||
label: 'В архиве',
|
||||
},
|
||||
created: {
|
||||
class: styles.created,
|
||||
label: 'Создан',
|
||||
},
|
||||
};
|
||||
|
||||
// Если статус не найден, ничего не рендерим или показываем дефолтный
|
||||
const currentStatus = statusMap[status];
|
||||
|
||||
if (!currentStatus) return null;
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`${styles.badge} ${currentStatus.class} ${className}`}
|
||||
{...props}
|
||||
>
|
||||
{currentStatus.label}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatusBadge;
|
||||
@ -1,37 +0,0 @@
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
-moz-box-align: center;
|
||||
align-items: center;
|
||||
min-height: 1.5rem;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
border: 1px solid rgb(254, 202, 202);
|
||||
border-radius: 3914px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.deleted {
|
||||
background-color: #fbe7e9;
|
||||
border-color: #f5d3d6;
|
||||
color: #7e2a2a;
|
||||
}
|
||||
|
||||
.approved {
|
||||
background-color: #e6f4ea;
|
||||
border-color: #ceead6;
|
||||
color: #1e7e34;
|
||||
}
|
||||
|
||||
.archived {
|
||||
background-color: #f1f3f4;
|
||||
border-color: #dadce0;
|
||||
color: #5f6368;
|
||||
}
|
||||
|
||||
.created {
|
||||
background-color: #e8f0fe;
|
||||
border-color: #d2e3fc;
|
||||
color: #1967d2;
|
||||
}
|
||||
@ -1,144 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
TextField,
|
||||
Autocomplete,
|
||||
Paper,
|
||||
Typography,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
} from '@mui/material';
|
||||
import { Search } from '@mui/icons-material';
|
||||
import { SspApi } from '../../../../api/ssp';
|
||||
|
||||
const TableFilters = ({
|
||||
onBranchChange,
|
||||
onSearchChange,
|
||||
selectedBranch,
|
||||
searchQuery,
|
||||
}) => {
|
||||
const [branches, setBranches] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// Загружаем филиалы из API
|
||||
useEffect(() => {
|
||||
const loadBranches = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await SspApi.getAll({ is_active: true });
|
||||
setBranches(data.result);
|
||||
} catch (error) {
|
||||
console.error('Error loading branches:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
loadBranches();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
mb: '1vh',
|
||||
backgroundColor: 'transparent',
|
||||
}}
|
||||
>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.5vh',
|
||||
flexWrap: 'wrap',
|
||||
maxHeight: '4.5vh',
|
||||
}}>
|
||||
|
||||
<Autocomplete
|
||||
size="small"
|
||||
sx={{
|
||||
minWidth: 250,
|
||||
maxWidth: 300,
|
||||
flex: '1 1 auto',
|
||||
}}
|
||||
options={branches}
|
||||
loading={loading}
|
||||
getOptionLabel={(option) => option.title || ''}
|
||||
getOptionKey={(option) => option.id}
|
||||
value={selectedBranch || null}
|
||||
onChange={(event, newValue) => {
|
||||
onBranchChange(newValue || '');
|
||||
}}
|
||||
renderInput={(params) => {
|
||||
const { InputProps, ...rest } = params;
|
||||
return (
|
||||
<TextField
|
||||
{...rest}
|
||||
placeholder="Региональные филиалы"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
InputProps={{
|
||||
...InputProps,
|
||||
endAdornment: (
|
||||
<>
|
||||
{loading && <CircularProgress color="inherit" size={20} />}
|
||||
{InputProps?.endAdornment}
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
renderOption={(props, option) => (
|
||||
<li {...props} key={option.id}>
|
||||
{option.title}
|
||||
</li>
|
||||
)}
|
||||
clearOnBlur={false}
|
||||
isOptionEqualToValue={(option, value) => option === value}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
size="small"
|
||||
placeholder="Название проекта"
|
||||
variant="outlined"
|
||||
value={searchQuery}
|
||||
onChange={(e) => onSearchChange(e.target.value)}
|
||||
sx={{
|
||||
minWidth: 250,
|
||||
maxWidth: 300,
|
||||
flex: '1 1 auto',
|
||||
}}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<Search sx={{
|
||||
color: 'text.secondary',
|
||||
mr: 1,
|
||||
fontSize: 20,
|
||||
}} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
|
||||
{(selectedBranch || searchQuery) && (
|
||||
<Box sx={{ display: 'flex', gap: 1, ml: 'auto' }}>
|
||||
<Chip
|
||||
label="Сбросить фильтры"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
onBranchChange('');
|
||||
onSearchChange('');
|
||||
}}
|
||||
sx={{
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
backgroundColor: 'action.hover',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
export default TableFilters;
|
||||
@ -1,420 +0,0 @@
|
||||
export const firstTableData = [
|
||||
{
|
||||
id: "478",
|
||||
org_unit_id: 6,
|
||||
project: "Алтайский_01",
|
||||
status: "created",
|
||||
techNumber: "2606_180801",
|
||||
address: "658213, Алтайский кр., г. Рубцовск, ул. Дз...",
|
||||
vspNumber: 1808,
|
||||
krfDate: "11.06.2026",
|
||||
fkDate: "18.06.2026",
|
||||
boardDate: "✅",
|
||||
openMoveCloseDate: "15.07.2026",
|
||||
implementationMonths: 8,
|
||||
koFinancing: 35697,
|
||||
baseYearEstimate: "2026",
|
||||
correctedEstimateQ2: 12482,
|
||||
correctedEstimateQ3: 13200,
|
||||
correctedEstimateQ4: 14100,
|
||||
developmentType: "Новое строительство",
|
||||
developmentBlock: "Центральный",
|
||||
reserveBankAXR: 1500,
|
||||
reserveBankKV: 2300,
|
||||
subRows: [
|
||||
{
|
||||
id: "sub_001_01",
|
||||
project: "Смета_2026",
|
||||
status: "Активна",
|
||||
techNumber: "2606_180801_01",
|
||||
address: "г. Рубцовск, ул. Дзержинского, 10",
|
||||
vspNumber: 1809,
|
||||
krfDate: "12.06.2026",
|
||||
fkDate: "19.06.2026",
|
||||
boardDate: "✅",
|
||||
openMoveCloseDate: "15.07.2026",
|
||||
implementationMonths: 8,
|
||||
koFinancing: 11762,
|
||||
baseYearEstimate: "2026",
|
||||
correctedEstimateQ2: 12482,
|
||||
correctedEstimateQ3: 13200,
|
||||
correctedEstimateQ4: 14100,
|
||||
developmentType: "Реконструкция",
|
||||
developmentBlock: "Центральный",
|
||||
reserveBankAXR: 500,
|
||||
reserveBankKV: 800,
|
||||
},
|
||||
{
|
||||
id: "sub_001_02",
|
||||
project: "Смета_2027",
|
||||
status: "Планируется",
|
||||
techNumber: "2606_180801_02",
|
||||
address: "г. Рубцовск, ул. Ленина, 25",
|
||||
vspNumber: 1810,
|
||||
krfDate: "13.06.2026",
|
||||
fkDate: "20.06.2026",
|
||||
boardDate: "⏳",
|
||||
openMoveCloseDate: "01.08.2027",
|
||||
implementationMonths: 12,
|
||||
koFinancing: 11899,
|
||||
baseYearEstimate: "2027",
|
||||
correctedEstimateQ2: 12619,
|
||||
correctedEstimateQ3: 13400,
|
||||
correctedEstimateQ4: 14300,
|
||||
developmentType: "Модернизация",
|
||||
developmentBlock: "Северный",
|
||||
reserveBankAXR: 600,
|
||||
reserveBankKV: 900,
|
||||
},
|
||||
{
|
||||
id: "sub_001_03",
|
||||
project: "Смета_2028",
|
||||
status: "Планируется",
|
||||
techNumber: "2606_180801_03",
|
||||
address: "г. Рубцовск, ул. Советская, 15",
|
||||
vspNumber: 1811,
|
||||
krfDate: "14.06.2026",
|
||||
fkDate: "21.06.2026",
|
||||
boardDate: "⏳",
|
||||
openMoveCloseDate: "01.08.2028",
|
||||
implementationMonths: 14,
|
||||
koFinancing: 12036,
|
||||
baseYearEstimate: "2028",
|
||||
correctedEstimateQ2: 12756,
|
||||
correctedEstimateQ3: 13600,
|
||||
correctedEstimateQ4: 14500,
|
||||
developmentType: "Расширение",
|
||||
developmentBlock: "Южный",
|
||||
reserveBankAXR: 700,
|
||||
reserveBankKV: 1000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "proj_002",
|
||||
project: "Алтайский_02",
|
||||
org_unit_id: 6,
|
||||
status: "deleted",
|
||||
techNumber: "2602_180801",
|
||||
address: "658213, Алтайский кр., г. Рубцовск, ул. Дз...",
|
||||
vspNumber: 1808,
|
||||
krfDate: "11.01.2026",
|
||||
fkDate: "16.01.2026",
|
||||
boardDate: "✅",
|
||||
openMoveCloseDate: "15.02.2026",
|
||||
implementationMonths: 3,
|
||||
koFinancing: 25000,
|
||||
baseYearEstimate: "2026",
|
||||
correctedEstimateQ2: 8500,
|
||||
correctedEstimateQ3: 9200,
|
||||
correctedEstimateQ4: 9800,
|
||||
developmentType: "Временный",
|
||||
developmentBlock: "Западный",
|
||||
reserveBankAXR: 300,
|
||||
reserveBankKV: 500,
|
||||
subRows: [],
|
||||
},
|
||||
{
|
||||
id: "proj_003",
|
||||
project: "Алтайский_03",
|
||||
org_unit_id: 7,
|
||||
status: "approved",
|
||||
techNumber: "2512_180601",
|
||||
address: "Алтайский кр., объект развития ВСП",
|
||||
vspNumber: null,
|
||||
krfDate: "10.04.2025",
|
||||
fkDate: "25.10.2025",
|
||||
boardDate: "02.11.2025",
|
||||
openMoveCloseDate: "01.12.2025",
|
||||
implementationMonths: 6,
|
||||
koFinancing: 32000,
|
||||
baseYearEstimate: "2025",
|
||||
correctedEstimateQ2: 10500,
|
||||
correctedEstimateQ3: 11200,
|
||||
correctedEstimateQ4: 11800,
|
||||
developmentType: "Капитальный ремонт",
|
||||
developmentBlock: "Восточный",
|
||||
reserveBankAXR: 400,
|
||||
reserveBankKV: 600,
|
||||
subRows: [
|
||||
{
|
||||
id: "sub_003_01",
|
||||
project: "Подпроект А",
|
||||
status: "Завершен",
|
||||
techNumber: "2512_180601_А",
|
||||
address: "г. Барнаул, ул. Пушкина, 15",
|
||||
vspNumber: 1811,
|
||||
krfDate: "11.04.2025",
|
||||
fkDate: "26.10.2025",
|
||||
boardDate: "03.11.2025",
|
||||
openMoveCloseDate: "15.11.2025",
|
||||
implementationMonths: 5,
|
||||
koFinancing: 15000,
|
||||
baseYearEstimate: "2025",
|
||||
correctedEstimateQ2: 5000,
|
||||
correctedEstimateQ3: 5500,
|
||||
correctedEstimateQ4: 6000,
|
||||
developmentType: "Реконструкция",
|
||||
developmentBlock: "Восточный",
|
||||
reserveBankAXR: 200,
|
||||
reserveBankKV: 300,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "proj_004",
|
||||
project: "Башкирский_01",
|
||||
status: "archived",
|
||||
org_unit_id: 8,
|
||||
techNumber: "2405_620501",
|
||||
address: "Республика Башкортостан, проект развит...",
|
||||
vspNumber: null,
|
||||
krfDate: "03.06.2024",
|
||||
fkDate: "14.06.2024",
|
||||
boardDate: "02.07.2024",
|
||||
openMoveCloseDate: "15.08.2024",
|
||||
implementationMonths: 10,
|
||||
koFinancing: 45000,
|
||||
baseYearEstimate: "2024",
|
||||
correctedEstimateQ2: 15000,
|
||||
correctedEstimateQ3: 16000,
|
||||
correctedEstimateQ4: 17000,
|
||||
developmentType: "Новое строительство",
|
||||
developmentBlock: "Центральный",
|
||||
reserveBankAXR: 800,
|
||||
reserveBankKV: 1200,
|
||||
subRows: [],
|
||||
},
|
||||
];
|
||||
|
||||
// Вторая таблица - объект, где ключ - id проекта, значение - массив данных для этого проекта
|
||||
export const secondTableData = {
|
||||
// Для проекта Алтайский_01 (3 дочерних строки)
|
||||
478: [
|
||||
{
|
||||
id: "sub_001_01",
|
||||
project: "Смета_2026",
|
||||
financingAXR: 11942,
|
||||
financingAXRLimit: 12122,
|
||||
financingAXRCurrent: 10502,
|
||||
financingKV: 12482,
|
||||
baseAXR: 2800,
|
||||
baseAXRLimit: 3000,
|
||||
baseAXRCurrent: 2500,
|
||||
baseKV: 2900,
|
||||
q2AXR: 3100,
|
||||
q2AXRLimit: 3300,
|
||||
q2AXRCurrent: 2800,
|
||||
q2KV: 3200,
|
||||
q3AXR: 3400,
|
||||
q3AXRLimit: 3600,
|
||||
q3AXRCurrent: 3100,
|
||||
q3KV: 3500,
|
||||
q4AXR: 3700,
|
||||
q4AXRLimit: 3900,
|
||||
q4AXRCurrent: 3400,
|
||||
q4KV: 3800,
|
||||
actualAXRQ1: 2400,
|
||||
actualAXRLimitQ1: 2600,
|
||||
actualAXRCurrentQ1: 2200,
|
||||
actualAXRQ2: 2800,
|
||||
actualAXRLimitQ2: 3000,
|
||||
actualAXRCurrentQ2: 2600,
|
||||
actualAXRQ3: 3200,
|
||||
actualAXRLimitQ3: 3400,
|
||||
actualAXRCurrentQ3: 3000,
|
||||
actualAXRQ4: 3600,
|
||||
actualAXRLimitQ4: 3800,
|
||||
actualAXRCurrentQ4: 3400,
|
||||
actualKVQ1: 2500,
|
||||
actualKVLimitQ1: 2700,
|
||||
actualKVCurrentQ1: 2300,
|
||||
actualKVQ2: 2900,
|
||||
actualKVLimitQ2: 3100,
|
||||
actualKVCurrentQ2: 2700,
|
||||
actualKVQ3: 3300,
|
||||
actualKVLimitQ3: 3500,
|
||||
actualKVCurrentQ3: 3100,
|
||||
actualKVQ4: 3700,
|
||||
actualKVLimitQ4: 3900,
|
||||
actualKVCurrentQ4: 3500,
|
||||
includeInEstimate2026: "Да",
|
||||
developmentBlock2026: "Центральный",
|
||||
impactRentAXR: 200,
|
||||
impactOtherAXR: 100,
|
||||
sumEstimateAXR: 11942,
|
||||
sumEstimateKV: 12482,
|
||||
},
|
||||
{
|
||||
id: "sub_001_02",
|
||||
project: "Смета_2027",
|
||||
financingAXR: 12079,
|
||||
financingAXRLimit: 12259,
|
||||
financingAXRCurrent: 10639,
|
||||
financingKV: 12619,
|
||||
baseAXR: 2900,
|
||||
baseAXRLimit: 3100,
|
||||
baseAXRCurrent: 2600,
|
||||
baseKV: 3000,
|
||||
q2AXR: 3200,
|
||||
q2AXRLimit: 3400,
|
||||
q2AXRCurrent: 2900,
|
||||
q2KV: 3300,
|
||||
q3AXR: 3500,
|
||||
q3AXRLimit: 3700,
|
||||
q3AXRCurrent: 3200,
|
||||
q3KV: 3600,
|
||||
q4AXR: 3800,
|
||||
q4AXRLimit: 4000,
|
||||
q4AXRCurrent: 3500,
|
||||
q4KV: 3900,
|
||||
actualAXRQ1: 2500,
|
||||
actualAXRLimitQ1: 2700,
|
||||
actualAXRCurrentQ1: 2300,
|
||||
actualAXRQ2: 2900,
|
||||
actualAXRLimitQ2: 3100,
|
||||
actualAXRCurrentQ2: 2700,
|
||||
actualAXRQ3: 3300,
|
||||
actualAXRLimitQ3: 3500,
|
||||
actualAXRCurrentQ3: 3100,
|
||||
actualAXRQ4: 3700,
|
||||
actualAXRLimitQ4: 3900,
|
||||
actualAXRCurrentQ4: 3500,
|
||||
actualKVQ1: 2600,
|
||||
actualKVLimitQ1: 2800,
|
||||
actualKVCurrentQ1: 2400,
|
||||
actualKVQ2: 3000,
|
||||
actualKVLimitQ2: 3200,
|
||||
actualKVCurrentQ2: 2800,
|
||||
actualKVQ3: 3400,
|
||||
actualKVLimitQ3: 3600,
|
||||
actualKVCurrentQ3: 3200,
|
||||
actualKVQ4: 3800,
|
||||
actualKVLimitQ4: 4000,
|
||||
actualKVCurrentQ4: 3600,
|
||||
includeInEstimate2026: "Нет",
|
||||
developmentBlock2026: "Северный",
|
||||
impactRentAXR: 250,
|
||||
impactOtherAXR: 150,
|
||||
sumEstimateAXR: 12079,
|
||||
sumEstimateKV: 12619,
|
||||
},
|
||||
{
|
||||
id: "sub_001_03",
|
||||
project: "Смета_2028",
|
||||
financingAXR: 12216,
|
||||
financingAXRLimit: 12396,
|
||||
financingAXRCurrent: 10776,
|
||||
financingKV: 12756,
|
||||
baseAXR: 3000,
|
||||
baseAXRLimit: 3200,
|
||||
baseAXRCurrent: 2700,
|
||||
baseKV: 3100,
|
||||
q2AXR: 3300,
|
||||
q2AXRLimit: 3500,
|
||||
q2AXRCurrent: 3000,
|
||||
q2KV: 3400,
|
||||
q3AXR: 3600,
|
||||
q3AXRLimit: 3800,
|
||||
q3AXRCurrent: 3300,
|
||||
q3KV: 3700,
|
||||
q4AXR: 3900,
|
||||
q4AXRLimit: 4100,
|
||||
q4AXRCurrent: 3600,
|
||||
q4KV: 4000,
|
||||
actualAXRQ1: 2600,
|
||||
actualAXRLimitQ1: 2800,
|
||||
actualAXRCurrentQ1: 2400,
|
||||
actualAXRQ2: 3000,
|
||||
actualAXRLimitQ2: 3200,
|
||||
actualAXRCurrentQ2: 2800,
|
||||
actualAXRQ3: 3400,
|
||||
actualAXRLimitQ3: 3600,
|
||||
actualAXRCurrentQ3: 3200,
|
||||
actualAXRQ4: 3800,
|
||||
actualAXRLimitQ4: 4000,
|
||||
actualAXRCurrentQ4: 3600,
|
||||
actualKVQ1: 2700,
|
||||
actualKVLimitQ1: 2900,
|
||||
actualKVCurrentQ1: 2500,
|
||||
actualKVQ2: 3100,
|
||||
actualKVLimitQ2: 3300,
|
||||
actualKVCurrentQ2: 2900,
|
||||
actualKVQ3: 3500,
|
||||
actualKVLimitQ3: 3700,
|
||||
actualKVCurrentQ3: 3300,
|
||||
actualKVQ4: 3900,
|
||||
actualKVLimitQ4: 4100,
|
||||
actualKVCurrentQ4: 3700,
|
||||
includeInEstimate2026: "Нет",
|
||||
developmentBlock2026: "Южный",
|
||||
impactRentAXR: 300,
|
||||
impactOtherAXR: 200,
|
||||
sumEstimateAXR: 12216,
|
||||
sumEstimateKV: 12756,
|
||||
},
|
||||
],
|
||||
|
||||
// Для проекта Алтайский_02 (0 дочерних строк - пустой массив)
|
||||
proj_002: [],
|
||||
|
||||
// Для проекта Алтайский_03 (1 дочерняя строка)
|
||||
proj_003: [
|
||||
{
|
||||
id: "sub_003_01",
|
||||
project: "Подпроект А",
|
||||
financingAXR: 15200,
|
||||
financingAXRLimit: 15400,
|
||||
financingAXRCurrent: 13800,
|
||||
financingKV: 15800,
|
||||
baseAXR: 3500,
|
||||
baseAXRLimit: 3700,
|
||||
baseAXRCurrent: 3200,
|
||||
baseKV: 3600,
|
||||
q2AXR: 3800,
|
||||
q2AXRLimit: 4000,
|
||||
q2AXRCurrent: 3500,
|
||||
q2KV: 3900,
|
||||
q3AXR: 4100,
|
||||
q3AXRLimit: 4300,
|
||||
q3AXRCurrent: 3800,
|
||||
q3KV: 4200,
|
||||
q4AXR: 4400,
|
||||
q4AXRLimit: 4600,
|
||||
q4AXRCurrent: 4100,
|
||||
q4KV: 4500,
|
||||
actualAXRQ1: 3200,
|
||||
actualAXRLimitQ1: 3400,
|
||||
actualAXRCurrentQ1: 3000,
|
||||
actualAXRQ2: 3600,
|
||||
actualAXRLimitQ2: 3800,
|
||||
actualAXRCurrentQ2: 3400,
|
||||
actualAXRQ3: 4000,
|
||||
actualAXRLimitQ3: 4200,
|
||||
actualAXRCurrentQ3: 3800,
|
||||
actualAXRQ4: 4400,
|
||||
actualAXRLimitQ4: 4600,
|
||||
actualAXRCurrentQ4: 4200,
|
||||
actualKVQ1: 3300,
|
||||
actualKVLimitQ1: 3500,
|
||||
actualKVCurrentQ1: 3100,
|
||||
actualKVQ2: 3700,
|
||||
actualKVLimitQ2: 3900,
|
||||
actualKVCurrentQ2: 3500,
|
||||
actualKVQ3: 4100,
|
||||
actualKVLimitQ3: 4300,
|
||||
actualKVCurrentQ3: 3900,
|
||||
actualKVQ4: 4500,
|
||||
actualKVLimitQ4: 4700,
|
||||
actualKVCurrentQ4: 4300,
|
||||
includeInEstimate2026: "Да",
|
||||
developmentBlock2026: "Восточный",
|
||||
impactRentAXR: 400,
|
||||
impactOtherAXR: 200,
|
||||
sumEstimateAXR: 15200,
|
||||
sumEstimateKV: 15800,
|
||||
},
|
||||
],
|
||||
|
||||
proj_004: [],
|
||||
};
|
||||
@ -1,14 +0,0 @@
|
||||
export const handleEditClick = (row, setEditModalOpen, setSelectedRowData) => {
|
||||
setSelectedRowData(row.original);
|
||||
setEditModalOpen(true);
|
||||
};
|
||||
|
||||
export const handleNavigateClick = (row, navigate) => {
|
||||
const projectId = row.original.id || row.original.project;
|
||||
navigate(`/project/${projectId}`);
|
||||
};
|
||||
|
||||
export const handleSaveEdit = (formData, updateTableData) => {
|
||||
updateTableData(formData);
|
||||
console.log('Сохраненные данные:', formData);
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user