добавление строк (не готово)
This commit is contained in:
parent
28ce0c1511
commit
73083153da
7
web/src/api/expense-item.js
Normal file
7
web/src/api/expense-item.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import api from "./client";
|
||||||
|
|
||||||
|
export const ExpenseItemApi = {
|
||||||
|
getAll(params) {
|
||||||
|
return api.get(`/expense-item/`, { params }).then((r) => r.data);
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -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>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,4 +1,3 @@
|
|||||||
// components/RealtimeTable/index.js
|
|
||||||
import React, { useState, useMemo, useRef, useEffect, useCallback, useTransition } from 'react';
|
import React, { useState, useMemo, useRef, useEffect, useCallback, useTransition } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import {
|
import {
|
||||||
@ -25,9 +24,11 @@ import {
|
|||||||
import { useRealtime } from './contexts/RealtimeContext';
|
import { useRealtime } from './contexts/RealtimeContext';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { CircularProgress } from '@mui/material';
|
import { CircularProgress } from '@mui/material';
|
||||||
import { additionVspRowTable } from './constants/addingRowConfig';
|
import { additionExpenseRowTable, additionVspRowTable } from './constants/addingRowConfig';
|
||||||
import { SelectVspModal } from './Modals/SelectVspModal';
|
import { SelectVspModal } from './Modals/SelectVspModal';
|
||||||
|
import { SelectExpenseItemModal } from './Modals/SelectExpenseItemModal';
|
||||||
import { getRowId } from './utils/rowUtils';
|
import { getRowId } from './utils/rowUtils';
|
||||||
|
import { FORM_TYPE_OPTIONS } from '../../constants/constants';
|
||||||
|
|
||||||
const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
||||||
const { data, setData, isLoading: isTableLoading, editingCells: dataEditingCells } = useRealtimeData(formId, sheetName, direction, formType, 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 [editingCell, setEditingCell] = useState(null);
|
||||||
|
|
||||||
const [isOpenModalSelectVsp, setIsOpenModalSelectVsp] = useState(false);
|
const [isOpenModalSelectVsp, setIsOpenModalSelectVsp] = useState(false);
|
||||||
|
const [isOpenModalSelectExpenseItem, setIsOpenModalSelectExpenseItem] = useState(false);
|
||||||
|
|
||||||
const isVspAdditionRow = useMemo(() => {
|
const isVspAdditionRow = useMemo(() => {
|
||||||
if (!formType || !sheetName) return false;
|
if (!formType || !sheetName) return false;
|
||||||
@ -47,6 +49,12 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
|||||||
return additionVspRowTable[formType].includes(sheetName);
|
return additionVspRowTable[formType].includes(sheetName);
|
||||||
}, [formType, 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) => {
|
const handleGlobalFilterChange = (value) => {
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
setGlobalFilter(value);
|
setGlobalFilter(value);
|
||||||
@ -359,11 +367,19 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
|||||||
|
|
||||||
const handleAddVspRow = useCallback((vsp_id) => {
|
const handleAddVspRow = useCallback((vsp_id) => {
|
||||||
contextAddRow({ vsp_id: vsp_id });
|
contextAddRow({ vsp_id: vsp_id });
|
||||||
}, [rowSelection, table]);
|
}, []);
|
||||||
|
|
||||||
|
const handleAddExpenseItemRow = useCallback((expense_item) => {
|
||||||
|
contextAddRow({ expense_item_id: expense_item.id });
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleOpenModalSelectVsp = useCallback(() => {
|
const handleOpenModalSelectVsp = useCallback(() => {
|
||||||
setIsOpenModalSelectVsp(true);
|
setIsOpenModalSelectVsp(true);
|
||||||
}, [rowSelection, table])
|
}, [])
|
||||||
|
|
||||||
|
const handleOpenModalSelectExpenseItem = useCallback(() => {
|
||||||
|
setIsOpenModalSelectExpenseItem(true);
|
||||||
|
}, [])
|
||||||
|
|
||||||
const handleDeleteRow = useCallback(() => {
|
const handleDeleteRow = useCallback(() => {
|
||||||
const allRows = table.getRowModel().rows;
|
const allRows = table.getRowModel().rows;
|
||||||
@ -379,6 +395,17 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
|||||||
setRowSelection({});
|
setRowSelection({});
|
||||||
}, [rowSelection, table])
|
}, [rowSelection, table])
|
||||||
|
|
||||||
|
const addRow = useCallback(() => {
|
||||||
|
|
||||||
|
if (isVspAdditionRow) {
|
||||||
|
return handleOpenModalSelectVsp();
|
||||||
|
}
|
||||||
|
if (isAdditionExpenseItem) {
|
||||||
|
return handleOpenModalSelectExpenseItem();
|
||||||
|
}
|
||||||
|
return handleAddRow();
|
||||||
|
}, [isVspAdditionRow, isAdditionExpenseItem, handleOpenModalSelectVsp, handleAddRow]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
setData([]);
|
setData([]);
|
||||||
@ -405,7 +432,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
|||||||
onGlobalFilterChange={handleGlobalFilterChange}
|
onGlobalFilterChange={handleGlobalFilterChange}
|
||||||
sizeMult={sizeMult}
|
sizeMult={sizeMult}
|
||||||
onChangeShowColumnFilters={setShowColumnFilters}
|
onChangeShowColumnFilters={setShowColumnFilters}
|
||||||
onAddRow={isVspAdditionRow ? handleOpenModalSelectVsp : handleAddRow}
|
onAddRow={addRow}
|
||||||
onDeleteRow={handleDeleteRow}
|
onDeleteRow={handleDeleteRow}
|
||||||
isLoadingData={isLoadingData}
|
isLoadingData={isLoadingData}
|
||||||
formId={formId}
|
formId={formId}
|
||||||
@ -475,6 +502,14 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
|||||||
onSelect={handleAddVspRow}
|
onSelect={handleAddVspRow}
|
||||||
title="Выбор ВСП"
|
title="Выбор ВСП"
|
||||||
/>
|
/>
|
||||||
|
<SelectExpenseItemModal
|
||||||
|
isOpen={isOpenModalSelectExpenseItem}
|
||||||
|
onClose={() => setIsOpenModalSelectExpenseItem(false)}
|
||||||
|
formId={formId}
|
||||||
|
onSelect={handleAddExpenseItemRow}
|
||||||
|
title="Добавление строки"
|
||||||
|
sheet={sheetName}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
export const additionVspRowTable = {
|
export const additionVspRowTable = {
|
||||||
FORM_2: ["AHR_SECURITY", "AHR_RENT", "AHR_UTILITY"],
|
FORM_2: ["AHR_SECURITY", "AHR_RENT", "AHR_UTILITY"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const additionExpenseRowTable = {
|
||||||
|
FORM_4: ["AHR", "CAP", "OPER"],
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user