diff --git a/web/src/api/expense-item.js b/web/src/api/expense-item.js
new file mode 100644
index 0000000..4365d46
--- /dev/null
+++ b/web/src/api/expense-item.js
@@ -0,0 +1,7 @@
+import api from "./client";
+
+export const ExpenseItemApi = {
+ getAll(params) {
+ return api.get(`/expense-item/`, { params }).then((r) => r.data);
+ },
+};
diff --git a/web/src/components/RealtimeTable/Modals/SelectExpenseItemModal.jsx b/web/src/components/RealtimeTable/Modals/SelectExpenseItemModal.jsx
new file mode 100644
index 0000000..0277f32
--- /dev/null
+++ b/web/src/components/RealtimeTable/Modals/SelectExpenseItemModal.jsx
@@ -0,0 +1,158 @@
+import { useEffect, useState } from 'react';
+import {
+ Box,
+ Button,
+ Divider,
+ FormControl,
+ FormLabel,
+ IconButton,
+ Stack,
+ Select,
+ MenuItem,
+ Autocomplete,
+ TextField,
+} from '@mui/material';
+import {
+ ModalBackdrop,
+ ModalContainer,
+ HeaderContainer,
+ ModalTitle,
+} from '../../common/Modal/ModalStyled';
+import { Cancel } from '../../common/icons/icons';
+import { DictVspApi } from '../../../api/dict-vsp';
+import { toast } from 'react-toastify';
+import { ExpenseItemApi } from '../../../api/expense-item';
+
+export const SelectExpenseItemModal = ({
+ isOpen,
+ onClose,
+ onSelect,
+ formId,
+ title = '',
+ isSaving = false,
+ sheet,
+}) => {
+ const [selectedValue, setSelectedValue] = useState('');
+ const [expenseItemOptions, setExpenseItemOption] = useState([])
+
+ useEffect(() => {
+ if (formId === null) return;
+ ExpenseItemApi.getAll({ r_start: true, sheet: sheet }).then(data => {
+ if (data.success) {
+ setExpenseItemOption(data.result)
+ return;
+ }
+ toast.error('Ошибка получения статья расходов')
+ })
+ }, [formId])
+
+ useEffect(() => {
+ if (!isOpen) {
+ setSelectedValue('');
+ }
+ }, [isOpen])
+
+ const handleCancel = () => {
+ setSelectedValue('');
+ onClose();
+ };
+
+ const handleBackdropClick = (e) => {
+ if (e.target === e.currentTarget) {
+ handleCancel();
+ }
+ };
+
+ const handleSave = () => {
+ onSelect?.(selectedValue);
+ onClose();
+ };
+
+ const isFormValid = selectedValue;
+
+ if (!isOpen) return null;
+
+ return (
+
+
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+ {/* Выбор ВСП */}
+
+
+ option.name || ''}
+ getOptionKey={(option) => option.id}
+ value={selectedValue}
+ onChange={(event, newValue) => {
+ setSelectedValue(newValue);
+ }}
+ slotProps={{
+ popper: {
+ style: { zIndex: 60 },
+ },
+ }}
+ renderInput={(params) => (
+
+ )}
+ />
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/web/src/components/RealtimeTable/RealtimeTable.jsx b/web/src/components/RealtimeTable/RealtimeTable.jsx
index c3bdbac..396753e 100644
--- a/web/src/components/RealtimeTable/RealtimeTable.jsx
+++ b/web/src/components/RealtimeTable/RealtimeTable.jsx
@@ -1,4 +1,3 @@
-// components/RealtimeTable/index.js
import React, { useState, useMemo, useRef, useEffect, useCallback, useTransition } from 'react';
import { createPortal } from 'react-dom';
import {
@@ -25,9 +24,11 @@ import {
import { useRealtime } from './contexts/RealtimeContext';
import { toast } from 'react-toastify';
import { CircularProgress } from '@mui/material';
-import { additionVspRowTable } from './constants/addingRowConfig';
+import { additionExpenseRowTable, additionVspRowTable } from './constants/addingRowConfig';
import { SelectVspModal } from './Modals/SelectVspModal';
+import { SelectExpenseItemModal } from './Modals/SelectExpenseItemModal';
import { getRowId } from './utils/rowUtils';
+import { FORM_TYPE_OPTIONS } from '../../constants/constants';
const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
const { data, setData, isLoading: isTableLoading, editingCells: dataEditingCells } = useRealtimeData(formId, sheetName, direction, formType, year);
@@ -40,6 +41,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
const [editingCell, setEditingCell] = useState(null);
const [isOpenModalSelectVsp, setIsOpenModalSelectVsp] = useState(false);
+ const [isOpenModalSelectExpenseItem, setIsOpenModalSelectExpenseItem] = useState(false);
const isVspAdditionRow = useMemo(() => {
if (!formType || !sheetName) return false;
@@ -47,6 +49,12 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
return additionVspRowTable[formType].includes(sheetName);
}, [formType, sheetName]);
+ const isAdditionExpenseItem = useMemo(() => {
+ if (!formType || !sheetName) return false;
+ if (!additionExpenseRowTable[formType]) return false;
+ return additionExpenseRowTable[formType].includes(sheetName);
+ }, [formType, sheetName]);
+
const handleGlobalFilterChange = (value) => {
startTransition(() => {
setGlobalFilter(value);
@@ -359,11 +367,19 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
const handleAddVspRow = useCallback((vsp_id) => {
contextAddRow({ vsp_id: vsp_id });
- }, [rowSelection, table]);
+ }, []);
+
+ const handleAddExpenseItemRow = useCallback((expense_item) => {
+ contextAddRow({ expense_item_id: expense_item.id });
+ }, []);
const handleOpenModalSelectVsp = useCallback(() => {
setIsOpenModalSelectVsp(true);
- }, [rowSelection, table])
+ }, [])
+
+ const handleOpenModalSelectExpenseItem = useCallback(() => {
+ setIsOpenModalSelectExpenseItem(true);
+ }, [])
const handleDeleteRow = useCallback(() => {
const allRows = table.getRowModel().rows;
@@ -379,6 +395,17 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
setRowSelection({});
}, [rowSelection, table])
+ const addRow = useCallback(() => {
+
+ if (isVspAdditionRow) {
+ return handleOpenModalSelectVsp();
+ }
+ if (isAdditionExpenseItem) {
+ return handleOpenModalSelectExpenseItem();
+ }
+ return handleAddRow();
+ }, [isVspAdditionRow, isAdditionExpenseItem, handleOpenModalSelectVsp, handleAddRow]);
+
useEffect(() => {
return () => {
setData([]);
@@ -405,7 +432,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
onGlobalFilterChange={handleGlobalFilterChange}
sizeMult={sizeMult}
onChangeShowColumnFilters={setShowColumnFilters}
- onAddRow={isVspAdditionRow ? handleOpenModalSelectVsp : handleAddRow}
+ onAddRow={addRow}
onDeleteRow={handleDeleteRow}
isLoadingData={isLoadingData}
formId={formId}
@@ -475,6 +502,14 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
onSelect={handleAddVspRow}
title="Выбор ВСП"
/>
+ setIsOpenModalSelectExpenseItem(false)}
+ formId={formId}
+ onSelect={handleAddExpenseItemRow}
+ title="Добавление строки"
+ sheet={sheetName}
+ />
>
);
};
diff --git a/web/src/components/RealtimeTable/constants/addingRowConfig.js b/web/src/components/RealtimeTable/constants/addingRowConfig.js
index 04e069b..7a50017 100644
--- a/web/src/components/RealtimeTable/constants/addingRowConfig.js
+++ b/web/src/components/RealtimeTable/constants/addingRowConfig.js
@@ -1,3 +1,7 @@
export const additionVspRowTable = {
FORM_2: ["AHR_SECURITY", "AHR_RENT", "AHR_UTILITY"],
};
+
+export const additionExpenseRowTable = {
+ FORM_4: ["AHR", "CAP", "OPER"],
+};
\ No newline at end of file
diff --git a/web/src/components/RealtimeTable/tableStyles.css b/web/src/components/RealtimeTable/tableStyles.css
deleted file mode 100644
index e69de29..0000000