form-4-add-row #54

Merged
PotapovaA merged 6 commits from form-4-add-row into test 2026-07-29 10:56:41 +03:00
5 changed files with 209 additions and 5 deletions
Showing only changes of commit 73083153da - Show all commits

View File

@ -0,0 +1,7 @@
import api from "./client";
export const ExpenseItemApi = {
getAll(params) {
return api.get(`/expense-item/`, { params }).then((r) => r.data);
},
};

View File

@ -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 (
<ModalBackdrop isOpen={isOpen} onClick={handleBackdropClick}>
<ModalContainer height={'max-content'} >
<HeaderContainer>
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
<ModalTitle>{title}</ModalTitle>
</Stack>
<IconButton size="small" onClick={handleCancel}>
<Cancel />
</IconButton>
</HeaderContainer>
<Box>
<Divider sx={{ marginBottom: '0.75rem' }} />
{/* Выбор ВСП */}
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
<FormControl fullWidth>
<Autocomplete
size="small"
options={expenseItemOptions}
noOptionsText="Не найдено"
getOptionLabel={(option) => option.name || ''}
getOptionKey={(option) => option.id}
value={selectedValue}
onChange={(event, newValue) => {
setSelectedValue(newValue);
}}
slotProps={{
popper: {
style: { zIndex: 60 },
},
}}
renderInput={(params) => (
<TextField
{...params}
placeholder="Не выбрана"
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: 'rgba(0,0,0,0.1)',
},
},
}}
/>
)}
/>
</FormControl>
</Stack>
<Stack
direction="row"
spacing={0.75}
sx={{
justifyContent: 'flex-end',
marginTop: '1.5rem',
width: '100%',
}}
>
<Button
variant="outlined"
color="default"
onClick={handleCancel}
style={{ height: '2.5rem' }}
disabled={isSaving}
>
Отмена
</Button>
<Button
variant="contained"
onClick={handleSave}
style={{ height: '2.5rem' }}
disabled={!isFormValid || isSaving}
loading={isSaving}
>
Выбрать
</Button>
</Stack>
</Box>
</ModalContainer>
</ModalBackdrop>
);
};

View File

@ -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="Выбор ВСП"
/>
<SelectExpenseItemModal
isOpen={isOpenModalSelectExpenseItem}
onClose={() => setIsOpenModalSelectExpenseItem(false)}
formId={formId}
onSelect={handleAddExpenseItemRow}
title="Добавление строки"
sheet={sheetName}
/>
</>
);
};

View File

@ -1,3 +1,7 @@
export const additionVspRowTable = {
FORM_2: ["AHR_SECURITY", "AHR_RENT", "AHR_UTILITY"],
};
export const additionExpenseRowTable = {
FORM_4: ["AHR", "CAP", "OPER"],
};