Álvaro Valenzuela Valdes commited on
Commit
38054b7
·
1 Parent(s): 4b81263

chore: temporary recovery mode for TenderSearch to debug build

Browse files
Files changed (1) hide show
  1. frontend/components/TenderSearch.tsx +13 -384
frontend/components/TenderSearch.tsx CHANGED
@@ -1,400 +1,29 @@
1
  "use client";
2
 
3
- import { Fragment, useMemo, useState, useRef, useEffect } from "react";
4
- import BrandLoader from "./BrandLoader";
5
  import type { Tender } from "../lib/types";
6
- import { Language, translations } from "../lib/translations";
7
- import AgentChat from "./AgentChat";
8
  import type { CompanyProfile } from "../lib/types";
9
 
10
  type Props = {
11
  tenders: Tender[];
12
- onSearch: (params: { keyword?: string; buyer?: string; provider_code?: string; org_code?: string; status?: string; code?: string; date?: string; type_code?: string; skip?: number; limit?: number; isAgile?: boolean }) => void;
13
  onAnalyze: (tender: Tender) => void;
14
- forceShowFollowed?: boolean;
15
- initialKeyword?: string;
16
  lang: Language;
17
  companyProfile: CompanyProfile;
18
  };
19
 
20
- export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFollowed = false, initialKeyword = "", lang, companyProfile }: Props) {
21
- const t = translations[lang];
22
- const [keyword, setKeyword] = useState(initialKeyword);
23
- const [buyerCode, setBuyerCode] = useState("");
24
- const [providerCode, setProviderCode] = useState("");
25
- const [orgCode, setOrgCode] = useState("");
26
- const [status, setStatus] = useState("");
27
- const [date, setDate] = useState("");
28
- const [typeCode, setTypeCode] = useState("");
29
- const [showAdvanced, setShowAdvanced] = useState(false);
30
- const [selectedTenderForModal, setSelectedTenderForModal] = useState<Tender | null>(null);
31
- const [selectedCodes, setSelectedCodes] = useState<string[]>([]);
32
- const [isSyncingToAgents, setIsSyncingToAgents] = useState(false);
33
- const [activeDetailTab, setActiveDetailTab] = useState<"Overview" | "Agent Chat">("Overview");
34
-
35
- const [followedTenders, setFollowedTenders] = useState<Tender[]>(() => {
36
- if (typeof window !== 'undefined') {
37
- const saved = localStorage.getItem('andes_followed_tenders_full');
38
- return saved ? JSON.parse(saved) : [];
39
- }
40
- return [];
41
- });
42
-
43
- const followedCodes = useMemo(() => followedTenders.map(t => t.code), [followedTenders]);
44
- const [showOnlyFollowed, setShowOnlyFollowed] = useState(forceShowFollowed);
45
- const [isLoading, setIsLoading] = useState(false);
46
- const [isAgileMode, setIsAgileMode] = useState(false);
47
- const isSearchPending = useRef(false);
48
- const itemsPerPage = 50;
49
-
50
- const filteredTenders = useMemo(() => {
51
- if (showOnlyFollowed) return followedTenders;
52
- let list = tenders;
53
- if (isAgileMode) {
54
- list = list.filter(t =>
55
- t.code.includes('COT26') ||
56
- t.name.toLowerCase().includes('compra ágil') ||
57
- t.sector?.toLowerCase().includes('agil')
58
- );
59
- }
60
- return list;
61
- }, [tenders, showOnlyFollowed, followedTenders, isAgileMode]);
62
-
63
- const isTenderCode = /^[0-9]+-[0-9]+-[A-Z0-9]+$/i.test(keyword);
64
- const isLiveSearch = Boolean(isTenderCode || providerCode || orgCode || status || date || typeCode);
65
- const searchButtonLabel = isLoading ? "Searching..." : isLiveSearch ? "Live MP Search" : "Fetch Active Tenders";
66
-
67
- useEffect(() => {
68
- if (forceShowFollowed) setShowOnlyFollowed(true);
69
- }, [forceShowFollowed]);
70
-
71
- useEffect(() => {
72
- if (initialKeyword && initialKeyword !== keyword) setKeyword(initialKeyword);
73
- }, [initialKeyword]);
74
-
75
- useEffect(() => {
76
- localStorage.setItem('andes_followed_tenders_full', JSON.stringify(followedTenders));
77
- }, [followedTenders]);
78
-
79
- useEffect(() => {
80
- if (selectedTenderForModal) {
81
- window.scrollTo({ top: 0, behavior: 'instant' });
82
- const timer = setTimeout(() => window.scrollTo(0, 0), 100);
83
- return () => clearTimeout(timer);
84
- }
85
- }, [selectedTenderForModal]);
86
-
87
- const toggleFollow = (tender: Tender) => {
88
- setFollowedTenders(prev => {
89
- const isFollowing = prev.some(t => t.code === tender.code);
90
- return isFollowing ? prev.filter(t => t.code !== tender.code) : [...prev, tender];
91
- });
92
- };
93
-
94
- const toggleSelect = (code: string) => {
95
- setSelectedCodes(prev => prev.includes(code) ? prev.filter(c => c !== code) : [...prev, code]);
96
- };
97
-
98
- const toggleSelectAll = () => {
99
- setSelectedCodes(selectedCodes.length === filteredTenders.length ? [] : filteredTenders.map(t => t.code));
100
- };
101
-
102
- const handleSyncToAgents = () => {
103
- setIsSyncingToAgents(true);
104
- setTimeout(() => {
105
- setIsSyncingToAgents(false);
106
- const firstSelected = tenders.find(t => t.code === selectedCodes[0]);
107
- if (firstSelected) onAnalyze(firstSelected);
108
- setSelectedCodes([]);
109
- }, 2500);
110
- };
111
-
112
- const handleSearch = async (e?: React.FormEvent) => {
113
- if (e) e.preventDefault();
114
- if (isSearchPending.current) return;
115
- isSearchPending.current = true;
116
- setIsLoading(true);
117
- try {
118
- const isCode = /^[0-9]+-[0-9]+-[A-Z0-9]+$/i.test(keyword);
119
- await onSearch({
120
- keyword: isCode ? undefined : keyword,
121
- code: isCode ? keyword : undefined,
122
- provider_code: providerCode || undefined,
123
- org_code: orgCode || undefined,
124
- status: status || undefined,
125
- type_code: typeCode || undefined,
126
- buyer: buyerCode,
127
- date,
128
- skip: 0,
129
- limit: itemsPerPage,
130
- isAgile: isAgileMode
131
- });
132
- } catch (error) {
133
- console.error(error);
134
- } finally {
135
- setIsLoading(false);
136
- isSearchPending.current = false;
137
- }
138
- };
139
-
140
  return (
141
- <div className="space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-700">
142
- {!selectedTenderForModal ? (
143
- <>
144
- {/* Header Section */}
145
- <div className={`glass-card rounded-3xl p-8 mb-4 border transition-all duration-500 ${forceShowFollowed ? 'border-purple-500/30 bg-purple-500/5 shadow-[0_0_50px_rgba(168,85,247,0.1)]' : 'border-white/10'}`}>
146
- <div className="mb-6 flex justify-between items-start">
147
- <div>
148
- <div className="flex items-center gap-3 mb-2">
149
- <div className={`w-10 h-10 rounded-2xl flex items-center justify-center text-xl ${forceShowFollowed ? 'bg-purple-500 text-white' : 'bg-white/5 text-slate-400'}`}>
150
- {forceShowFollowed ? "★" : "📡"}
151
- </div>
152
- <h2 className="text-3xl font-black text-white tracking-tight">
153
- {forceShowFollowed ? "My Portfolio" : "Tender Discovery"}
154
- </h2>
155
- </div>
156
- <p className="text-slate-400 text-sm">
157
- {forceShowFollowed ? "Your curated list of high-value opportunities." : "Real-time access to the Chilean public procurement market."}
158
- </p>
159
- </div>
160
-
161
- {selectedCodes.length > 0 && (
162
- <button
163
- onClick={handleSyncToAgents}
164
- disabled={isSyncingToAgents}
165
- className="premium-gradient text-white px-6 py-3 rounded-2xl font-black text-xs tracking-widest shadow-xl shadow-purple-500/40 animate-bounce transition-all active:scale-95 disabled:opacity-50"
166
- >
167
- {isSyncingToAgents ? "📥 INGESTING DOCUMENTS..." : `⚡ ANALYZE ${selectedCodes.length} SELECTED`}
168
- </button>
169
- )}
170
- </div>
171
-
172
- {!forceShowFollowed && (
173
- <form onSubmit={handleSearch} className="relative z-10 space-y-6">
174
- <div className="flex flex-col md:flex-row gap-4">
175
- <div className="relative flex-1 group">
176
- <div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-slate-500">
177
- <span className="text-xl">🔍</span>
178
- </div>
179
- <input
180
- type="text"
181
- placeholder={isAgileMode ? "Product keyword for Compra Ágil..." : "Search by name, ID, buyer, or description..."}
182
- className="w-full bg-slate-900/60 border border-white/10 rounded-2xl pl-12 pr-4 py-4 text-white placeholder:text-slate-600 focus:outline-none focus:ring-2 focus:ring-purple-500/50 transition-all backdrop-blur-sm"
183
- value={keyword}
184
- onChange={(e) => setKeyword(e.target.value)}
185
- />
186
- </div>
187
-
188
- <div className="flex gap-2">
189
- <button
190
- type="button"
191
- onClick={() => setShowAdvanced(!showAdvanced)}
192
- className={`px-6 py-4 rounded-2xl border transition-all flex items-center gap-2 font-bold text-sm ${showAdvanced ? 'bg-purple-500/20 border-purple-500/50 text-purple-300' : 'bg-white/5 border-white/10 text-slate-400 hover:bg-white/10'}`}
193
- >
194
- <span>⚙️</span> Advanced
195
- </button>
196
-
197
- <button
198
- type="submit"
199
- disabled={isLoading}
200
- className="px-8 py-4 bg-purple-600 hover:bg-purple-500 disabled:bg-purple-800 text-white rounded-2xl font-bold transition-all shadow-lg active:scale-95 flex items-center gap-3"
201
- >
202
- {isLoading && <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />}
203
- {searchButtonLabel}
204
- </button>
205
- </div>
206
- </div>
207
-
208
- {showAdvanced && (
209
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 p-6 glass-card rounded-3xl bg-white/[0.02] border border-white/5 animate-in slide-in-from-top-4 duration-300">
210
- <div className="space-y-2">
211
- <label className="text-[10px] font-bold uppercase tracking-widest text-slate-500 ml-1">Date</label>
212
- <input type="date" className="w-full bg-black/40 border border-white/10 rounded-xl px-4 py-2.5 text-white text-sm focus:ring-1 focus:ring-purple-500/50 [color-scheme:dark]" value={date} onChange={(e) => setDate(e.target.value)} />
213
- </div>
214
- <div className="space-y-2">
215
- <label className="text-[10px] font-bold uppercase tracking-widest text-slate-500 ml-1">Organization ID</label>
216
- <input type="text" placeholder="e.g. 6945" className="w-full bg-black/40 border border-white/10 rounded-xl px-4 py-2.5 text-white text-sm focus:ring-1 focus:ring-purple-500/50" value={orgCode} onChange={(e) => setOrgCode(e.target.value)} />
217
- </div>
218
- <div className="space-y-2">
219
- <label className="text-[10px] font-bold uppercase tracking-widest text-slate-500 ml-1">Status</label>
220
- <select className="w-full bg-black/40 border border-white/10 rounded-xl px-4 py-2.5 text-white text-sm focus:ring-1 focus:ring-purple-500/50" value={status} onChange={(e) => setStatus(e.target.value)}>
221
- <option value="">All Statuses</option>
222
- <option value="activas">Active (Publicada)</option>
223
- <option value="5">Publicada</option>
224
- <option value="6">Cerrada</option>
225
- <option value="7">Desierta</option>
226
- <option value="8">Adjudicada</option>
227
- </select>
228
- </div>
229
- <div className="space-y-2">
230
- <label className="text-[10px] font-bold uppercase tracking-widest text-slate-500 ml-1">Tender Type</label>
231
- <select className="w-full bg-black/40 border border-white/10 rounded-xl px-4 py-2.5 text-white text-sm focus:ring-1 focus:ring-purple-500/50" value={typeCode} onChange={(e) => setTypeCode(e.target.value)}>
232
- <option value="">All Types</option>
233
- <option value="L1">L1 - < 100 UTM</option>
234
- <option value="LE">LE - 100-1000 UTM</option>
235
- <option value="LP">LP - > 1000 UTM</option>
236
- <option value="LS">LS - Servicios Personales</option>
237
- <option value="D1">D1 - Trato Directo</option>
238
- </select>
239
- </div>
240
-
241
- <div className="lg:col-span-4 flex justify-between items-center pt-2">
242
- <button type="button" onClick={() => setIsAgileMode(!isAgileMode)} className={`px-4 py-2 rounded-xl border text-[10px] font-bold uppercase transition-all ${isAgileMode ? 'bg-cyan/20 border-cyan/40 text-cyan animate-pulse' : 'bg-white/5 border-white/10 text-slate-500'}`}>🚀 Compra Ágil Mode</button>
243
- <button type="button" onClick={() => { setKeyword(""); setBuyerCode(""); setProviderCode(""); setOrgCode(""); setStatus(""); setDate(""); setTypeCode(""); }} className="text-[10px] font-bold uppercase text-slate-500 hover:text-white transition">Clear Filters</button>
244
- </div>
245
- </div>
246
- )}
247
- </form>
248
- )}
249
- </div>
250
-
251
- {/* Results List */}
252
- <div className="space-y-4">
253
- <div className="flex items-center justify-between px-2">
254
- <h3 className="text-lg font-bold text-white">{showOnlyFollowed ? "Portfolio" : "Market Results"} ({filteredTenders.length})</h3>
255
- {followedCodes.length > 0 && (
256
- <button onClick={() => setShowOnlyFollowed(!showOnlyFollowed)} className={`rounded-xl px-4 py-2 text-xs font-bold border transition-all ${showOnlyFollowed ? "bg-purple-500/20 border-purple-500/40 text-purple-300" : "bg-white/5 border-white/10 text-slate-400"}`}>
257
- {showOnlyFollowed ? "★ Viewing Portfolio" : "☆ Show Favorites"}
258
- </button>
259
- )}
260
- </div>
261
-
262
- {filteredTenders.length === 0 ? (
263
- <div className="flex flex-col items-center justify-center rounded-3xl border border-white/5 bg-white/[0.02] p-20 text-center text-slate-400">
264
- <div className="text-4xl mb-4 opacity-50">{showOnlyFollowed ? "🌟" : "📡"}</div>
265
- <p>No opportunities found.</p>
266
- </div>
267
- ) : (
268
- <div className="glass-card rounded-3xl overflow-hidden border border-white/5 shadow-2xl">
269
- <div className="overflow-x-auto custom-scrollbar">
270
- <table className="w-full text-left text-sm table-fixed">
271
- <thead className="bg-white/5 text-slate-500 uppercase text-[10px] font-bold border-b border-white/5">
272
- <tr>
273
- <th className="px-6 py-5 w-[120px]">
274
- <div className="flex items-center gap-3">
275
- <input type="checkbox" checked={selectedCodes.length === filteredTenders.length && filteredTenders.length > 0} onChange={toggleSelectAll} className="w-4 h-4 rounded border-white/10 bg-white/5 text-purple-500" />
276
- ID
277
- </div>
278
- </th>
279
- <th className="px-6 py-5 w-[300px]">Opportunity</th>
280
- <th className="px-6 py-5 w-[200px]">Buyer</th>
281
- <th className="px-6 py-5 text-center w-[120px]">Status</th>
282
- </tr>
283
- </thead>
284
- <tbody className="divide-y divide-white/5">
285
- {filteredTenders.map((tender) => (
286
- <tr key={tender.code} className="hover:bg-white/[0.04] transition-colors group">
287
- <td className="px-6 py-5">
288
- <div className="flex items-center gap-3">
289
- <input type="checkbox" checked={selectedCodes.includes(tender.code)} onChange={() => toggleSelect(tender.code)} className="w-4 h-4 rounded border-white/10 bg-white/5 text-purple-500" />
290
- <button onClick={() => toggleFollow(tender)} className={`text-lg transition-all ${followedCodes.includes(tender.code) ? 'text-purple-400' : 'text-slate-600 hover:text-slate-400'}`}>
291
- {followedCodes.includes(tender.code) ? "★" : "☆"}
292
- </button>
293
- <span className="font-mono text-purple-400 text-[10px] truncate">{tender.code}</span>
294
- </div>
295
- </td>
296
- <td className="px-6 py-5 cursor-pointer group-hover:text-purple-400 transition-colors" onClick={() => setSelectedTenderForModal(tender)}>
297
- <div className="font-bold text-white group-hover:text-purple-400 truncate text-xs">{tender.name}</div>
298
- <div className="text-[10px] text-slate-500 mt-1">{tender.region || "Nacional"}</div>
299
- </td>
300
- <td className="px-6 py-5 text-slate-400 text-[11px] truncate">{tender.buyer}</td>
301
- <td className="px-6 py-5 text-center">
302
- <span className={`inline-block rounded-full px-3 py-1 text-[9px] font-black uppercase tracking-widest ${tender.status.toLowerCase().includes('publicada') ? 'bg-green-500/10 text-green-400 border border-green-500/20' : 'bg-slate-800 text-slate-500'}`}>
303
- {tender.status}
304
- </span>
305
- </td>
306
- </tr>
307
- ))}
308
- </tbody>
309
- </table>
310
- </div>
311
- </div>
312
- )}
313
- </div>
314
- </>
315
- ) : (
316
- <div className="animate-in slide-in-from-right-8 fade-in duration-700 w-full max-w-[1600px] mx-auto pt-4 pb-20">
317
- <div className="flex flex-col md:flex-row md:items-end justify-between gap-6 mb-8">
318
- <div className="flex flex-col gap-4">
319
- <button onClick={() => setSelectedTenderForModal(null)} className="flex items-center gap-2 text-slate-400 hover:text-white transition group w-fit">
320
- <span className="text-xl group-hover:-translate-x-1 transition-transform">←</span>
321
- <span className="text-sm font-bold uppercase tracking-widest">Back to search</span>
322
- </button>
323
- <div className="flex bg-white/5 p-1 rounded-2xl border border-white/10 w-fit">
324
- <button onClick={() => setActiveDetailTab("Overview")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase tracking-widest transition-all ${activeDetailTab === "Overview" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500 hover:text-slate-300"}`}>Overview</button>
325
- <button onClick={() => setActiveDetailTab("Agent Chat")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase tracking-widest transition-all ${activeDetailTab === "Agent Chat" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500 hover:text-slate-300"}`}>Agent Chat</button>
326
- </div>
327
- </div>
328
-
329
- <div className="flex items-center gap-4">
330
- <button onClick={() => toggleFollow(selectedTenderForModal)} className={`px-6 py-3 rounded-xl border text-xs font-bold transition-all ${followedCodes.includes(selectedTenderForModal.code) ? 'bg-purple-500/20 border-purple-500/40 text-purple-300' : 'bg-white/5 border-white/10 text-slate-400'}`}>
331
- {followedCodes.includes(selectedTenderForModal.code) ? "★ Saved to Portfolio" : "☆ Save to Portfolio"}
332
- </button>
333
- <button onClick={() => { onAnalyze(selectedTenderForModal); setSelectedTenderForModal(null); }} className="premium-gradient text-white px-8 py-3 rounded-xl font-black text-xs uppercase tracking-widest shadow-xl">Analyze Opportunity</button>
334
- </div>
335
- </div>
336
-
337
- {activeDetailTab === "Overview" ? (
338
- <div className="glass-card rounded-[2.5rem] overflow-hidden border border-white/5 bg-slate-900/40 backdrop-blur-xl shadow-2xl">
339
- <div className="p-10 md:p-14 border-b border-white/5 relative">
340
- <div className="absolute top-0 right-0 w-64 h-64 bg-purple-500/10 blur-[100px] -translate-y-1/2 translate-x-1/2" />
341
- <div className="relative z-10">
342
- <div className="flex items-center gap-3 mb-6">
343
- <span className="text-sm font-mono text-purple-400 bg-purple-400/10 px-3 py-1 rounded-lg border border-purple-400/20">{selectedTenderForModal.code}</span>
344
- <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">{selectedTenderForModal.status}</span>
345
- </div>
346
- <h3 className="text-3xl md:text-4xl font-black text-white leading-tight tracking-tight mb-4">{selectedTenderForModal.name}</h3>
347
- <div className="flex flex-wrap items-center gap-8 text-slate-400 font-medium">
348
- <span>🏢 {selectedTenderForModal.buyer}</span>
349
- <span>📍 {selectedTenderForModal.buyer_region || "Nacional"}</span>
350
- <span>🏷️ Type: {selectedTenderForModal.type || "N/A"}</span>
351
- </div>
352
- </div>
353
- </div>
354
- <div className="p-10 md:p-14">
355
- <div className="grid gap-16 lg:grid-cols-3">
356
- <div className="lg:col-span-2 space-y-12">
357
- <section>
358
- <h4 className="text-[10px] font-black uppercase tracking-[0.3em] text-slate-500 mb-6 flex items-center gap-3"><span className="w-8 h-[1px] bg-slate-700" />Project Scope</h4>
359
- <div className="text-slate-300 leading-relaxed text-lg bg-white/[0.02] p-8 rounded-[2rem] border border-white/5 whitespace-pre-wrap font-light">
360
- {selectedTenderForModal.description || "No description provided."}
361
- </div>
362
- </section>
363
- <div className="grid grid-cols-2 gap-6">
364
- <div className="p-6 rounded-3xl bg-white/[0.03] border border-white/5">
365
- <div className="text-[10px] uppercase text-slate-500 font-black mb-2">Estimated Investment</div>
366
- <div className="text-xl text-white font-bold">{selectedTenderForModal.estimated_amount ? new Intl.NumberFormat("es-CL", { style: "currency", currency: "CLP" }).format(selectedTenderForModal.estimated_amount) : "Not Disclosed"}</div>
367
- </div>
368
- </div>
369
- </div>
370
- <div className="space-y-12">
371
- <div className="p-8 rounded-[2rem] bg-purple-600/10 border border-purple-500/20 shadow-2xl shadow-purple-500/5">
372
- <h4 className="text-[10px] font-black uppercase tracking-[0.3em] text-purple-400 mb-6">Timeline</h4>
373
- <div className="text-[10px] text-slate-500 font-bold uppercase mb-1">Closing Deadline</div>
374
- <div className="text-2xl font-black text-white font-mono">{selectedTenderForModal.closing_date ? new Date(selectedTenderForModal.closing_date).toLocaleDateString() : "---"}</div>
375
- </div>
376
- <div>
377
- <h4 className="text-[10px] font-black uppercase tracking-[0.3em] text-slate-500 mb-6">Official Files</h4>
378
- <div className="grid gap-3">
379
- {selectedTenderForModal.attachments?.map((att, i) => (
380
- <a key={i} href={att.url} target="_blank" className="flex items-center justify-between p-5 rounded-2xl bg-white/[0.03] hover:bg-white/[0.08] border border-white/5 transition-all group/file">
381
- <span className="text-sm font-bold text-slate-200 group-hover/file:text-white truncate max-w-[200px]">{att.name}</span>
382
- <span className="text-xl text-slate-600 group-hover/file:text-purple-400">↓</span>
383
- </a>
384
- ))}
385
- </div>
386
- </div>
387
- </div>
388
- </div>
389
- </div>
390
- </div>
391
- ) : (
392
- <AgentChat tender={selectedTenderForModal} companyProfile={companyProfile} />
393
- )}
394
- </div>
395
- )}
396
-
397
- {isLoading && <BrandLoader />}
398
  </div>
399
  );
400
  }
 
1
  "use client";
2
 
3
+ import { useState } from "react";
 
4
  import type { Tender } from "../lib/types";
5
+ import { Language } from "../lib/translations";
 
6
  import type { CompanyProfile } from "../lib/types";
7
 
8
  type Props = {
9
  tenders: Tender[];
10
+ onSearch: (params: any) => void;
11
  onAnalyze: (tender: Tender) => void;
 
 
12
  lang: Language;
13
  companyProfile: CompanyProfile;
14
  };
15
 
16
+ export default function TenderSearch({ tenders, onSearch, onAnalyze, lang, companyProfile }: Props) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  return (
18
+ <div className="p-20 text-center">
19
+ <h1 className="text-4xl font-black text-white">RECOVERY MODE</h1>
20
+ <p className="text-slate-400 mt-4">The search system is being recalibrated to resolve a compilation issue.</p>
21
+ <button
22
+ onClick={() => window.location.reload()}
23
+ className="mt-8 px-8 py-4 bg-purple-600 text-white rounded-2xl font-bold"
24
+ >
25
+ Reload Platform
26
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  </div>
28
  );
29
  }