2026-05-21 11:09:31 +03:00

378 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { createPortal } from 'react-dom';
import { TablesApi } from '../api/tables';
import {
TaskInfoContainer,
NameTask,
} from '../components/common/SwitchFormTask/SwitchFormTask.style';
import {
Box,
Button,
CircularProgress,
FormControl,
FormLabel,
TextField,
Typography,
} from '@mui/material';
import { Chip } from '../components/styles/StyledChip';
import { IconWithContent } from '../components/common/IconWithContent';
import { TableIcon } from '../components/common/icons/icons';
import Modal from '../components/common/Modal/Modal';
import { toast } from 'react-toastify';
import { FormsApi } from '../api/forms';
import SearchComponent from '../components/common/SearchComponent';
import { SettingModal as SettingStageModal } from '../components/Stages/SettingModal';
import { BackButton } from '../components/common/Buttons/BackButton';
import { CustomCheckbox } from '../components/common/StyledCheckbox';
import TableList from '../components/common/TableList/TableList';
const FormInfo = ({ form }) => {
const portalContent = (
<TaskInfoContainer>
<BackButton to="/forms" />
<NameTask>{form.title}</NameTask>
</TaskInfoContainer>
);
const targetElement = document.getElementById('TableInfo');
if (targetElement) {
return createPortal(portalContent, targetElement);
}
};
export default function FormPage() {
const { formId } = useParams();
const id = Number(formId);
const [form, setForm] = useState(null);
const [tables, setTables] = useState([]);
const [newTableName, setNewTableName] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [query, setQuery] = useState('');
const [modalOpen, setModalOpen] = useState(false);
const [newTableIsProject, setNewTableIsProject] = useState(false);
const [modalStageOpen, setModalStageOpen] = useState(false);
const [projects, setProjects] = useState([]);
useEffect(() => {
if (!formId) return;
const fetchProjects = async () => {
try {
const { success, result } = await FormsApi.getProjects(formId);
success ? setProjects(result) : toast.error('Ошибка получения проекта');
} catch {
toast.error('Ошибка получения проекта');
}
};
fetchProjects();
}, [formId]);
const handleClickCreate = () => {
setModalOpen(true);
};
const handleCancel = () => {
setModalOpen(false);
setNewTableName('');
};
const handleCreateTable = async () => {
const trimmedName = newTableName.trim();
if (!trimmedName) {
toast.error('Название не может быть пустым');
return;
}
try {
let result;
if (newTableIsProject) {
result = await createProjectTable(trimmedName);
} else {
result = await TablesApi.createTemp({
name: trimmedName,
form_id: id,
});
}
setTables((prevTables) => [...prevTables, result.result]);
setNewTableName('');
setModalOpen(false);
} catch (error) {
const errorMessage =
error.response?.data?.detail ||
error.message ||
'Не удалось создать таблицу';
toast.error(errorMessage);
}
};
const createProjectTable = async (tableName) => {
let project = projects[0] || null;
if (!project) {
const result = await createDefaultProject();
if (result && result.success) {
setProjects([result.result]);
project = result.result;
} else {
throw new Error('Не удалось создать проект');
}
}
return await FormsApi.createProjectTable(formId, project.id, {
name: tableName,
});
};
const createDefaultProject = async () => {
const defaultProjectData = {
name: 'Проектные таблицы',
// ToDo: надо уточнить что сюда вообще пишется
add_projects_data: {
'Тип проекта развития': {
type: 'multiselect',
options: [
'Открытие ВСП',
'Закрытие ВСП',
'Переезд ВСП',
'Реновация РФ',
'Открытие УРМ',
],
placeholder: '',
defaultValue: null,
},
'Название проекта': {
type: 'text',
placeholder: 'Введите название проекта',
defaultValue: '',
},
'Формат ВСП': {
type: 'multiselect',
options: [
'Фланговый',
'Типовой',
'Розничный',
'МСБ',
'Лёгкий',
'Мини',
'Розничный-киоск',
'МБО',
'Офис самообслуживания',
'Другое',
],
placeholder: '',
defaultValue: null,
},
'Адрес объекта': {
type: 'text',
placeholder: 'Введите адрес объекта',
defaultValue: '',
},
'Целевая численность, чел.': {
type: 'number',
placeholder: 'Введите число',
defaultValue: 0,
min: 0,
// max: 1000000000,
step: 1,
},
'Тип размещения': {
type: 'multiselect',
options: ['Собственность', 'Аренда', 'Субаренда'],
placeholder: '',
defaultValue: null,
},
'Площадь размещения, м2': {
type: 'number',
placeholder: 'Введите число',
defaultValue: 0,
min: 0,
// max: 1000000000,
step: 1,
},
},
};
return await FormsApi.createProjects(formId, defaultProjectData);
};
const loadFormTemplates = async () => {
setIsLoading(true);
try {
const data = await FormsApi.formTablesList(id, true);
setTables(data.result);
} catch (error) {
toast.error(error?.response?.data?.detail || 'Ошибка загрузки таблиц');
} finally {
setIsLoading(false);
}
};
const getFormInfo = async () => {
setIsLoading(true);
try {
const data = await FormsApi.getForm(id);
setForm(data.result);
} catch (error) {
toast.error(error?.response?.data?.detail || 'Ошибка загрузки таблиц');
} finally {
setIsLoading(false);
}
};
useEffect(() => {
if (Number.isFinite(id)) {
getFormInfo();
}
}, [id]);
useEffect(() => {
if (form) {
loadFormTemplates();
}
}, [form]);
// Фильтруем таблицы по query
const filteredTables = tables.filter((item) =>
item.name?.toLowerCase().includes(query.toLowerCase()),
);
if (isLoading) {
return (
<div className="flex justify-center pt-12">
<CircularProgress />
</div>
);
}
if (!form) {
return (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
paddingTop: '2.5rem'
}}
>
Эта форма не существует
</Box>
);
}
return (
<>
{form && <FormInfo form={form} />}
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
paddingTop: '2.5rem'
}}
>
<Box sx={{ display: 'flex', gap: '1rem', flexDirection: 'column', width: '50rem' }}>
<Box sx={{ display: 'flex', gap: '1rem' }}>
<span>Таблицы</span>
<Chip>
<IconWithContent icon={<TableIcon />}>
<span style={{ fontSize: '0.8rem' }}>{tables.length} шт.</span>
</IconWithContent>
</Chip>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<Box sx={{ display: 'flex', gap: '1rem' }}>
<SearchComponent
placeholder="Поиск по названию таблицы"
value={query}
onChange={setQuery}
/>
<Button variant="contained" onClick={handleClickCreate}>
Создать
</Button>
</Box>
<Box>
<Button
variant="outlined"
onClick={() => setModalStageOpen(true)}
>
<span>Этапы</span>
</Button>
<SettingStageModal
isOpen={modalStageOpen}
onClose={() => {
setModalStageOpen(false);
}}
formId={formId}
/>
</Box>
</Box>
<TableList
filteredTables={filteredTables}
basePath="/table-temp"
query={query}
projects={projects}
/>
</Box>
</Box>
<Modal
open={modalOpen}
onClose={handleCancel}
title="Создать таблицу"
actions={
<>
<Button
variant="grey"
onClick={handleCancel}
sx={{ height: '2.5rem' }}
>
Отменить
</Button>
<Button
variant="contained"
onClick={handleCreateTable}
sx={{ height: '2.5rem' }}
>
Создать
</Button>
</>
}
>
<FormControl fullWidth>
<FormLabel required>Название таблицы</FormLabel>
<TextField
size="small"
placeholder="Укажите название таблицы"
value={newTableName}
onChange={(e) => setNewTableName(e.target.value)}
/>
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: '0.75rem',
marginTop: '1rem'
}}
>
<CustomCheckbox
checked={newTableIsProject}
onChange={(e) => {
setNewTableIsProject(e.target.checked ? true : false);
}}
/>
<Box sx={{ fontSize: '1rem', color: '#1F1F1F' }}>
Проектная таблица
</Box>
</Box>
</FormControl>
</Modal>
</>
);
}