import { Alert, Button, Input, Modal, Space, Tooltip, Typography } from 'antd'; import { useState } from 'react'; import type { ChecksOut, FailedCheckOut } from '../../types/api'; import { formatAmount } from '../../utils/money'; export const failureText = (f: FailedCheckOut) => `Колонка ${f.column_index + 1}: ${f.relation} — ожидалось ${formatAmount(f.expected)}, получено ${formatAmount(f.actual)}`; type Props = { checks: ChecksOut; editable: boolean; dirty: boolean; onAccept: (comment: string) => Promise }; // soft_failed — мягкие соотношения §7 (2400, 2500, «сумма подстрок = родитель») и жёсткие в пределах округления; // подтверждение они не блокируют // длинный список нарушений (OCR) не должен выталкивать таблицу формы за экран const failureList = (list: FailedCheckOut[]) => (
{list.map((f) => (
{failureText(f)}
))}
); export function ChecksPanel({ checks, editable, dirty, onAccept }: Props) { const [open, setOpen] = useState(false); const [comment, setComment] = useState(''); const [saving, setSaving] = useState(false); const canAccept = editable && checks.failed.length > 0 && checks.accepted === null; const submit = async () => { setSaving(true); try { await onAccept(comment.trim()); setOpen(false); setComment(''); } catch { // ошибку уже показал вызывающий; окно остаётся открытым, чтобы не потерять комментарий } finally { setSaving(false); } }; return ( {checks.failed.length === 0 && checks.soft_failed.length === 0 && !checks.cross_form && ( )} {checks.failed.length > 0 && ( )} {checks.soft_failed.length > 0 && ( )} {checks.cross_form && ( )} {checks.accepted && ( )} {canAccept && ( )} setOpen(false)}> Комментарий обязателен (до 2000 символов). setComment(e.target.value)} /> ); }