import { DownloadOutlined, FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons'; import { Button, ConfigProvider } from 'antd'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; import { ApiError } from '../../../api/client'; import { exportChessConsolidationsResult, exportIntercompanyMatrix, fetchChessConsolidationsResult, fetchIntercompanyMatrix, } from '../../../services/api/intercompanyMatrix'; import type { IntercompanyMatrixRequest, IntercompanyMatrixResponse, IntercompanyMatrixResultResponse, MatrixCompany, } from '../../../types/api'; import type { VersionCard } from '../../../types/consolidations/version_members'; import { chessMatrixMode } from '../../../utils/chessMatrixMode'; import { chessMatrixRequest, isWholePerimeter } from '../../../utils/chessMatrixRequest'; import { saveBlob, xlsxFilename } from '../../../utils/download'; import { useNotificationApi } from '../../../utils/useNotification'; import { ConsolidationChessFormatTableFilter } from '../ConsolidationChessFormatTableFilter/ConsolidationChessFormatTableFilter'; import { ConsolidationChessResTable } from '../ConsolidationChessResTable/ConsolidationChessResTable'; import { ConsolidationChessTable } from '../ConsolidationChessTable/ConsolidationChessTable'; import { ConsolidationChessTableFilter } from '../ConsolidationChessTableFilter/ConsolidationChessTableFilter'; export const ChessContent = ({ card }: { card: VersionCard | null }) => { const { version_id } = useParams<{ version_id: string }>(); const notification = useNotificationApi(); const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [matrixExportLoading, setMatrixExportLoading] = useState(false); const [resExportLoading, setResExportLoading] = useState(false); const [companies, setCompanies] = useState([]); // варианты фильтра «Компании» — весь периметр версии; при выборе компаний ответ сужен и их не меняет const [perimeter, setPerimeter] = useState([]); const [decimals, setDecimals] = useState(2); const [units, setUnits] = useState('thousand'); const [debit, setDebit] = useState([]); const [credit, setCredit] = useState([]); const [chessResData, setChessResData] = useState(null); const [chessResUnits, setChessResUnits] = useState('thousand'); const [chessResDecimals, setChessResDecimals] = useState(2); const [chessResLoading, setChessResLoading] = useState(false); const chessTableRef = useRef(null); const resTableRef = useRef(null); const [isChessFullscreen, setIsChessFullscreen] = useState(false); const [isResFullscreen, setIsResFullscreen] = useState(false); const toggleFullscreen = async (ref: React.RefObject, setFullscreen: (val: boolean) => void) => { if (!ref.current) return; try { if (!document.fullscreenElement) { await ref.current.requestFullscreen(); setFullscreen(true); } else { await document.exitFullscreen(); setFullscreen(false); } } catch (e) { notification.error({ description: e instanceof Error ? e.message : 'Не удалось переключить полноэкранный режим', }); } }; useEffect(() => { const handleFullscreenChange = () => { if (!document.fullscreenElement) { setIsChessFullscreen(false); setIsResFullscreen(false); } }; document.addEventListener('fullscreenchange', handleFullscreenChange); return () => document.removeEventListener('fullscreenchange', handleFullscreenChange); }, []); const matrixMode = chessMatrixMode(debit, credit); const isHalfFiltered = matrixMode === 'half'; const loadData = useCallback( async (vId: string, request: IntercompanyMatrixRequest, isActual: () => boolean) => { setLoading(true); try { const res = await fetchIntercompanyMatrix(vId, request); if (isActual()) { setData(res); if (isWholePerimeter(request)) { setPerimeter(res.companies); } } } catch (e) { if (isActual() && e instanceof ApiError) { notification.error({ description: e.message }); } } finally { if (isActual()) { setLoading(false); } } }, [notification], ); const loadResData = useCallback( async (vid: string) => { setChessResLoading(true); try { const res = await fetchChessConsolidationsResult(vid); setChessResData(res); } catch (e) { if (e instanceof ApiError) { notification.error({ description: e.message }); } } finally { setChessResLoading(false); } }, [notification], ); const versionInfo = card ? { groupName: card.company_group.name, year: card.year, quarter: card.quarter } : null; const download = async () => { if (!version_id) { return; } setMatrixExportLoading(true); try { // выгрузка по тем же счетам и компаниям, что на экране: итоги в xlsx совпадают с таблицей const { blob, filename } = await exportIntercompanyMatrix(version_id, chessMatrixRequest(debit, credit, companies)); saveBlob(blob, filename ?? xlsxFilename('Шахматка', versionInfo)); } catch (e) { if (e instanceof ApiError) { notification.error({ description: e.message }); } } finally { setMatrixExportLoading(false); } }; const downloadResTable = async () => { if (!version_id) { return; } setResExportLoading(true); try { const { blob, filename } = await exportChessConsolidationsResult(version_id); saveBlob(blob, filename ?? xlsxFilename('Результирующая_таблица_ВГО', versionInfo)); } catch (e) { if (e instanceof ApiError) { notification.error({ description: e.message }); } } finally { setResExportLoading(false); } }; useEffect(() => { // выбрана только одна сторона Дт/Кт — запрос не шлём, таблица показывает подсказку if (!version_id || isHalfFiltered) return; let isMounted = true; const isActual = () => isMounted; loadData(version_id, chessMatrixRequest(debit, credit, companies), isActual); return () => { isMounted = false; setLoading(false); }; }, [version_id, debit, credit, companies, isHalfFiltered, loadData]); useEffect(() => { if (!version_id) return; loadResData(version_id); }, [version_id, loadResData]); return ( (document.fullscreenElement as HTMLElement) || document.body}>
} />
} />
); };