File size: 3,631 Bytes
feca495
3786a3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
feca495
 
 
 
3786a3f
 
 
feca495
 
 
 
3786a3f
 
 
 
 
feca495
 
3786a3f
feca495
3786a3f
 
feca495
 
 
 
 
 
 
 
 
 
 
 
 
 
3786a3f
 
 
feca495
 
 
 
 
 
 
 
 
 
 
 
3786a3f
 
 
feca495
 
3786a3f
 
feca495
3786a3f
 
 
 
 
 
 
feca495
3786a3f
 
 
 
 
 
 
 
 
feca495
3786a3f
 
 
 
 
 
 
 
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { FileText, AlertCircle, RotateCcw, Trash2 } from 'lucide-react';
import { DocumentItem } from '@/store/documents';
import { StatusBadge } from './StatusBadge';
import { ProcessingSteps } from './ProcessingSteps';
import { cn } from '@/lib/utils';

function formatDate(iso: string) {
  try {
    return new Date(iso).toLocaleString(undefined, {
      hour: 'numeric',
      minute: '2-digit',
      month: 'short',
      day: 'numeric',
    });
  } catch {
    return '';
  }
}

export function DocumentRow({
  doc,
  isSelected,
  onToggleSelect,
  onViewDetails,
  onDelete,
  onRetry,
}: {
  doc: DocumentItem;
  isSelected?: boolean;
  onToggleSelect?: (id: string) => void;
  onViewDetails?: (doc: DocumentItem) => void;
  onDelete?: (id: string) => void;
  onRetry?: (id: string) => void;
}) {
  return (
    <div
      className={cn(
        'rounded-md border border-border bg-bg-surface p-3 transition-colors',
        doc.status === 'COMPLETED' && 'hover:border-accent-violet/30 cursor-pointer'
      )}
      onClick={() => doc.status === 'COMPLETED' && onViewDetails?.(doc)}
    >
      <div className="flex items-center justify-between gap-3">
        <div className="flex min-w-0 flex-1 items-center gap-2">
          {doc.status === 'COMPLETED' ? (
            <input
              type="checkbox"
              checked={isSelected}
              onChange={(e) => {
                e.stopPropagation();
                onToggleSelect?.(doc.id);
              }}
              className="h-4 w-4 rounded border-border bg-bg-surface text-accent-violet focus:ring-accent-violet cursor-pointer"
            />
          ) : (
            <div className="w-4 h-4 shrink-0" /> // Spacer to preserve alignment
          )}
          <FileText className="h-4 w-4 shrink-0 text-text-muted" />
          <span className="truncate text-sm font-medium text-text-primary">{doc.name}</span>
        </div>
        
        <div className="flex items-center gap-2" onClick={(e) => e.stopPropagation()}>
          <StatusBadge status={doc.status} />
          <button
            type="button"
            onClick={() => onDelete?.(doc.id)}
            className="rounded p-1 text-text-muted hover:bg-bg-elevated hover:text-error transition-colors"
            title="Delete document"
          >
            <Trash2 className="h-4 w-4" />
          </button>
        </div>
      </div>

      {doc.status === 'PROCESSING' ? (
        <div className="mt-2 pl-6">
          <ProcessingSteps currentStep={doc.processingStep} status={doc.status} />
        </div>
      ) : (
        <div className="mt-2 pl-6 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-muted">
          {doc.entities !== undefined && <span>{doc.entities} entities</span>}
          {doc.relationships !== undefined && <span>{doc.relationships} relations</span>}
          <span>{formatDate(doc.uploadedAt)}</span>
        </div>
      )}

      {doc.status === 'FAILED' && (
        <div className="mt-2 ml-6 flex items-center justify-between gap-2 rounded-md bg-error/10 px-2 py-1.5 text-xs text-error">
          <span className="flex items-center gap-1">
            <AlertCircle className="h-3.5 w-3.5" /> {doc.error || 'Processing failed'}
          </span>
          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation();
              onRetry?.(doc.id);
            }}
            className="inline-flex items-center gap-1 font-medium hover:underline text-error"
          >
            <RotateCcw className="h-3 w-3" /> Retry
          </button>
        </div>
      )}
    </div>
  );
}