stage project #102
@ -27,6 +27,24 @@ export const StagesApi = {
|
|||||||
getStages(formId) {
|
getStages(formId) {
|
||||||
return api.get(`/stages/form/${formId}`).then((r) => r.data);
|
return api.get(`/stages/form/${formId}`).then((r) => r.data);
|
||||||
},
|
},
|
||||||
|
getProjectStages(projectId, year, reportType) {
|
||||||
|
return api
|
||||||
|
.get(`/stages/project/${projectId}`, { params: { year, report_type: reportType } })
|
||||||
|
.then((r) => r.data);
|
||||||
|
},
|
||||||
|
createProjectStage(projectId, payload) {
|
||||||
|
return api.post(`/stages/project/${projectId}`, payload).then((r) => r.data);
|
||||||
|
},
|
||||||
|
updateProjectStage(projectId, year, reportType, phaseCode, payload) {
|
||||||
|
return api
|
||||||
|
.patch(`/stages/project/${projectId}/${year}/${reportType}/${encodeURIComponent(phaseCode)}`, payload)
|
||||||
|
.then((r) => r.data);
|
||||||
|
},
|
||||||
|
deleteProjectStage(projectId, year, reportType, phaseCode) {
|
||||||
|
return api
|
||||||
|
.delete(`/stages/project/${projectId}/${year}/${reportType}/${encodeURIComponent(phaseCode)}`)
|
||||||
|
.then((r) => r.data);
|
||||||
|
},
|
||||||
createStageAccessHeader(tableId, stageId, payload) {
|
createStageAccessHeader(tableId, stageId, payload) {
|
||||||
return api
|
return api
|
||||||
.post(
|
.post(
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import { StageStatusChip } from './StageStatusChip';
|
|||||||
import { getStageStatus, getStatusColors } from './StagesTable/utils';
|
import { getStageStatus, getStatusColors } from './StagesTable/utils';
|
||||||
import { stageColumnsHiddenFromPicker } from './constants';
|
import { stageColumnsHiddenFromPicker } from './constants';
|
||||||
|
|
||||||
|
const stageSelectMenuProps = { sx: { zIndex: 70 } };
|
||||||
|
|
||||||
export const AddStagesModal = ({
|
export const AddStagesModal = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
@ -184,7 +186,12 @@ export const AddStagesModal = ({
|
|||||||
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
|
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
<FormLabel>Выбор листа</FormLabel>
|
<FormLabel>Выбор листа</FormLabel>
|
||||||
<Select value={selectedSheet} onChange={handleSheetChange} displayEmpty size='small'>
|
<Select
|
||||||
|
value={selectedSheet}
|
||||||
|
onChange={handleSheetChange}
|
||||||
|
displayEmpty
|
||||||
|
size='small'
|
||||||
|
MenuProps={stageSelectMenuProps}>
|
||||||
<MenuItem value='' disabled>
|
<MenuItem value='' disabled>
|
||||||
Выберите лист
|
Выберите лист
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -207,6 +214,7 @@ export const AddStagesModal = ({
|
|||||||
onChange={(e) => setSelectedDirection(e.target.value)}
|
onChange={(e) => setSelectedDirection(e.target.value)}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
size='small'
|
size='small'
|
||||||
|
MenuProps={stageSelectMenuProps}
|
||||||
>
|
>
|
||||||
<MenuItem value='' disabled>
|
<MenuItem value='' disabled>
|
||||||
Выберите направление
|
Выберите направление
|
||||||
@ -242,7 +250,12 @@ export const AddStagesModal = ({
|
|||||||
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
|
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
<FormLabel>Роль</FormLabel>
|
<FormLabel>Роль</FormLabel>
|
||||||
<Select value={selectedRole ?? ''} onChange={(e) => setSelectedRole(e.target.value)} displayEmpty size='small'>
|
<Select
|
||||||
|
value={selectedRole ?? ''}
|
||||||
|
onChange={(e) => setSelectedRole(e.target.value)}
|
||||||
|
displayEmpty
|
||||||
|
size='small'
|
||||||
|
MenuProps={stageSelectMenuProps}>
|
||||||
{Object.entries(STAGE_ROLE_RUSSIAN_NAME).map(([key, label]) => (
|
{Object.entries(STAGE_ROLE_RUSSIAN_NAME).map(([key, label]) => (
|
||||||
<MenuItem key={key} value={key}>
|
<MenuItem key={key} value={key}>
|
||||||
{label}
|
{label}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import CloseIcon from '@mui/icons-material/Close';
|
import { Box, CircularProgress, Stack } from '@mui/material';
|
||||||
import { Box, CircularProgress, IconButton, Stack, Typography } from '@mui/material';
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useTaskStages } from '../../hooks/useTaskStages';
|
import { useTaskStages } from '../../hooks/useTaskStages';
|
||||||
|
import { useProjectStages } from '../../hooks/useProjectStages';
|
||||||
|
import { SHEET_NAME } from '../../constants/constants';
|
||||||
import { PrimaryButton } from '../common/Buttons/Buttons';
|
import { PrimaryButton } from '../common/Buttons/Buttons';
|
||||||
import { ModalSetting } from '../common/Modal/ModalSetting';
|
import Modal from '../common/Modal/Modal';
|
||||||
import { EditContainer, ModalContainer, ModalContent } from '../common/Modal/ModalStyled';
|
import { EditContainer } from '../common/Modal/ModalStyled';
|
||||||
import { WhitePlus } from '../common/icons/icons';
|
import { WhitePlus } from '../common/icons/icons';
|
||||||
import { AddStagesModal } from './AddStagesModal';
|
import { AddStagesModal } from './AddStagesModal';
|
||||||
import { DeleteStageModal } from './DeleteStageModal';
|
import { DeleteStageModal } from './DeleteStageModal';
|
||||||
@ -15,16 +16,25 @@ export const SettingModal = ({
|
|||||||
onClose,
|
onClose,
|
||||||
formId,
|
formId,
|
||||||
taskId,
|
taskId,
|
||||||
|
projectId,
|
||||||
|
year,
|
||||||
|
reportType,
|
||||||
mode = 'form', // 'form' | 'task'
|
mode = 'form', // 'form' | 'task'
|
||||||
formTypeCode = '',
|
formTypeCode = '',
|
||||||
sheets,
|
sheets,
|
||||||
}) => {
|
}) => {
|
||||||
const taskStages = useTaskStages(taskId);
|
const taskStages = useTaskStages(taskId);
|
||||||
|
const projectStages = useProjectStages(projectId, year, reportType);
|
||||||
|
const stages = mode === 'project' ? projectStages : taskStages;
|
||||||
|
|
||||||
const { deleteStage, stagesInfo, getStages, createStage, updateStage, isSaving } = taskStages;
|
const { deleteStage, stagesInfo, getStages, createStage, updateStage, isSaving } = stages;
|
||||||
|
|
||||||
const isTaskMode = mode === 'task';
|
const isTaskMode = mode === 'task';
|
||||||
const entityId = taskId;
|
const entityId = mode === 'project' ? projectId : taskId;
|
||||||
|
const projectSheetTitle = SHEET_NAME[reportType] || reportType;
|
||||||
|
const modalTitle = mode === 'project' && reportType
|
||||||
|
? `Этапы — ${projectSheetTitle}${year ? `, ${year} год` : ''}`
|
||||||
|
: 'Этапы';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen && entityId) {
|
if (isOpen && entityId) {
|
||||||
@ -125,71 +135,57 @@ export const SettingModal = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ModalSetting
|
<Modal open={isOpen} onClose={onClose} title={modalTitle} customSize={50}>
|
||||||
isOpen={isOpen}
|
<EditContainer style={{ margin: 0 }}>
|
||||||
onClose={onClose}
|
<Stack direction='row' sx={{ width: '100%', justifyContent: 'flex-end' }}>
|
||||||
children={
|
<PrimaryButton onClick={handleAddStage} startIcon={<WhitePlus />}>
|
||||||
<ModalContainer>
|
Добавить этап
|
||||||
<ModalContent>
|
</PrimaryButton>
|
||||||
<Stack direction='row' sx={{ width: '100%', justifyContent: 'flex-end' }}>
|
</Stack>
|
||||||
<IconButton size='small' onClick={onClose}>
|
|
||||||
<CloseIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<EditContainer>
|
{stagesInfo.isLoading ? (
|
||||||
<Stack direction='row' sx={{ width: '100%', justifyContent: 'space-between' }}>
|
<Box
|
||||||
<Typography sx={{ fontWeight: 'bold' }}>Этапы</Typography>
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
<PrimaryButton onClick={handleAddStage} startIcon={<WhitePlus />}>
|
justifyContent: 'center',
|
||||||
Добавить этап
|
py: 4,
|
||||||
</PrimaryButton>
|
}}>
|
||||||
</Stack>
|
<CircularProgress />
|
||||||
|
</Box>
|
||||||
{stagesInfo.isLoading ? (
|
) : (
|
||||||
<Box
|
<StagesTable
|
||||||
sx={{
|
stages={stagesInfo.stages || []}
|
||||||
display: 'flex',
|
onEdit={handleEditStage}
|
||||||
justifyContent: 'center',
|
onDelete={!isTaskMode ? handleDeleteStage : undefined}
|
||||||
py: 4,
|
/>
|
||||||
}}>
|
)}
|
||||||
<CircularProgress />
|
<AddStagesModal
|
||||||
</Box>
|
isOpen={isAddEditModalOpen}
|
||||||
) : (
|
onClose={() => {
|
||||||
<StagesTable
|
setIsAddEditModalOpen(false);
|
||||||
stages={stagesInfo.stages || []}
|
}}
|
||||||
onEdit={handleEditStage}
|
stage={stageForEdit}
|
||||||
onDelete={!isTaskMode ? handleDeleteStage : undefined}
|
createStage={createStage}
|
||||||
/>
|
updateStage={updateStage}
|
||||||
)}
|
isTaskMode={isTaskMode}
|
||||||
<AddStagesModal
|
isSaving={isSaving}
|
||||||
isOpen={isAddEditModalOpen}
|
sheetOptions={sheetOptions}
|
||||||
onClose={() => {
|
formType={formTypeCode}
|
||||||
setIsAddEditModalOpen(false);
|
defaultSheet={mode === 'project' ? reportType : ''}
|
||||||
}}
|
/>
|
||||||
stage={stageForEdit}
|
{!isTaskMode && (
|
||||||
createStage={createStage}
|
<DeleteStageModal
|
||||||
updateStage={updateStage}
|
isOpen={isDeleteModalOpen}
|
||||||
isTaskMode={isTaskMode}
|
onClose={() => {
|
||||||
isSaving={isSaving}
|
setIsDeleteModalOpen(false);
|
||||||
sheetOptions={sheetOptions}
|
setStageToDelete(null);
|
||||||
formType={formTypeCode}
|
}}
|
||||||
/>
|
onConfirm={handleConfirmDelete}
|
||||||
{!isTaskMode && (
|
stage={stageToDelete}
|
||||||
<DeleteStageModal
|
/>
|
||||||
isOpen={isDeleteModalOpen}
|
)}
|
||||||
onClose={() => {
|
</EditContainer>
|
||||||
setIsDeleteModalOpen(false);
|
</Modal>
|
||||||
setStageToDelete(null);
|
|
||||||
}}
|
|
||||||
onConfirm={handleConfirmDelete}
|
|
||||||
stage={stageToDelete}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</EditContainer>
|
|
||||||
</ModalContent>
|
|
||||||
</ModalContainer>
|
|
||||||
}></ModalSetting>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -103,6 +103,7 @@ export const StagesTable = ({ stages, onEdit, onDelete }) => {
|
|||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
open={Boolean(anchorEl)}
|
open={Boolean(anchorEl)}
|
||||||
onClose={handleCloseMenu}
|
onClose={handleCloseMenu}
|
||||||
|
sx={{ zIndex: 60 }}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: 'bottom',
|
vertical: 'bottom',
|
||||||
horizontal: 'right',
|
horizontal: 'right',
|
||||||
|
|||||||
@ -198,6 +198,7 @@ const CollapsibleTree = ({
|
|||||||
open={open}
|
open={open}
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
|
sx={forStage ? { zIndex: 70 } : undefined}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: 'bottom',
|
vertical: 'bottom',
|
||||||
horizontal: 'left',
|
horizontal: 'left',
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { DIRECTION_TRANSLATE } from '../../../constants/constants';
|
import { DIRECTION_TRANSLATE } from '../../../constants/constants';
|
||||||
import { Right, Section, SectionStartPart, SectionTitle } from './TableCard.styled';
|
import { Right, Section, SectionStartPart, SectionTitle } from './TableCard.styled';
|
||||||
|
|
||||||
const TableCard = ({ table, onNavigate }) => {
|
const TableCard = ({ table, onNavigate, action }) => {
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (onNavigate) {
|
if (onNavigate) {
|
||||||
onNavigate(table.id);
|
onNavigate(table.id);
|
||||||
@ -23,7 +23,7 @@ const TableCard = ({ table, onNavigate }) => {
|
|||||||
</UsersList> */}
|
</UsersList> */}
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
</SectionStartPart>
|
</SectionStartPart>
|
||||||
<Right />
|
<div onClick={(event) => event.stopPropagation()}>{action || <Right />}</div>
|
||||||
</Section>
|
</Section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Box, Typography } from '@mui/material';
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import TableCard from '../TableCard/TableCard';
|
import TableCard from '../TableCard/TableCard';
|
||||||
|
|
||||||
const TablesList = ({ filteredTables, query, basePath = '/table', formInfo, isProject = false }) => {
|
const TablesList = ({ filteredTables, query, basePath = '/table', formInfo, isProject = false, renderTableAction }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleNavigate = (path) => {
|
const handleNavigate = (path) => {
|
||||||
@ -16,7 +16,14 @@ const TablesList = ({ filteredTables, query, basePath = '/table', formInfo, isPr
|
|||||||
}
|
}
|
||||||
const path = `${basePath}/form/${formInfo.id}/form-type/${isProject ? 'PROJECT' : formInfo.form_type_code}/${table.sheet}/${table?.direction}/${table?.year}`;
|
const path = `${basePath}/form/${formInfo.id}/form-type/${isProject ? 'PROJECT' : formInfo.form_type_code}/${table.sheet}/${table?.direction}/${table?.year}`;
|
||||||
|
|
||||||
return <TableCard key={`${table.sheet}_${table?.direction}_${table?.year}`} onNavigate={() => handleNavigate(path)} table={table} />;
|
return (
|
||||||
|
<TableCard
|
||||||
|
key={`${table.sheet}_${table?.direction}_${table?.year}`}
|
||||||
|
onNavigate={() => handleNavigate(path)}
|
||||||
|
table={table}
|
||||||
|
action={renderTableAction?.(table)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const projectTablesByYear = isProject
|
const projectTablesByYear = isProject
|
||||||
|
|||||||
@ -60,4 +60,6 @@ export const SHEET_NAME = {
|
|||||||
OTCH9F: 'Отчет 9ф',
|
OTCH9F: 'Отчет 9ф',
|
||||||
SMETA: 'Смета',
|
SMETA: 'Смета',
|
||||||
STRUCTURE: 'Структура',
|
STRUCTURE: 'Структура',
|
||||||
|
CURRENT_EXPENSES: 'Текущие расходы',
|
||||||
|
LIMIT: 'Лимиты',
|
||||||
};
|
};
|
||||||
|
|||||||
94
web/src/hooks/useProjectStages.js
Normal file
94
web/src/hooks/useProjectStages.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
import { StagesApi } from '../api/stages';
|
||||||
|
|
||||||
|
export const useProjectStages = (projectId, year, reportType) => {
|
||||||
|
const [stagesInfo, setStagesInfo] = useState({ isLoading: false, stages: [] });
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
|
||||||
|
const normalizeStage = useCallback(
|
||||||
|
(stage) => ({ ...stage, sheet: stage.report_type || reportType, year: stage.year || year }),
|
||||||
|
[reportType, year],
|
||||||
|
);
|
||||||
|
|
||||||
|
const getStages = useCallback(() => {
|
||||||
|
if (!projectId || !year || !reportType) return;
|
||||||
|
setStagesInfo((prev) => ({ ...prev, isLoading: true }));
|
||||||
|
|
||||||
|
StagesApi.getProjectStages(projectId, year, reportType)
|
||||||
|
.then((data) => {
|
||||||
|
setStagesInfo({ stages: (data.result ?? []).map(normalizeStage), isLoading: false });
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setStagesInfo((prev) => ({ ...prev, isLoading: false }));
|
||||||
|
toast.error(error?.response?.data?.detail || 'Ошибка при получении этапов');
|
||||||
|
});
|
||||||
|
}, [normalizeStage, projectId, reportType, year]);
|
||||||
|
|
||||||
|
const createStage = useCallback(
|
||||||
|
(payload) => {
|
||||||
|
if (!projectId || !year || !reportType) return Promise.reject('Не задан контекст отчёта проекта');
|
||||||
|
const { sheet, direction, ...stageData } = payload;
|
||||||
|
setIsSaving(true);
|
||||||
|
return StagesApi.createProjectStage(projectId, { ...stageData, year, report_type: reportType })
|
||||||
|
.then((data) => {
|
||||||
|
setStagesInfo((prev) => ({ ...prev, stages: [...prev.stages, normalizeStage(data.result)] }));
|
||||||
|
toast.success('Этап добавлен');
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
toast.error(error?.response?.data?.detail || 'Ошибка добавления этапа');
|
||||||
|
throw error;
|
||||||
|
})
|
||||||
|
.finally(() => setIsSaving(false));
|
||||||
|
},
|
||||||
|
[normalizeStage, projectId, reportType, year],
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateStage = useCallback(
|
||||||
|
(stage) => {
|
||||||
|
if (!projectId || !year || !reportType) return Promise.reject('Не задан контекст отчёта проекта');
|
||||||
|
const { phase_code, role, column_keys, opens_at, closes_at } = stage;
|
||||||
|
setIsSaving(true);
|
||||||
|
return StagesApi.updateProjectStage(projectId, year, reportType, phase_code, {
|
||||||
|
role,
|
||||||
|
column_keys,
|
||||||
|
opens_at,
|
||||||
|
closes_at,
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
const updatedStage = normalizeStage(data.result);
|
||||||
|
setStagesInfo((prev) => ({
|
||||||
|
...prev,
|
||||||
|
stages: prev.stages.map((item) => (item.phase_code === phase_code ? updatedStage : item)),
|
||||||
|
}));
|
||||||
|
toast.success('Данные об этапе обновлены');
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
toast.error(error?.response?.data?.detail || 'Ошибка при обновлении этапа');
|
||||||
|
throw error;
|
||||||
|
})
|
||||||
|
.finally(() => setIsSaving(false));
|
||||||
|
},
|
||||||
|
[normalizeStage, projectId, reportType, year],
|
||||||
|
);
|
||||||
|
|
||||||
|
const deleteStage = useCallback(
|
||||||
|
(stage) => {
|
||||||
|
if (!projectId || !year || !reportType || !stage?.phase_code) return;
|
||||||
|
StagesApi.deleteProjectStage(projectId, year, reportType, stage.phase_code)
|
||||||
|
.then(() => {
|
||||||
|
setStagesInfo((prev) => ({
|
||||||
|
...prev,
|
||||||
|
stages: prev.stages.filter((item) => item.phase_code !== stage.phase_code),
|
||||||
|
}));
|
||||||
|
toast.success('Этап успешно удален');
|
||||||
|
})
|
||||||
|
.catch((error) => toast.error(error?.response?.data?.detail || 'Ошибка при удалении этапа'));
|
||||||
|
},
|
||||||
|
[projectId, reportType, year],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { stagesInfo, getStages, createStage, updateStage, deleteStage, isSaving };
|
||||||
|
};
|
||||||
@ -46,7 +46,7 @@ export default function TaskPage() {
|
|||||||
const [tables, setTables] = useState([]);
|
const [tables, setTables] = useState([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [modalStageOpen, setModalStageOpen] = useState(false);
|
const [stageReport, setStageReport] = useState(null);
|
||||||
const [modalProjectOpen, setModalProjectOpen] = useState(false);
|
const [modalProjectOpen, setModalProjectOpen] = useState(false);
|
||||||
const [tempProjects, setTempProjects] = useState([]);
|
const [tempProjects, setTempProjects] = useState([]);
|
||||||
const [projects, setProjects] = useState([]);
|
const [projects, setProjects] = useState([]);
|
||||||
@ -176,9 +176,11 @@ export default function TaskPage() {
|
|||||||
<SearchComponent placeholder='Поиск по названию или направлению' value={query} onChange={setQuery} />
|
<SearchComponent placeholder='Поиск по названию или направлению' value={query} onChange={setQuery} />
|
||||||
<Stack sx={{ flexDirection: 'row', spacing: '.5rem', justifyContent: 'end', gap: '.5rem' }}>
|
<Stack sx={{ flexDirection: 'row', spacing: '.5rem', justifyContent: 'end', gap: '.5rem' }}>
|
||||||
<ExportWithTextButton onClick={handleExport} />
|
<ExportWithTextButton onClick={handleExport} />
|
||||||
<PrimaryOutlinedButton variant='outlined' onClick={() => setModalStageOpen(true)}>
|
{!isProject && (
|
||||||
<span>Этапы</span>
|
<PrimaryOutlinedButton variant='outlined' onClick={() => setStageReport({})}>
|
||||||
</PrimaryOutlinedButton>
|
<span>Этапы</span>
|
||||||
|
</PrimaryOutlinedButton>
|
||||||
|
)}
|
||||||
{isProject && (
|
{isProject && (
|
||||||
<PrimaryButton onClick={() => setAddYearModalOpen(true)}>
|
<PrimaryButton onClick={() => setAddYearModalOpen(true)}>
|
||||||
Добавить год
|
Добавить год
|
||||||
@ -186,13 +188,15 @@ export default function TaskPage() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<SettingStageModal
|
<SettingStageModal
|
||||||
isOpen={modalStageOpen}
|
isOpen={stageReport !== null}
|
||||||
onClose={() => setModalStageOpen(false)}
|
onClose={() => setStageReport(null)}
|
||||||
taskId={isProject ? undefined : taskId}
|
taskId={isProject ? undefined : taskId}
|
||||||
projectId={isProject ? projectId : undefined}
|
projectId={isProject ? projectId : undefined}
|
||||||
|
year={stageReport?.year}
|
||||||
|
reportType={stageReport?.sheet}
|
||||||
mode={isProject ? 'project' : 'task'}
|
mode={isProject ? 'project' : 'task'}
|
||||||
formTypeCode={task?.form_type_code || ''}
|
formTypeCode={isProject ? 'PROJECT' : task?.form_type_code || ''}
|
||||||
sheets={tables}
|
sheets={isProject && stageReport ? [stageReport] : tables}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
@ -204,6 +208,15 @@ export default function TaskPage() {
|
|||||||
basePath={'/table'}
|
basePath={'/table'}
|
||||||
formInfo={task}
|
formInfo={task}
|
||||||
isProject={isProject}
|
isProject={isProject}
|
||||||
|
renderTableAction={
|
||||||
|
isProject
|
||||||
|
? (table) => (
|
||||||
|
<PrimaryOutlinedButton variant='outlined' onClick={() => setStageReport(table)}>
|
||||||
|
Этапы
|
||||||
|
</PrimaryOutlinedButton>
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user