171 lines
5.1 KiB
TypeScript
171 lines
5.1 KiB
TypeScript
import { useEffect, useMemo, useState, useRef } from 'react';
|
||
import { useParams } from 'react-router-dom';
|
||
import { Button } from 'antd';
|
||
import { FullscreenOutlined, FullscreenExitOutlined, DownloadOutlined } from '@ant-design/icons';
|
||
import { ApiError } from '../../api/client';
|
||
import {
|
||
exportChessTableAll,
|
||
exportChessTableManual,
|
||
fetchChessConsolidations,
|
||
fetchChessConsolidationsManual,
|
||
} from '../../services/consodilation/chess';
|
||
import type { IntercompanyMatrixResponse } from '../../types/chess/chess';
|
||
import { useNotificationApi } from '../../utils/useNotification';
|
||
import { ConsolidationChessTable } from '../ConsolidationChessTable/ConsolidationChessTable';
|
||
import { ConsolidationChessTableFilter } from '../ConsolidationChessTable/ConsolidationChessTableFilter';
|
||
import { saveBlob } from '../../utils/download';
|
||
|
||
|
||
|
||
|
||
export const ChessContent = () => {
|
||
const { version_id } = useParams<{ version_id: string }>();
|
||
const notification = useNotificationApi();
|
||
|
||
const [data, setData] = useState<IntercompanyMatrixResponse | null>(null);
|
||
const [loading, setLoading] = useState(false);
|
||
const [expoerLoading, setExportLoading] = useState(false);
|
||
const [companies, setCompanies] = useState<string[]>([]);
|
||
const [decimals, setDecimals] = useState(2);
|
||
const [units, setUnits] = useState('thousand');
|
||
const [debit, setDebit] = useState<string[]>([]);
|
||
const [credit, setCredit] = useState<string[]>([]);
|
||
|
||
const containerRef = useRef<HTMLDivElement>(null);
|
||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||
|
||
const toggleFullscreen = async () => {
|
||
if (!containerRef.current) return;
|
||
try {
|
||
if (!document.fullscreenElement) {
|
||
await containerRef.current.requestFullscreen();
|
||
} else {
|
||
await document.exitFullscreen();
|
||
}
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
};
|
||
|
||
const loadData = async (vId: string, dIds: string[], cIds: string[]) => {
|
||
setLoading(true);
|
||
try {
|
||
let res;
|
||
if (dIds?.length && cIds?.length) {
|
||
res = await fetchChessConsolidationsManual(vId, { debit_account_ids: dIds, credit_account_ids: cIds });
|
||
} else {
|
||
res = await fetchChessConsolidations(vId);
|
||
}
|
||
setData(res);
|
||
} catch (e) {
|
||
if (e instanceof ApiError) {
|
||
notification.error({ description: e.message });
|
||
}
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const download = async () => {
|
||
if (!version_id) {
|
||
return;
|
||
}
|
||
setExportLoading(true);
|
||
try {
|
||
if (debit?.length && credit?.length) {
|
||
const { blob, filename } = await exportChessTableManual(version_id, { debit_account_ids: debit, credit_account_ids: credit });
|
||
saveBlob(blob, filename ?? 'Шахматка');
|
||
} else {
|
||
const { blob, filename } = await exportChessTableAll(version_id);
|
||
saveBlob(blob, filename ?? 'Шахматка');
|
||
}
|
||
} catch (e) {
|
||
if (e instanceof ApiError) {
|
||
notification.error({ description: e.message });
|
||
}
|
||
} finally {
|
||
setExportLoading(false);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (!version_id) return;
|
||
loadData(version_id, debit, credit);
|
||
}, [version_id, debit, credit]);
|
||
|
||
useEffect(() => {
|
||
const handleFullscreenChange = () => {
|
||
setIsFullscreen(!!document.fullscreenElement);
|
||
};
|
||
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
||
return () => {
|
||
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
||
};
|
||
}, []);
|
||
|
||
const filteredData = useMemo(() => {
|
||
if (!data) return null;
|
||
if (companies.length === 0) return data;
|
||
|
||
const filteredCompanies = data.companies.filter((c) => companies.includes(c.id));
|
||
const filteredCells = data.cells.filter((c) => companies.includes(c.company_a_id) && companies.includes(c.company_b_id));
|
||
|
||
return { companies: filteredCompanies, cells: filteredCells };
|
||
}, [data, companies]);
|
||
|
||
return (
|
||
<div
|
||
ref={containerRef}
|
||
style={{
|
||
backgroundColor: isFullscreen ? '#fff' : 'transparent',
|
||
padding: isFullscreen ? 24 : 0,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
height: isFullscreen ? '100vh' : 'auto',
|
||
overflow: isFullscreen ? 'hidden' : 'visible',
|
||
}}>
|
||
<ConsolidationChessTable
|
||
data={filteredData}
|
||
loading={loading}
|
||
decimals={decimals}
|
||
units={units}
|
||
isFullscreen={isFullscreen}
|
||
toolbar={
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
width: '100%',
|
||
flexWrap: 'wrap',
|
||
gap: 16,
|
||
}}>
|
||
<div style={{ flex: '1 1 auto' }}>
|
||
<ConsolidationChessTableFilter
|
||
companies={companies}
|
||
onCompaniesChange={setCompanies}
|
||
decimals={decimals}
|
||
onDecimalsChange={setDecimals}
|
||
units={units}
|
||
onUnitsChange={setUnits}
|
||
debit={debit}
|
||
onDebitChange={setDebit}
|
||
credit={credit}
|
||
onCreditChange={setCredit}
|
||
allCompanies={data?.companies || []}
|
||
/>
|
||
</div>
|
||
<Button loading={expoerLoading} onClick={() => download()} icon={<DownloadOutlined />}>
|
||
Экспорт
|
||
</Button>
|
||
<Button onClick={toggleFullscreen} icon={isFullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}>
|
||
{isFullscreen ? 'Свернуть' : 'На весь экран'}
|
||
</Button>
|
||
</div>
|
||
}
|
||
|
||
/>
|
||
</div>
|
||
);
|
||
};
|