Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
94 lines
3.7 KiB
TypeScript
94 lines
3.7 KiB
TypeScript
import { Button, Input, Tooltip } from 'antd';
|
||
import type { DocumentType, IssueOut, StatementHeaderOut } from '../../types/api';
|
||
import { SeverityIcon } from './IssuesPanel';
|
||
import { type HeaderFieldKey, headerFields } from './headerFields';
|
||
import { worstSeverity } from './issuePlaces';
|
||
import { formTitle, formatReportDate } from './reviewView';
|
||
|
||
export type HeaderDraft = Partial<Record<HeaderFieldKey, string>>;
|
||
|
||
type Props = {
|
||
header: StatementHeaderOut;
|
||
documentType: DocumentType;
|
||
editing: boolean;
|
||
draft: HeaderDraft;
|
||
onDraftChange: (field: HeaderFieldKey, text: string) => void;
|
||
/** предупреждения по полям шапки (IssuePlaces.byField) */
|
||
byField?: Map<string, IssueOut[]>;
|
||
/** «Подтвердить дату»; черновик подтверждения подключает T6 */
|
||
onConfirmDate?: () => void;
|
||
};
|
||
|
||
const ATTENTION_BG = '#fff7e6';
|
||
const MODIFIED_BG = '#e6f4ff';
|
||
const PLACEHOLDER: Record<HeaderFieldKey, string> = {
|
||
organization_name: 'Наименование организации',
|
||
inn: 'ИНН',
|
||
report_date: 'ГГГГ-ММ-ДД',
|
||
units: 'тыс. руб.',
|
||
};
|
||
const cell = { border: '1px solid #d0d5dd', padding: '4px 10px' };
|
||
|
||
function fieldBackground(modified: boolean, attention: boolean): string | undefined {
|
||
if (modified) return MODIFIED_BG;
|
||
return attention ? ATTENTION_BG : undefined;
|
||
}
|
||
|
||
/**
|
||
* Шапка формы как в старом АРМ (PDFResultViewer): справа компактная таблица ИНН / Дата отчёта / Единица измерения —
|
||
* ровно то, что распознавание извлекает надёжно; дальше заголовок формы. Реквизиты бумажной формы из макета [41]
|
||
* (ОКПО, ОКОПФ, ОКФС, адрес) распознавание не отдаёт (arm-scan-gateway#15) — пустые рамки не рисуем.
|
||
*/
|
||
export function StatementHeaderBlock({ header, documentType, editing, draft, onDraftChange, byField, onConfirmDate }: Props) {
|
||
const reportDate = formatReportDate(header.report_date.value);
|
||
return (
|
||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||
<table style={{ alignSelf: 'flex-end', borderCollapse: 'collapse', fontSize: 13 }}>
|
||
<tbody>
|
||
{headerFields(header, byField).map((r) => (
|
||
<tr key={r.field}>
|
||
<td style={{ ...cell, color: '#475467' }}>{r.label}</td>
|
||
<td
|
||
style={{
|
||
...cell,
|
||
fontWeight: 600,
|
||
minWidth: r.field === 'organization_name' ? 320 : 160,
|
||
background: fieldBackground(r.modified, r.attention),
|
||
}}>
|
||
{r.issues.length > 0 && (
|
||
<Tooltip title={r.issues.map((i) => i.message).join('; ')}>
|
||
<span>
|
||
<SeverityIcon severity={worstSeverity(r.issues) ?? 'info'} style={{ marginRight: 4 }} />
|
||
</span>
|
||
</Tooltip>
|
||
)}
|
||
{editing ? (
|
||
<>
|
||
<Input
|
||
size='small'
|
||
placeholder={PLACEHOLDER[r.field]}
|
||
value={draft[r.field] ?? r.raw ?? ''}
|
||
onChange={(e) => onDraftChange(r.field, e.target.value)}
|
||
/>
|
||
{r.canConfirm && onConfirmDate && (
|
||
<Button size='small' style={{ marginTop: 4 }} onClick={onConfirmDate}>
|
||
Подтвердить дату
|
||
</Button>
|
||
)}
|
||
</>
|
||
) : (
|
||
<Tooltip title={r.tip}>{r.text}</Tooltip>
|
||
)}
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
<div style={{ textAlign: 'center' }}>
|
||
<div style={{ fontSize: 18, fontWeight: 600 }}>{formTitle(documentType)}</div>
|
||
{reportDate && <div style={{ fontWeight: 500 }}>на {reportDate}</div>}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|