Álvaro Valenzuela Valdes commited on
Commit ·
bc31c2f
1
Parent(s): 759a61a
feat: complete tender detail view with attachments, items, and external link
Browse files- frontend/components/TenderSearch.tsx +105 -19
frontend/components/TenderSearch.tsx
CHANGED
|
@@ -181,33 +181,119 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
|
|
| 181 |
const renderDetailView = (tender: Tender) => (
|
| 182 |
<div className="animate-in slide-in-from-right-8 fade-in duration-700 w-full max-w-[1600px] mx-auto pt-4 pb-20">
|
| 183 |
<div className="flex justify-between items-end mb-8">
|
| 184 |
-
<button onClick={() => setSelectedTenderForModal(null)} className="flex items-center gap-2 text-slate-400 hover:text-white transition group">
|
| 185 |
-
<span className="text-
|
| 186 |
-
<span className="text-
|
| 187 |
</button>
|
| 188 |
<div className="flex bg-white/5 p-1 rounded-2xl border border-white/10">
|
| 189 |
-
<button onClick={() => setActiveDetailTab("Overview")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Overview" ? "bg-purple-600 text-white" : "text-slate-500"}`}>Overview</button>
|
| 190 |
-
<button onClick={() => setActiveDetailTab("Agent Chat")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Agent Chat" ? "bg-purple-600 text-white" : "text-slate-500"}`}>Agent Chat</button>
|
| 191 |
</div>
|
| 192 |
</div>
|
| 193 |
|
| 194 |
{activeDetailTab === "Overview" ? (
|
| 195 |
-
<div className="
|
| 196 |
-
<div className="
|
| 197 |
-
<
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
</div>
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
</div>
|
| 210 |
-
<button onClick={() => { onAnalyze(tender); setSelectedTenderForModal(null); }} className="w-full premium-gradient text-white px-8 py-4 rounded-2xl font-black uppercase shadow-xl">Analyze with AI</button>
|
| 211 |
</div>
|
| 212 |
</div>
|
| 213 |
</div>
|
|
|
|
| 181 |
const renderDetailView = (tender: Tender) => (
|
| 182 |
<div className="animate-in slide-in-from-right-8 fade-in duration-700 w-full max-w-[1600px] mx-auto pt-4 pb-20">
|
| 183 |
<div className="flex justify-between items-end mb-8">
|
| 184 |
+
<button onClick={() => setSelectedTenderForModal(null)} className="flex items-center gap-4 px-4 py-2 rounded-xl bg-white/5 border border-white/10 text-slate-400 hover:text-white hover:bg-white/10 transition-all group active:scale-95">
|
| 185 |
+
<span className="text-2xl group-hover:-translate-x-1 transition-transform">←</span>
|
| 186 |
+
<span className="text-xs font-black uppercase tracking-widest">Back to search</span>
|
| 187 |
</button>
|
| 188 |
<div className="flex bg-white/5 p-1 rounded-2xl border border-white/10">
|
| 189 |
+
<button onClick={() => setActiveDetailTab("Overview")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Overview" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500"}`}>Overview</button>
|
| 190 |
+
<button onClick={() => setActiveDetailTab("Agent Chat")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Agent Chat" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500"}`}>Agent Chat</button>
|
| 191 |
</div>
|
| 192 |
</div>
|
| 193 |
|
| 194 |
{activeDetailTab === "Overview" ? (
|
| 195 |
+
<div className="space-y-8">
|
| 196 |
+
<div className="glass-card rounded-[2.5rem] overflow-hidden border border-white/5 bg-slate-900/40 backdrop-blur-xl p-10 md:p-14 relative">
|
| 197 |
+
<div className="absolute top-0 right-0 p-8">
|
| 198 |
+
<a
|
| 199 |
+
href={`https://www.mercadopublico.cl/fichaLicitacion.html?code=${tender.code}`}
|
| 200 |
+
target="_blank"
|
| 201 |
+
rel="noopener noreferrer"
|
| 202 |
+
className="flex items-center gap-2 px-4 py-2 rounded-xl bg-cyan/10 border border-cyan/30 text-cyan text-[10px] font-black uppercase tracking-widest hover:bg-cyan/20 transition-all"
|
| 203 |
+
>
|
| 204 |
+
Visit Official Site 🔗
|
| 205 |
+
</a>
|
| 206 |
+
</div>
|
| 207 |
+
|
| 208 |
+
<div className="flex items-center gap-3 mb-6">
|
| 209 |
+
<span className="text-sm font-mono text-purple-400 bg-purple-400/10 px-3 py-1 rounded-lg border border-purple-400/20">{tender.code}</span>
|
| 210 |
+
<span className="px-3 py-1 rounded-lg text-xs font-black uppercase bg-green-500/10 text-green-400 border border-green-500/20">{tender.status}</span>
|
| 211 |
+
<span className="px-3 py-1 rounded-lg text-[10px] font-bold uppercase bg-white/5 text-slate-500 border border-white/10">{tender.type || "N/A"}</span>
|
| 212 |
</div>
|
| 213 |
+
|
| 214 |
+
<h3 className="text-3xl md:text-5xl font-black text-white leading-tight mb-4 max-w-4xl">{tender.name}</h3>
|
| 215 |
+
<p className="text-slate-400 text-xl font-medium mb-12">{tender.buyer}</p>
|
| 216 |
+
|
| 217 |
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
|
| 218 |
+
<div className="bg-white/5 p-6 rounded-3xl border border-white/5">
|
| 219 |
+
<p className="text-[10px] uppercase font-bold text-slate-500 tracking-[0.2em] mb-2">Estimated Investment</p>
|
| 220 |
+
<p className="text-2xl font-black text-white">
|
| 221 |
+
{tender.estimated_amount ? new Intl.NumberFormat("es-CL", { style: "currency", currency: tender.currency || "CLP", maximumFractionDigits: 0 }).format(tender.estimated_amount) : "N/A"}
|
| 222 |
+
</p>
|
| 223 |
+
</div>
|
| 224 |
+
<div className="bg-white/5 p-6 rounded-3xl border border-white/5">
|
| 225 |
+
<p className="text-[10px] uppercase font-bold text-slate-500 tracking-[0.2em] mb-2">Closing Deadline</p>
|
| 226 |
+
<p className="text-2xl font-black text-white font-mono">{tender.closing_date ? new Date(tender.closing_date).toLocaleDateString() : "---"}</p>
|
| 227 |
+
</div>
|
| 228 |
+
<div className="bg-white/5 p-6 rounded-3xl border border-white/5">
|
| 229 |
+
<p className="text-[10px] uppercase font-bold text-slate-500 tracking-[0.2em] mb-2">Region</p>
|
| 230 |
+
<p className="text-2xl font-black text-white truncate" title={tender.region}>{tender.region || "Nacional"}</p>
|
| 231 |
+
</div>
|
| 232 |
+
<div className="bg-white/5 p-6 rounded-3xl border border-white/5">
|
| 233 |
+
<p className="text-[10px] uppercase font-bold text-slate-500 tracking-[0.2em] mb-2">Sector</p>
|
| 234 |
+
<p className="text-2xl font-black text-white truncate">{tender.sector || "General"}</p>
|
| 235 |
+
</div>
|
| 236 |
+
</div>
|
| 237 |
+
|
| 238 |
+
<div className="grid lg:grid-cols-3 gap-12">
|
| 239 |
+
<div className="lg:col-span-2 space-y-8">
|
| 240 |
+
<div>
|
| 241 |
+
<h4 className="text-[10px] font-black uppercase tracking-[0.3em] text-slate-500 mb-4">Detailed Description</h4>
|
| 242 |
+
<div className="text-slate-300 leading-relaxed text-lg bg-white/[0.02] p-10 rounded-[2.5rem] border border-white/5 whitespace-pre-wrap">{tender.description || "No description provided."}</div>
|
| 243 |
+
</div>
|
| 244 |
+
|
| 245 |
+
{tender.items && tender.items.length > 0 && (
|
| 246 |
+
<div>
|
| 247 |
+
<h4 className="text-[10px] font-black uppercase tracking-[0.3em] text-slate-500 mb-4">Products / Services Required</h4>
|
| 248 |
+
<div className="overflow-hidden rounded-3xl border border-white/5 bg-black/20">
|
| 249 |
+
<table className="w-full text-left text-xs">
|
| 250 |
+
<thead className="bg-white/5 text-slate-500 font-bold uppercase text-[9px]">
|
| 251 |
+
<tr>
|
| 252 |
+
<th className="px-6 py-4">Item Name</th>
|
| 253 |
+
<th className="px-6 py-4 text-right">Quantity</th>
|
| 254 |
+
</tr>
|
| 255 |
+
</thead>
|
| 256 |
+
<tbody className="divide-y divide-white/5">
|
| 257 |
+
{tender.items.map((item, idx) => (
|
| 258 |
+
<tr key={idx} className="hover:bg-white/5 transition-colors">
|
| 259 |
+
<td className="px-6 py-4 text-slate-300 font-medium">{item.name}</td>
|
| 260 |
+
<td className="px-6 py-4 text-right font-mono text-cyan">{item.quantity} {item.unit}</td>
|
| 261 |
+
</tr>
|
| 262 |
+
))}
|
| 263 |
+
</tbody>
|
| 264 |
+
</table>
|
| 265 |
+
</div>
|
| 266 |
+
</div>
|
| 267 |
+
)}
|
| 268 |
+
</div>
|
| 269 |
+
|
| 270 |
+
<div className="space-y-8">
|
| 271 |
+
<div className="p-8 rounded-[2.5rem] bg-purple-600/10 border border-purple-500/20 relative overflow-hidden group">
|
| 272 |
+
<div className="absolute -right-10 -bottom-10 h-32 w-32 bg-purple-500/10 rounded-full blur-3xl group-hover:bg-purple-500/20 transition-all" />
|
| 273 |
+
<h4 className="text-[10px] font-black uppercase tracking-[0.3em] text-purple-400 mb-6">Decision Intelligence</h4>
|
| 274 |
+
<p className="text-xs text-slate-400 leading-relaxed mb-8">Launch our multi-agent AI pipeline to analyze compliance, risks, and win-probability for this opportunity.</p>
|
| 275 |
+
<button onClick={() => { onAnalyze(tender); setSelectedTenderForModal(null); }} className="w-full premium-gradient text-white px-8 py-5 rounded-2xl font-black uppercase shadow-xl shadow-purple-500/20 hover:scale-[1.02] active:scale-[0.98] transition-all">Analyze with AI</button>
|
| 276 |
+
</div>
|
| 277 |
+
|
| 278 |
+
<div className="p-8 rounded-[2.5rem] bg-white/5 border border-white/10">
|
| 279 |
+
<h4 className="text-[10px] font-black uppercase tracking-[0.3em] text-slate-500 mb-6">Documents & Attachments</h4>
|
| 280 |
+
{tender.attachments && tender.attachments.length > 0 ? (
|
| 281 |
+
<div className="space-y-3">
|
| 282 |
+
{tender.attachments.map((att, idx) => (
|
| 283 |
+
<a key={idx} href={att.url} target="_blank" rel="noopener noreferrer" className="flex items-center justify-between p-4 rounded-xl bg-black/40 border border-white/5 hover:border-purple-500/40 transition-all group">
|
| 284 |
+
<span className="text-[11px] text-slate-400 group-hover:text-white truncate max-w-[180px]">{att.name}</span>
|
| 285 |
+
<span className="text-xs">📥</span>
|
| 286 |
+
</a>
|
| 287 |
+
))}
|
| 288 |
+
</div>
|
| 289 |
+
) : (
|
| 290 |
+
<div className="text-center py-10 px-4 rounded-2xl bg-black/20 border border-dashed border-white/10">
|
| 291 |
+
<span className="text-2xl mb-2 block">📄</span>
|
| 292 |
+
<p className="text-[10px] text-slate-600 font-bold uppercase leading-relaxed">No direct attachments found. Check the official site for the full bidding package.</p>
|
| 293 |
+
</div>
|
| 294 |
+
)}
|
| 295 |
+
</div>
|
| 296 |
</div>
|
|
|
|
| 297 |
</div>
|
| 298 |
</div>
|
| 299 |
</div>
|