Γlvaro Valenzuela Valdes commited on
Commit Β·
5aff464
1
Parent(s): 434a703
feat: upgrade Document Corral with real icons, multi-upload and deletion
Browse files
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
|
| 97 |
-
const
|
| 98 |
-
const id = Math.random().toString(36).substring(7);
|
| 99 |
-
|
| 100 |
setIsUploading(true);
|
|
|
|
|
|
|
| 101 |
try {
|
| 102 |
-
const
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
|
|
|
|
|
|
|
|
|
| 111 |
} catch (err) {
|
| 112 |
console.error("Upload error", err);
|
| 113 |
-
setError("Failed to upload and process
|
| 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: "π",
|
| 176 |
-
if (ext === 'doc' || ext === 'docx') return { emoji: "π",
|
| 177 |
-
if (ext === 'xls' || ext === 'xlsx') return { emoji: "π",
|
| 178 |
-
return { emoji: "
|
|
|
|
| 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 |
-
<
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
|