Álvaro Valenzuela Valdes commited on
Commit
5aff464
Β·
1 Parent(s): 434a703

feat: upgrade Document Corral with real icons, multi-upload and deletion

Browse files
Files changed (1) hide show
  1. frontend/components/AgentAnalysis.tsx +48 -31
frontend/components/AgentAnalysis.tsx CHANGED
@@ -93,30 +93,39 @@ export default function AgentAnalysis({ tender, companyProfile, analysis, onAnal
93
  };
94
 
95
  const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
96
- if (event.target.files && event.target.files[0]) {
97
- const newFile = event.target.files[0];
98
- const id = Math.random().toString(36).substring(7);
99
-
100
  setIsUploading(true);
 
 
101
  try {
102
- const uploadResult = await uploadDocument(newFile);
103
- const newEntry = {
104
- file: newFile,
105
- text: uploadResult.text,
106
- analysis: null,
107
- id
108
- };
109
- setCorral(prev => [...prev, newEntry]);
110
- setActiveAnimalId(id);
 
 
 
111
  } catch (err) {
112
  console.error("Upload error", err);
113
- setError("Failed to upload and process document.");
114
  } finally {
115
  setIsUploading(false);
116
  }
117
  }
118
  };
119
 
 
 
 
 
 
 
120
  const handleAnalyzeClick = async () => {
121
  if (!approved || !tender || !activeAnimalId) return;
122
  const activeEntry = corral.find(a => a.id === activeAnimalId);
@@ -172,10 +181,11 @@ export default function AgentAnalysis({ tender, companyProfile, analysis, onAnal
172
 
173
  const getFileIcon = (fileName: string) => {
174
  const ext = fileName.split('.').pop()?.toLowerCase();
175
- if (ext === 'pdf') return { emoji: "πŸ“„", animal: "🦒", color: "bg-red-500/10 text-red-400" };
176
- if (ext === 'doc' || ext === 'docx') return { emoji: "πŸ“", animal: "πŸ’", color: "bg-blue-500/10 text-blue-400" };
177
- if (ext === 'xls' || ext === 'xlsx') return { emoji: "πŸ“Š", animal: "🐘", color: "bg-green-500/10 text-green-400" };
178
- return { emoji: "πŸ“", animal: "🐈", color: "bg-slate-500/10 text-slate-400" };
 
179
  };
180
 
181
  if (!tender && !analysis) {
@@ -405,24 +415,31 @@ export default function AgentAnalysis({ tender, companyProfile, analysis, onAnal
405
  {corral.map((item) => {
406
  const icon = getFileIcon(item.file.name);
407
  return (
408
- <button
409
- key={item.id}
410
- onClick={() => setActiveAnimalId(item.id)}
411
- className={`group relative flex flex-col items-center justify-center h-16 w-16 rounded-2xl border transition-all duration-500 hover:scale-110 active:scale-95 ${activeAnimalId === item.id ? 'bg-purple-500/20 border-purple-500 shadow-lg shadow-purple-500/20' : 'bg-white/5 border-white/10'}`}
412
- title={item.file.name}
413
- >
414
- <span className={`text-2xl transition-all duration-500 group-hover:rotate-12 ${activeAnimalId === item.id ? 'animate-bounce' : 'group-hover:animate-wiggle'}`}>
415
- {icon.animal}
416
- </span>
417
- <span className="absolute -bottom-1 -right-1 text-[10px]">{icon.emoji}</span>
418
- {item.analysis && <span className="absolute -top-1 -right-1 h-3 w-3 bg-green-500 rounded-full border-2 border-black" title="Analyzed" />}
419
- </button>
 
 
 
 
 
 
 
420
  );
421
  })}
422
 
423
  <label className="flex flex-col items-center justify-center h-16 w-16 rounded-2xl border border-dashed border-white/20 bg-white/5 cursor-pointer hover:bg-white/10 hover:border-purple-500/50 transition-all">
424
  <span className="text-xl text-slate-500">+</span>
425
- <input type="file" onChange={handleFileChange} className="hidden" />
426
  </label>
427
  </div>
428
 
 
93
  };
94
 
95
  const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
96
+ if (event.target.files && event.target.files.length > 0) {
97
+ const filesArray = Array.from(event.target.files);
 
 
98
  setIsUploading(true);
99
+ setError(null);
100
+
101
  try {
102
+ for (const newFile of filesArray) {
103
+ const id = Math.random().toString(36).substring(7);
104
+ const uploadResult = await uploadDocument(newFile);
105
+ const newEntry = {
106
+ file: newFile,
107
+ text: uploadResult.text,
108
+ analysis: null,
109
+ id
110
+ };
111
+ setCorral(prev => [...prev, newEntry]);
112
+ setActiveAnimalId(id);
113
+ }
114
  } catch (err) {
115
  console.error("Upload error", err);
116
+ setError("Failed to upload and process one or more documents.");
117
  } finally {
118
  setIsUploading(false);
119
  }
120
  }
121
  };
122
 
123
+ const removeFromCorral = (id: string, e: React.MouseEvent) => {
124
+ e.stopPropagation();
125
+ setCorral(prev => prev.filter(a => a.id !== id));
126
+ if (activeAnimalId === id) setActiveAnimalId(null);
127
+ };
128
+
129
  const handleAnalyzeClick = async () => {
130
  if (!approved || !tender || !activeAnimalId) return;
131
  const activeEntry = corral.find(a => a.id === activeAnimalId);
 
181
 
182
  const getFileIcon = (fileName: string) => {
183
  const ext = fileName.split('.').pop()?.toLowerCase();
184
+ if (ext === 'pdf') return { emoji: "πŸ“„", label: "PDF", color: "bg-red-500/20 text-red-400 border-red-500/30" };
185
+ if (ext === 'doc' || ext === 'docx') return { emoji: "πŸ“", label: "DOC", color: "bg-blue-500/20 text-blue-400 border-blue-500/30" };
186
+ if (ext === 'xls' || ext === 'xlsx') return { emoji: "πŸ“Š", label: "XLS", color: "bg-green-500/20 text-green-400 border-green-500/30" };
187
+ if (ext === 'zip' || ext === 'rar') return { emoji: "πŸ“¦", label: "ZIP", color: "bg-amber-500/20 text-amber-400 border-amber-500/30" };
188
+ return { emoji: "πŸ“", label: "FILE", color: "bg-slate-500/20 text-slate-400 border-white/10" };
189
  };
190
 
191
  if (!tender && !analysis) {
 
415
  {corral.map((item) => {
416
  const icon = getFileIcon(item.file.name);
417
  return (
418
+ <div key={item.id} className="relative group">
419
+ <button
420
+ onClick={() => setActiveAnimalId(item.id)}
421
+ className={`flex flex-col items-center justify-center h-16 w-16 rounded-2xl border transition-all duration-500 hover:scale-110 active:scale-95 ${activeAnimalId === item.id ? 'bg-purple-500/20 border-purple-500 shadow-lg shadow-purple-500/20' : 'bg-white/5 border-white/10'}`}
422
+ title={item.file.name}
423
+ >
424
+ <span className={`text-2xl transition-all duration-500 ${activeAnimalId === item.id ? 'scale-110' : ''}`}>
425
+ {icon.emoji}
426
+ </span>
427
+ <span className="text-[8px] font-black uppercase mt-1 opacity-60">{icon.label}</span>
428
+ {item.analysis && <span className="absolute -top-1 -right-1 h-3 w-3 bg-green-500 rounded-full border-2 border-black" title="Analyzed" />}
429
+ </button>
430
+ <button
431
+ onClick={(e) => removeFromCorral(item.id, e)}
432
+ className="absolute -top-2 -right-2 h-5 w-5 bg-red-500 text-white text-[10px] rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity shadow-lg z-20"
433
+ >
434
+ Γ—
435
+ </button>
436
+ </div>
437
  );
438
  })}
439
 
440
  <label className="flex flex-col items-center justify-center h-16 w-16 rounded-2xl border border-dashed border-white/20 bg-white/5 cursor-pointer hover:bg-white/10 hover:border-purple-500/50 transition-all">
441
  <span className="text-xl text-slate-500">+</span>
442
+ <input type="file" onChange={handleFileChange} className="hidden" multiple />
443
  </label>
444
  </div>
445