1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88import { ShieldAlert, FileWarning, Lock, FileX, FileStack } from 'lucide-react';
import { Button } from '@/components/ui/button';
import type { StepResult } from '@/types/pipeline-viewer';
interface ClassificationErrorProps {
step: StepResult;
onReset: () => void;
}
const ICON_MAP: Record<string, typeof ShieldAlert> = {
form_acroform: FileWarning,
form_xfa: FileWarning,
encrypted: Lock,
empty_document: FileX,
too_many_pages: FileStack,
};
function getIcon(findings: Array<{ code: string; severity: string }>) {
for (const f of findings) {
if (f.severity === 'error' && ICON_MAP[f.code]) {
return ICON_MAP[f.code];
}
}
return ShieldAlert;
}
export function ClassificationError({ step, onReset }: ClassificationErrorProps) {
const findings = (step.metadata?.findings ?? []) as Array<{
code: string;
severity: string;
message: string;
}>;
const docType = step.metadata?.document_type as string | undefined;
const errors = findings.filter((f) => f.severity === 'error');
const warnings = findings.filter((f) => f.severity === 'warning');
const Icon = getIcon(findings);
return (
<div className="flex-1 flex items-center justify-center p-8">
<div className="max-w-lg text-center">
<div className="mx-auto w-16 h-16 rounded-full bg-red-50 flex items-center justify-center mb-4">
<Icon className="w-8 h-8 text-red-500" />
</div>
<h2 className="text-lg font-semibold text-gray-900 mb-1">
Unsupported Document
</h2>
{docType && docType !== 'unknown' && (
<p className="text-xs font-medium text-red-600 uppercase tracking-wide mb-3">
Detected type: {docType.replace('_', ' ')}
</p>
)}
<div className="space-y-2 mb-4 text-left">
{errors.map((f, i) => (
<div
key={i}
className="flex items-start gap-2 px-4 py-2.5 rounded-lg bg-red-50 text-sm text-red-800"
>
<ShieldAlert className="w-4 h-4 mt-0.5 flex-shrink-0 text-red-500" />
<span>{f.message}</span>
</div>
))}
</div>
{warnings.length > 0 && (
<div className="space-y-1.5 mb-4 text-left">
{warnings.map((f, i) => (
<p key={i} className="text-xs text-amber-700 px-4">
{f.message}
</p>
))}
</div>
)}
<p className="text-sm text-muted-foreground mb-4">
{step.elapsed_ms}ms classification time
</p>
<Button variant="outline" onClick={onReset}>
Upload a Different PDF
</Button>
</div>
</div>
);
}