File "ProjectPage.tsx"
Full Path: /var/www/html/gitep_front/src/pages/ProjectPage/ProjectPage.tsx
File size: 33.2 KB
MIME-type: text/x-java
Charset: utf-8
import TableComponent from "@/shared/ui/TableComponent/TableComponent";
import {Button, Checkbox, Flex, notification, Tag, Typography, Modal, Tooltip} from "antd";
import { TableRowSelection } from "antd/es/table/interface";
import React, { useEffect, useMemo, useState, useRef } from "react";
import { useMediaQuery } from "react-responsive";
import styles from './project.module.scss';
import { HeaderProject } from "./header/Header";
import { SortableBlock } from "./SortableBlock/SortableBlock";
import { useUnit } from "effector-react";
import ArrowShow from "@shared/assets/images/icons/arrow-show.svg?react";
import ArrowShowRight from "@shared/assets/images/icons/arrow-show-right.svg?react";
import { TotalBlock } from "./TotalBlock/TotalBlock";
import { DrawerComponent } from "@/shared/ui/DrawerComponent/DrawerComponent";
import { AddGroupContent } from "./addGroup/AddGroupContent";
import { AddProjectContent } from "./addProject/AddProjectContent";
import { GroupReadDrawer } from "./groupReadDrawer/groupReadDrawer";
import { createGroup } from "@/entities/payment-card/api/createGroup";
import { getGroupList } from "@/entities/payment-card/api/getGroupList";
import { createProject } from "@/entities/payment-card/api/createProject";
import { ProjectReadDrawer } from "./projectReadDrawer/ProjectReadDrawer";
import { getProjectItem } from "@/entities/project/api/getProjectItem";
import { getGroupProject } from "@/entities/project/api/getGroupProject";
import { updateProject } from "@/entities/payment-card/api/updateProject";
import { updateGroup } from "@/entities/payment-card/api/updateGroup";
import { postExcelFile } from "@/entities/project/api/postExcelFile";
import { $projectItemStore } from "@/entities/project/model";
import { useStore } from "effector-react";
import { $roleStore, $permissionStore } from "@features/roles/store/stores"
import isEqual from 'lodash.isequal';
import { Helmet } from "react-helmet";
import { formatWholeSum } from '@/shared/lib';
const getAllChildKeys = (data: any[], key: string): React.Key[] => {
const group = data.find(item => item.key === key);
return group?.children?.map((child: any) => child.key) || [];
};
const defaultProjectData = {
offer_number: '',
object_address: '',
short_description: '',
description: '',
project_group_id: '',
project_limits: 1222,
status: 'active'
}
const defaultGroupData = {
name: '',
description: '',
projects: []
}
interface IStats {
in_work: number
income: number
outcome: number
}
export const ProjectPage = () => {
const tableToBig = useMediaQuery({ query: '(min-width: 769px)' })
const projectDataItem = useUnit($projectItemStore);
const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
const [expandedRowKeys, setExpandedRowKeys] = useState<React.Key[]>([]);
const [sortField, setSortField] = useState<string>('name');
const [sortDirection, setSortDirection] = useState<'ASC' | 'DESC'>('ASC');
const [currentTab, setCurrentTab] = useState('current')
const [isRowDrawerOpen, setIsRowDrawerOpen] = useState(false);
const [openChildRow, setOpenChildRow] = useState(false);
const [isAddProject, setIsAddProject] = useState(false)
const [isAddGroup, setIsAddGroup] = useState(false)
const [recordData, setRecordData]: any = useState(null)
const [projectItemData, setProjectItemData]: any = useState(null)
const [groupItemData, setGroupItemData]: any = useState(null)
const [projects, setProjects] = useState([])
const [stats, setStats] = useState<IStats>({in_work: 0, income: 0, outcome: 0})
const [search, setSearch] = useState('')
const [isEditDrawer, setIsEditDrawer] = useState(false)
const[IsEditablebyRole, setIsEditableByRole] = useState(true);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isModalProjectOpen, setIsModalProjectOpen] = useState(false);
const [initialGroupData, setInitialGroupData] = useState(defaultGroupData);
const [initialProjectData, setInitialProjectData] = useState(defaultProjectData);
const roleStore = useUnit($roleStore).role;
const transformedData = useMemo(() => {
return projects?.map((group: any, groupIndex) => ({
key: group.id ? `group_${group.id}` : `ungrouped_${groupIndex}`,
id: group.id ? group.id : '',
supplier: group.name,
totalAmountPayments: group.total_payments?.total_amount_payment,
inProcess: group.total_payments?.in_process,
isGroup: true,
total_amounts: {
total_credit: group.total_amounts.total_credit,
total_debit: group.total_amounts.total_debit,
},
total_limits: {
credit: group.total_limits.credit,
debit: group.total_limits.debit,
},
subtitle: group.description || '',
children: group.projects.map((project: any, projectIndex: number) => ({
key: project.id ? `${project.id}` : '',
supplier: project.offer_number,
totalAmountPayments: project?.project_payments?.total_amount_payment,
inProcess: project?.project_payments?.in_process,
isGroup: false,
total_amounts: {
total_credit: project.project_amounts.credit,
total_debit: project.project_amounts.debit,
},
total_limits: {
credit: project.project_limits.credit,
debit: project.project_limits.debit,
},
payments: 0,
...project,
})),
}));
}, [projects]);
const prevTransformedRef = React.useRef<any[]>([]);
useEffect(() => {
if (!search) {
prevTransformedRef.current = transformedData;
return;
}
if (expandedRowKeys.length > 0) return;
if (isEqual(prevTransformedRef.current, transformedData)) {
prevTransformedRef.current = transformedData;
return;
}
const defaultGroupKeys = transformedData
.filter((g: any) => g.isGroup)
.map((g: any) => g.key);
if (defaultGroupKeys.length > 0) {
setExpandedRowKeys(defaultGroupKeys as React.Key[]);
}
prevTransformedRef.current = transformedData;
}, [search, transformedData, expandedRowKeys]);
const [groupData, setGroupData]: any = useState({
name: '',
description: '',
projects: [],
})
const [projectData, setProjectData] = useState({
offer_number: '',
object_address: '',
short_description: '',
description: '',
project_group_id: '',
project_limits: 1222,
status: 'active'
})
const [projectId, setProjectId] = useState(null)
const [groupId, setGroupId] = useState(null)
const getProject = async() => {
const { data }: any = await getGroupList({
search: search,
sort: sortField,
sort_direction: sortDirection,
type: currentTab
})
const ungroupedProjects = data.data.projects_without_groups || [];
const ungroupedTotals = ungroupedProjects.reduce(
(acc: any, project: any) => {
acc.credit += parseFloat(project.project_limits.credit) || 0;
acc.debit += parseFloat(project.project_limits.debit) || 0;
acc.total_credit += project.project_amounts.credit || 0;
acc.total_debit += project.project_amounts.debit || 0;
return acc;
},
{ credit: 0, debit: 0, total_credit: 0, total_debit: 0 }
);
const totalPayments = ungroupedProjects.reduce(
(acc: any, project: any) => {
return {
in_process: acc.in_process + (project.total_payments?.in_process || 0),
total_amount_payment:
acc.total_amount_payment + (project.total_payments?.total_amount_payment || 0),
};},
{ in_process: 0, total_amount_payment: 0 }
);
const ungroupedGroup = {
id: null,
name: "Не в группе",
description: null,
total_limits: {
credit: ungroupedTotals.credit,
debit: ungroupedTotals.debit,
},
total_amounts: {
total_credit: ungroupedTotals.total_credit,
total_debit: ungroupedTotals.total_debit,
},
total_payments: totalPayments,
projects: ungroupedProjects,
};
const allGroups: any = [ungroupedGroup, ...(data.data.projects_groups || [])];
setProjects(allGroups);
setStats(data.data.header)
}
useEffect(() => {
}, [projectDataItem])
useEffect(() => {
getProject()
}, [search, sortField, sortDirection, currentTab])
const isFirstRenderGroup = useRef(true);
useEffect(() => {
if (isFirstRenderGroup.current && isAddGroup) {
setInitialGroupData({ ...groupData });
isFirstRenderGroup.current = false;
}
}, [isAddGroup]);
const isFirstRender = useRef(true);
useEffect(() => {
// if (isFirstRender.current && isAddProject) {
setInitialProjectData({...projectData});
isFirstRender.current = false;
// }
}, [isAddProject]);
const formatterNumberPayments = (value: number): string => {
const absValue = Math.abs(value);
const lastTwo = absValue % 100;
const lastOne = absValue % 10;
if (lastTwo >= 11 && lastTwo <= 14) {
return `${value} платежей`;
}
if (lastOne === 1) {
return `${value} платеж`;
}
if (lastOne >= 2 && lastOne <= 4) {
return `${value} платежа`;
}
return `${value} платежей`;
};
const columns = [
{
title: <Flex style={{marginLeft: '30px'}}>Название</Flex>,
dataIndex: 'supplier',
key: 'article',
render: (value:any, record: any) => {
const fullText = `${value} ${record.object_address ? `| ${record.object_address}` : ''} ${record.short_description ? `| ${record.short_description}` : ''}`;
return (
<Tooltip placement="bottomRight" color="#344054" title={fullText}>
<span className={styles.projectName} style={{marginLeft: '30px'}}>
{!record.children ? fullText : value}
</span>
</Tooltip>
)
}
},
{
title: <Flex justify="end">Доходы, ₽</Flex>,
width: 140,
key: 'total_amounts',
dataIndex: 'total_amounts',
render: (value: number, record: any) => <Flex style={{flexDirection: 'column', lineHeight: '1.3', marginLeft: 'auto'}} align="end"><span style={{color: '#52C41A'}}>{formatWholeSum(record.total_amounts.total_credit)}</span> <span style={{color: '#98A2B3', fontSize: '12px', fontWeight: 400}}>{`[${formatWholeSum(record.total_limits.credit)}]`}</span></Flex>
},
{
title: <Flex justify="end">Расходы, ₽</Flex>,
dataIndex: 'expense',
key: 'expense',
width: 140,
render: (value: number, record: any) => record.children ? (
<Flex style={{flexDirection: 'column', lineHeight: '1.3', marginLeft: 'auto'}} align="end"><span style={{color: '#101828'}}>{formatWholeSum(+record.total_amounts.total_debit)}</span> <span style={{color: '#FF4d4F', fontSize: '12px', fontWeight: 400}}>[{formatWholeSum(+record.total_limits.debit)}]</span></Flex>
) : <Flex style={{flexDirection: 'column', lineHeight: '1.3', marginLeft: 'auto'}} align="end"><span style={{color: '#101828'}}>{formatWholeSum(record.total_amounts.total_debit)}</span> <span style={{color: '#FF4d4F', fontSize: '12px', fontWeight: 400}}>{`[${formatWholeSum(+record.total_limits.debit)}]`}</span></Flex>,
},
{
title: 'Платежи в процессе',
dataIndex: 'payments',
width: 200,
render: (value: number, record: any) => (
<Flex gap={8}>
<Tag color="#EAECF0" style={{ color: '#101828' }}>
{formatterNumberPayments(record?.inProcess || record?.total_payments?.in_process || 0)} ┆ {formatWholeSum(record.totalAmountPayments || record?.total_payments?.total_amount_payment || 0)} ₽
</Tag>
</Flex>
),
},
];
const { totalIncome, totalExpense, selectedCount } = useMemo(() => {
const selectedKeysSet = new Set(selectedKeys);
let totalIncome = 0;
let totalExpense = 0;
let count = 0;
transformedData.forEach(group => {
if (selectedKeysSet.has(group.key)) {
totalIncome += group.total_amounts.total_credit || 0;
totalExpense += group.total_amounts.total_debit || 0;
count++;
return;
}
group.children?.forEach((project: any) => {
if (selectedKeysSet.has(project.key)) {
totalIncome += project.total_amounts.total_credit || 0;
totalExpense += project.total_amounts.total_debit || 0;
count++;
}
});
});
return { totalIncome, totalExpense, selectedCount: count };
}, [selectedKeys, transformedData]);
const permissionsRaw = useUnit($permissionStore).permissions as any;
const permissionsStore = Array.isArray(permissionsRaw)
? permissionsRaw
: typeof permissionsRaw === 'string'
? permissionsRaw.split(',').filter(Boolean)
: [];
const allowedRoles: any = ['accountant', 'superAdmin'];
const allowedCollaboratorProject: any = ['collaborator'];
const isAllowedProjectEdit = () => {
const isRoleAllowed = allowedRoles.includes(roleStore);
return (
(isRoleAllowed) ||
(allowedCollaboratorProject && permissionsStore.includes("project_management"))
);
};
const handleRowClick = (record: any) => {
return {
onClick: async (event: React.MouseEvent) => {
if (record.isGroup) {
event.stopPropagation();
const { data }: any = await getGroupProject(record.id)
setGroupItemData(data.data)
setIsRowDrawerOpen(true);
setRecordData(record)
setIsEditableByRole(isAllowedProjectEdit())
}
if (!record.isGroup) {
event.stopPropagation();
const { data }: any = await getProjectItem(record.id)
setProjectItemData(data.data)
setOpenChildRow(true)
setRecordData(record)
setIsEditableByRole(isAllowedProjectEdit())
}
},
};
};
const handleGroupSelect = (groupKey: string, checked: boolean) => {
const childKeys = getAllChildKeys(transformedData, groupKey);
setSelectedKeys(prev =>
checked
? [...prev, ...childKeys]
: prev.filter(k => !childKeys.includes(k))
);
};
const handleSingleSelect = (key: React.Key, checked: boolean) => {
setSelectedKeys(prev =>
checked
? [...prev, key]
: prev.filter(k => k !== key)
);
};
const rowSelection: TableRowSelection<any> = useMemo(() => ({
selectedRowKeys: selectedKeys,
onChange: (keys) => setSelectedKeys(keys || []),
columnWidth: 45,
renderCell: (checked, record) => {
const stop = (e: React.MouseEvent) => {
e.stopPropagation();
};
if (record.isGroup) {
const childrenKeys = getAllChildKeys(transformedData, record.key);
const allSelected = childrenKeys.every(k => selectedKeys.includes(k));
const indeterminate = !allSelected && childrenKeys.some(k => selectedKeys.includes(k));
if (childrenKeys.length === 0 && !record.project_group_id) {
return (
<div onClick={stop}>
<Checkbox
checked={checked}
onClick={(e) => {
e.stopPropagation();
handleSingleSelect(record.key, !checked);
}}
/>
</div>
)}
return (
<div onClick={stop}>
<Checkbox
checked={allSelected}
indeterminate={indeterminate}
onClick={(e) => {
e.stopPropagation();
handleGroupSelect(record.key, !allSelected);
}}
/>
</div>
);
}
return (
<div onClick={stop}>
<Checkbox
checked={checked}
onClick={(e) => {
e.stopPropagation();
handleSingleSelect(record.key, !checked);
}}
/>
</div>
);
}
}), [selectedKeys, transformedData]);
const createGroupHandler = async() => {
try {
await createGroup(groupData);
notification.success({
message: 'Успех',
description: 'Группа успешно создана',
});
getProject()
setIsAddGroup(false);
setGroupData(defaultGroupData)
await getProject();
} catch (err) {
notification.error({
message: 'Ошибка',
description: 'Не удалось создать группу',
});
}
}
const createProjectHandler = async() => {
try{
await createProject(projectData)
notification.success({
message: 'Успех',
description: 'Проект успешно создан',
});
getProject()
setIsAddProject(false);
setProjectData(defaultProjectData)
}catch(err) {
notification.error({
message: 'Ошибка',
description: 'Не удалось создать проект',
});
}
}
const updateProjectHandler = async() => {
if(!projectId) {
return
}
try{
await updateProject(projectData, projectId)
setRecordData({
description: projectData.description,
supplier: projectData.offer_number,
object_address: projectData.object_address,
short_description: projectData.short_description,
id: projectData.project_group_id,
});
notification.success({
message: 'Успех',
description: 'Проект успешно отредактирован',
});
getProject()
setIsAddProject(false);
// setOpenChildRow(false)
setIsEditDrawer(false);
setProjectData(defaultProjectData);
setInitialProjectData({...projectData});
}catch(err) {
notification.error({
message: 'Ошибка',
description: 'Не удалось отредактировать проект',
});
}
}
const updateGroupHandler = async() => {
if(!groupId) {
return
}
try{
const payload = {
...groupData,
projects: groupData.projects.join(',')
};
await updateGroup(payload, groupId)
setRecordData({
supplier: groupData.name,
});
notification.success({
message: 'Успех',
description: 'Группа успешно отредактирована',
});
getProject()
setIsAddGroup(false);
// setIsRowDrawerOpen(false)
setGroupData(defaultGroupData)
}catch(err) {
notification.error({
message: 'Ошибка',
description: 'Не удалось отредактировать группу',
});
}
}
const excelUpload = async () => {
try {
const filteredArrayOfSelectedKeys = selectedKeys.filter((item:any) => !isNaN(item));
const { data }: any = await postExcelFile({ids: filteredArrayOfSelectedKeys});
const originalUrl = data.data.url;
// const modifiedUrl = originalUrl
// .replace('gitep.dev-top-it.ru', 'gitep.dev-top-it.ru:8080');
const relativePath = originalUrl.split('://')[1]?.split('/').slice(1).join('/');
const modifiedUrl = originalUrl
? new URL(`/${relativePath}`, import.meta.env.VITE_BASE_URL).href
: undefined;
if (modifiedUrl) {
const encodedUrl = encodeURI(modifiedUrl);
window.open(encodedUrl, '_blank');
}
} catch (error) {
console.error('Ошибка загрузки файла:', error);
}
};
const handleSortChange = (field: string, direction: 'ASC' | 'DESC') => {
setSortField(field);
setSortDirection(direction);
};
const handleSegmentChange = (value: string) => {
if(value === 'current') {
setCurrentTab('current')
} else {
setCurrentTab('archive')
}
};
const closeWithoutSave = () => {
setIsModalOpen(false);
setIsModalProjectOpen(false);
setGroupData(defaultGroupData);
setProjectData(defaultProjectData);
};
const tableRef = useRef<HTMLDivElement>(null);
const [tableHeight, setTableHeight] = useState(600);
useEffect(() => {
const calculateHeight = () => {
if (tableRef.current) {
const viewportHeight = window.innerHeight;
const tableTop = 130;
const paddingBottom = 100;
const height = viewportHeight - tableTop - paddingBottom;
setTableHeight(Math.max(height, 300));
}
};
calculateHeight();
window.addEventListener('resize', calculateHeight);
return () => window.removeEventListener('resize', calculateHeight);
}, []);
return (
<div className={styles.wrapper}>
<Helmet>
<title>Проекты | Платежи</title>
</Helmet>
{tableToBig && <HeaderProject transformedData={transformedData} workLength={stats.in_work} income={stats.income} outcome={stats.outcome} /> }
<SortableBlock
sortField={sortField}
sortDirection={sortDirection}
onSortChange={handleSortChange}
currentTab={currentTab}
handleSegmentChange={handleSegmentChange}
onSearch={(value) => setSearch(value)}
setAddGroup={() => setIsAddGroup(true)}
setAddProject={() => setIsAddProject(true)}
roleStore={roleStore}
/>
<Flex vertical style={{ height: 'calc(100vh - 172px)' }}>
<TableComponent
tableRef={tableRef}
columns={columns}
dataSource={transformedData}
className={styles.wrapperTable}
rowSelection={rowSelection}
groupedView
rowClassName={(record) =>
record.isGroupHeader ? 'group-row' : 'child-row'
}
expandable={{
expandedRowKeys,
onExpand: (expanded, record) => {
setExpandedRowKeys(prev =>
expanded
? [...prev, record.key]
: prev.filter(key => key !== record.key))
},
}}
expandIcon={({ expanded, onExpand, record }) =>
record.children && record.children.length > 0 ? (
<span
onClick={(e) => {
e.stopPropagation()
onExpand(record, e)
}}
style={{ marginRight: 8, transition: "all 0.3s", position: 'absolute', left: '14px', top: '20px' }}
>
{expanded ? (
<ArrowShow width={16} height={16} />
) : (
<ArrowShowRight width={16} height={16} />
)}
</span>
) : null
}
onRow={handleRowClick}
virtual
scroll={{ x: 'auto', y: tableHeight }}
components={{
body: {
cell: (props: any) => (
<td {...props} style={{ ...props.style, display: 'flex', alignItems: 'center'}} />
),
},
}}
/>
{selectedKeys.length ? (
<TotalBlock
downloadExcelHadler={excelUpload}
selectedCount={selectedCount}
totalIncome={totalIncome}
totalExpense={totalExpense}
/>
) : ''}
</Flex>
{/* {selectedKeys.length ? (
<TotalBlock
downloadExcelHadler={excelUpload}
selectedCount={selectedCount}
totalIncome={totalIncome}
totalExpense={totalExpense}
/>
) : ''} */}
<DrawerComponent
open={isAddGroup}
zIndexCustom={2000}
IsEditablebyRole={IsEditablebyRole}
handleClose={async () => {
getProject()
// setGroupData(defaultGroupData)
setIsEditDrawer(false)
const isDataChanged =
groupData.name !== initialGroupData.name ||
groupData.description !== initialGroupData.description ||
!isEqual(groupData.projects, initialGroupData.projects);
if (isDataChanged) {
setIsModalOpen(true);
} else {
setGroupData(defaultGroupData);
}
setIsAddGroup(false)
}}
id={projectItemData?.id}
title={`${isEditDrawer ? (recordData?.supplier ? recordData?.supplier: 'Название группы') : 'Новая группа'}`}
content={<AddGroupContent
isAddGroup={isAddGroup}
isOpen={isAddGroup}
isEdit={isEditDrawer}
recordData={recordData}
groupData={groupData}
setGroupData={(data: any) => setGroupData({ ...groupData, ...data })}/>}
footer={
<Flex gap={12} className={styles.footer}>
<Button onClick={() => setIsAddGroup(false)} size="large">Отменить</Button>
<Button
onClick={isEditDrawer ? updateGroupHandler : createGroupHandler}
disabled={!groupData?.name?.trim()}
size="large"
>Готово</Button>
</Flex>
}
/>
<DrawerComponent
open={isAddProject}
zIndexCustom={2000}
IsEditablebyRole={IsEditablebyRole}
handleClose={async() => {
getProject()
setIsAddProject(false)
setIsEditDrawer(false)
const isDataChanged = !isEqual(projectData, initialProjectData);
if (isDataChanged) {
setIsModalProjectOpen(true);
} else {
setProjectData(defaultProjectData);
}
setInitialProjectData(defaultProjectData);
}}
id={projectItemData?.id}
title={isEditDrawer ? `${recordData.supplier} | ${recordData.object_address} | ${recordData.short_description}`
: 'Новый проект'}
content={
<AddProjectContent isOpen={isAddProject} isEditDrawer={isEditDrawer} projectData={projectData} setProjectData={(data: Partial<typeof projectData>) =>
setProjectData(prev => ({...prev, ...data}))}
/>}
footer={
<Flex gap={12} className={styles.footer}>
<Button onClick={() => setIsAddProject(false)} size="large">Отменить</Button>
<Button onClick={isEditDrawer ? updateProjectHandler : createProjectHandler} size="large">Готово</Button>
</Flex>
}
/>
<DrawerComponent
open={isRowDrawerOpen}
handleClose={async() => {
getProject()
setIsRowDrawerOpen(false)
}}
title={recordData ? recordData.supplier : ''}
id={projectItemData?.id}
zIndexCustom={100}
idGroup={recordData?.id}
updateTable={() => getProject()}
subtitle={recordData ? recordData.subtitle : ''}
isRead
clickEditItem={() => {
setIsEditDrawer(true)
setGroupId(recordData.id)
setGroupData({
name: groupItemData.name,
description: groupItemData.description,
projects: recordData?.children?.map((it: any) => it.id),
})
setIsAddGroup(true)
}}
width={900}
content={<GroupReadDrawer isRowDrawerOpen={isRowDrawerOpen} idGroup={recordData?.id} openChildRow={isRowDrawerOpen} IsEditablebyRole={IsEditablebyRole}/>}
footer={<></>}
IsEditablebyRole={IsEditablebyRole}
/>
<DrawerComponent
open={openChildRow}
handleClose={async() => {
getProject()
setOpenChildRow(false)
}}
projectItemData={projectItemData}
zIndexCustom={100}
clickEditItem={() => {
setIsEditDrawer(true)
setProjectId(recordData.id)
setProjectData({
offer_number: projectItemData.offer_number,
object_address: projectItemData.object_address,
short_description: projectItemData.short_description,
description: projectItemData.description,
project_group_id: projectItemData?.project_group?.id || null,
project_limits: projectItemData.project_limits,
status: projectItemData.status
})
setIsAddProject(true)
}}
id={projectItemData?.id}
title={recordData ? `${recordData.supplier} | ${recordData.object_address} | ${recordData.short_description}` : ''}
subtitle={recordData ? recordData.description : ''}
isProject
updateTable={() => getProject()}
isRead
width={900}
content={<ProjectReadDrawer projectData={projectItemData} openChildRow={openChildRow} IsEditablebyRole={IsEditablebyRole} />}
footer={<></>}
IsEditablebyRole={IsEditablebyRole}
/>
<Modal
title={<p className={styles["modal-save__title"]}>Выйти без сохранения?</p>}
className={styles["modal-save"]}
width={460}
closable={false}
open={isModalOpen}
onOk={() => (isEditDrawer ? updateGroupHandler : createGroupHandler)()}
onCancel={() => setIsAddGroup(true)}
footer={(_, { }) => (
<>
<Button
style={{ width: '100%' }}
className="primary-red-btn"
onClick={() => closeWithoutSave()}
>
Закрыть без сохранения
</Button>
</>
)}
>
<Flex vertical gap={32}>
<p className={styles["modal-save__text"]}>Данные не были сохранены. Хотите сохранить их перед выходом?</p>
<Flex vertical gap={8}>
<Button type="primary" key="back" onClick={() => (setIsAddGroup(true), setIsModalOpen(false))}>
Вернуться
</Button>
<Button onClick={() => {(isEditDrawer ? updateGroupHandler : createGroupHandler)()
setIsModalOpen(false)
}}>
Сохранить и закрыть
</Button>
</Flex>
</Flex>
</Modal>
<Modal
title={<p className={styles["modal-save__title"]}>Выйти без сохранения?</p>}
className={styles["modal-save"]}
width={460}
closable={false}
open={isModalProjectOpen}
// onOk={() => (isEditDrawer ? updateProjectHandler : createProjectHandler)()}
onCancel={() => setIsAddProject(false)}
footer={(_, { }) => (
<>
<Button
style={{ width: '100%' }}
className="primary-red-btn"
onClick={() => closeWithoutSave()}
>
Закрыть без сохранения
</Button>
</>
)}
>
<Flex vertical gap={32}>
<p className={styles["modal-save__text"]}>Данные не были сохранены. Хотите сохранить их перед выходом?</p>
<Flex vertical gap={8}>
<Button type="primary" key="back" onClick={() => (setProjectData({ ...projectData }), setIsAddProject(true), setIsModalProjectOpen(false))}>
Вернуться
</Button>
<Button onClick={() => {(isEditDrawer ? updateProjectHandler : createProjectHandler)()
setIsModalProjectOpen(false)
}}>
Сохранить и закрыть
</Button>
</Flex>
</Flex>
</Modal>
</div>
);
};