Seth0330 commited on
Commit
78ca83f
·
verified ·
1 Parent(s): bb09573

Update frontend/src/components/ocr/UploadZone.jsx

Browse files
frontend/src/components/ocr/UploadZone.jsx CHANGED
@@ -1,11 +1,58 @@
1
- import React, { useState } from "react";
2
  import { motion, AnimatePresence } from "framer-motion";
3
- import { Upload, FileText, Image, FileSpreadsheet, X, Sparkles } from "lucide-react";
4
  import { cn } from "@/lib/utils";
5
  import { Input } from "@/components/ui/input";
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  export default function UploadZone({ onFileSelect, selectedFile, onClear, keyFields = "", onKeyFieldsChange = () => {} }) {
8
  const [isDragging, setIsDragging] = useState(false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  const handleDragOver = (e) => {
11
  e.preventDefault();
@@ -20,7 +67,9 @@ export default function UploadZone({ onFileSelect, selectedFile, onClear, keyFie
20
  e.preventDefault();
21
  setIsDragging(false);
22
  const file = e.dataTransfer.files[0];
23
- if (file) onFileSelect(file);
 
 
24
  };
25
 
26
  const getFileIcon = (type) => {
@@ -31,6 +80,13 @@ export default function UploadZone({ onFileSelect, selectedFile, onClear, keyFie
31
 
32
  const FileIcon = selectedFile ? getFileIcon(selectedFile.type) : FileText;
33
 
 
 
 
 
 
 
 
34
  return (
35
  <div className="w-full">
36
  <AnimatePresence mode="wait">
@@ -76,7 +132,7 @@ export default function UploadZone({ onFileSelect, selectedFile, onClear, keyFie
76
  {isDragging ? "Drop your file here" : "Drop your file here, or browse"}
77
  </p>
78
  <p className="text-sm text-slate-400">
79
- Supports PDF, PNG, JPG, TIFF, DOCX up to 50MB
80
  </p>
81
  </div>
82
 
@@ -102,8 +158,15 @@ export default function UploadZone({ onFileSelect, selectedFile, onClear, keyFie
102
  <input
103
  type="file"
104
  className="hidden"
105
- accept=".pdf,.png,.jpg,.jpeg,.tiff,.docx,.xlsx"
106
- onChange={(e) => e.target.files[0] && onFileSelect(e.target.files[0])}
 
 
 
 
 
 
 
107
  />
108
  </label>
109
 
@@ -164,6 +227,25 @@ export default function UploadZone({ onFileSelect, selectedFile, onClear, keyFie
164
  </motion.div>
165
  )}
166
  </AnimatePresence>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  </div>
168
  );
169
  }
 
1
+ import React, { useState, useEffect } from "react";
2
  import { motion, AnimatePresence } from "framer-motion";
3
+ import { Upload, FileText, Image, FileSpreadsheet, X, Sparkles, AlertCircle } from "lucide-react";
4
  import { cn } from "@/lib/utils";
5
  import { Input } from "@/components/ui/input";
6
 
7
+ // Allowed file types
8
+ const ALLOWED_TYPES = [
9
+ "application/pdf",
10
+ "image/png",
11
+ "image/jpeg",
12
+ "image/jpg",
13
+ "image/tiff",
14
+ "image/tif"
15
+ ];
16
+
17
+ // Allowed file extensions (for fallback validation)
18
+ const ALLOWED_EXTENSIONS = [".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".tif"];
19
+
20
+ // Maximum file size: 4 MB
21
+ const MAX_FILE_SIZE = 4 * 1024 * 1024; // 4 MB in bytes
22
+
23
  export default function UploadZone({ onFileSelect, selectedFile, onClear, keyFields = "", onKeyFieldsChange = () => {} }) {
24
  const [isDragging, setIsDragging] = useState(false);
25
+ const [error, setError] = useState(null);
26
+
27
+ const validateFile = (file) => {
28
+ // Reset error
29
+ setError(null);
30
+
31
+ // Check file type
32
+ const fileExtension = "." + file.name.split(".").pop().toLowerCase();
33
+ const isValidType = ALLOWED_TYPES.includes(file.type) || ALLOWED_EXTENSIONS.includes(fileExtension);
34
+
35
+ if (!isValidType) {
36
+ setError("Only PDF, PNG, JPG, and TIFF files are allowed.");
37
+ return false;
38
+ }
39
+
40
+ // Check file size
41
+ if (file.size > MAX_FILE_SIZE) {
42
+ const fileSizeMB = (file.size / 1024 / 1024).toFixed(2);
43
+ setError(`File size exceeds 4 MB limit. Your file is ${fileSizeMB} MB.`);
44
+ return false;
45
+ }
46
+
47
+ return true;
48
+ };
49
+
50
+ const handleFileSelect = (file) => {
51
+ if (validateFile(file)) {
52
+ setError(null);
53
+ onFileSelect(file);
54
+ }
55
+ };
56
 
57
  const handleDragOver = (e) => {
58
  e.preventDefault();
 
67
  e.preventDefault();
68
  setIsDragging(false);
69
  const file = e.dataTransfer.files[0];
70
+ if (file) {
71
+ handleFileSelect(file);
72
+ }
73
  };
74
 
75
  const getFileIcon = (type) => {
 
80
 
81
  const FileIcon = selectedFile ? getFileIcon(selectedFile.type) : FileText;
82
 
83
+ // Clear error when file is cleared
84
+ useEffect(() => {
85
+ if (!selectedFile) {
86
+ setError(null);
87
+ }
88
+ }, [selectedFile]);
89
+
90
  return (
91
  <div className="w-full">
92
  <AnimatePresence mode="wait">
 
132
  {isDragging ? "Drop your file here" : "Drop your file here, or browse"}
133
  </p>
134
  <p className="text-sm text-slate-400">
135
+ Supports PDF, PNG, JPG, TIFF up to 4MB
136
  </p>
137
  </div>
138
 
 
158
  <input
159
  type="file"
160
  className="hidden"
161
+ accept=".pdf,.png,.jpg,.jpeg,.tiff,.tif"
162
+ onChange={(e) => {
163
+ const file = e.target.files[0];
164
+ if (file) {
165
+ handleFileSelect(file);
166
+ }
167
+ // Reset input so same file can be selected again after error
168
+ e.target.value = "";
169
+ }}
170
  />
171
  </label>
172
 
 
227
  </motion.div>
228
  )}
229
  </AnimatePresence>
230
+
231
+ {/* Error Message */}
232
+ {error && (
233
+ <motion.div
234
+ initial={{ opacity: 0, y: -10 }}
235
+ animate={{ opacity: 1, y: 0 }}
236
+ exit={{ opacity: 0, y: -10 }}
237
+ className="mt-3 p-3 bg-red-50 border border-red-200 rounded-xl flex items-start gap-2"
238
+ >
239
+ <AlertCircle className="h-4 w-4 text-red-600 flex-shrink-0 mt-0.5" />
240
+ <p className="text-sm text-red-700 flex-1">{error}</p>
241
+ <button
242
+ onClick={() => setError(null)}
243
+ className="text-red-600 hover:text-red-800 transition-colors"
244
+ >
245
+ <X className="h-4 w-4" />
246
+ </button>
247
+ </motion.div>
248
+ )}
249
  </div>
250
  );
251
  }