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