arm-core/web/src/widgets/ConsoleLegalEntities/ConsoleLegalEntities.tsx
Andrey Epifancev 175343b843 fix(web): вернуть синхронизацию фронта #139/#140, затёртую в ветке шахматки (ревью #158)
Коммит 7891430 откатил синхронизацию фронта (5bec434, #139/#140) и форматирование Prettier (#137).
Из origin/main восстановлены файлы, не относящиеся к шахматке:
- index.tsx (тема antd: Layout.fontSize, Form.labelFontSize/labelColor);
- layouts/DocumentPage.tsx (переключатель документа, комментарий к документу);
- services/api: consolidations.ts (getChecklist), documents.ts (postComment), files.ts (removeFile),
  directories/catalogue_jur.ts; types/consolidations/version_members.ts (ChecklistBackendShape);
- widgets: ConsoleLegalEntities (ChecklistModal, checklist_utils), FilesDrawer (DeleteModal, ReplaceDocModal,
  documentRows), DocumentReview (CommentModal, StatementReview, reviewCounters, reviewView),
  CatalogueJurForm, CatalogueJurTable, CompanyGroupsList;
- hooks/useVirtualList.tsx и components/TableTag/presets.tsx (форматирование Prettier).

В файлах шахматки оставлены её изменения: App.tsx, layouts/index.ts, api/client.ts (init в apiFetchBlob), OsvTabs.tsx,
ConsolidatedOsvContent.tsx. Из main возвращён key={version_id}: страница отчёта разделена на обёртку с key и
содержимое, чтобы при смене версии состояние (карточка, фильтры, страница) создавалось заново, как в ConsolidatedOsvPage.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 14:04:19 +04:00

144 lines
5.2 KiB
TypeScript
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 { DownloadOutlined } from '@ant-design/icons';
import { Button, Space, message } from 'antd';
import { useEffect, useMemo, useState } from 'react';
import { ApiError } from '../../api/client';
import { ColumnSettings, DataTable, useFilteredRows, useVisibleColumns } from '../../components/GenericTable';
import { useTableFilters } from '../../components/GenericTable/useTableFilters';
import { downloadChecklistCsv } from '../../services/api/consolidations';
import { getVersionCard } from '../../services/api/consolidations';
import { setSelectedLegalEntity, setSelectedVersion } from '../../store/slices/consolidations/consolidationsSlice';
import { useAppDispatch, useAppSelector } from '../../store/store';
import type { IVersionCard, MemberRow } from '../../types/consolidations/version_members';
import { saveBlob } from '../../utils/download';
import ChecklistModal from './ChecklistModal';
import { membersConfig } from './config';
import { normalizeData } from './normalize';
import { checklistFilename, responsibleName } from './panelInfo';
export function ConsoleLegalEntitiesTable({ onDrawerOpen, reloadKey }: { onDrawerOpen: () => void; reloadKey: number }) {
const dispatch = useAppDispatch();
const [loading, setLoading] = useState(false);
const consolidation_id = useAppSelector((s) => s.consolidations.current_version_id);
const [checklistOpen, setChecklistOpen] = useState(false);
const [consolidationData, setConsolidationData] = useState<IVersionCard | null>(null);
useEffect(() => {
async function getLegalEntities() {
if (!consolidation_id) return;
setLoading(true);
try {
setConsolidationData(await getVersionCard(consolidation_id));
} catch (e: unknown) {
message.error(e instanceof ApiError ? e.message : 'Не удалось загрузить карточку версии');
} finally {
setLoading(false);
}
}
getLegalEntities();
}, [consolidation_id, reloadKey]);
const rawRows = useMemo(() => normalizeData(consolidationData), [consolidationData]);
const downloadChecklist = async () => {
if (!consolidationData) return;
try {
const { blob, filename } = await downloadChecklistCsv(consolidationData.id);
const card = consolidationData;
saveBlob(blob, filename ?? checklistFilename(card.company_group.name, card.year, card.quarter));
} catch (e: unknown) {
message.error(e instanceof ApiError ? e.message : 'Не удалось скачать чек-лист');
}
};
const viewChecklist = () => {
if (!consolidationData) return;
setChecklistOpen(true);
};
const { visibleKeys, setVisibleKeys } = useVisibleColumns(membersConfig);
const { rawQuery, columnFilters, setColumnFilters, sort, setSort, resetAll, hasActiveFilters } = useTableFilters<MemberRow>();
// single filtered array — title count and table share it
const { rows: filtered } = useFilteredRows(rawRows, membersConfig, rawQuery, columnFilters, sort);
const onRow = (row: MemberRow) => ({
onClick: () => {
dispatch(setSelectedVersion(row.version_id));
dispatch(setSelectedLegalEntity(row.id));
onDrawerOpen();
},
});
return (
<>
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<Space
style={{
width: '100%',
justifyContent: 'space-between',
padding: '12px 16px',
flex: 0,
}}>
<div style={{ display: 'flex', alignItems: 'baseline', gap: 8, margin: 0 }}>
<h2
style={{
display: 'block',
boxSizing: 'border-box',
fontSize: 17,
fontWeight: 600,
margin: 0,
}}>
Организации
</h2>
<span style={{ fontSize: 13, color: 'rgb(102, 112, 133)' }}>{rawRows.length} шт.</span>
{consolidationData && (
// «Утверждён в РФ» / «Верифицирован в ГО» — маршрут согласования, Срез 7
<span
style={{
fontSize: 13,
color: 'rgb(102, 112, 133)',
marginLeft: 8,
}}>
Ответственный: {responsibleName(consolidationData)}&nbsp;&nbsp; Утверждён в РФ: —&nbsp;&nbsp; Верифицирован в ГО: —
</span>
)}
</div>
<div>
{hasActiveFilters && (
<Button
type='default'
onClick={() => {
resetAll();
}}>
Сбросить фильтры
</Button>
)}
<ColumnSettings defs={membersConfig.columns} visibleKeys={visibleKeys} onChange={setVisibleKeys} />
<Button icon={<DownloadOutlined />} disabled={!consolidationData} onClick={viewChecklist} style={{ marginLeft: 8 }}>
Скачать чек-лист
</Button>
</div>
</Space>
<DataTable
config={membersConfig}
rows={filtered}
allRows={rawRows}
loading={loading}
visibleKeys={visibleKeys}
columnFilters={columnFilters}
onColumnFiltersChange={setColumnFilters}
sortState={sort}
onSortChange={setSort}
onRow={onRow}
/>
</div>
{consolidationData && (
<ChecklistModal
open={checklistOpen}
onClose={() => {
setChecklistOpen(false);
}}
onDownload={downloadChecklist}
consolidationData={consolidationData}
/>
)}
</>
);
}