Álvaro Valenzuela Valdes commited on
Commit
1dbaf75
·
1 Parent(s): 59fcb47

feat: Premium interactive rows, file icons, and enhanced search filtering

Browse files
backend/app/main.py CHANGED
@@ -109,8 +109,14 @@ async def startup_event():
109
  region="Valparaíso",
110
  sector="Cloud",
111
  source="Mercado Público",
112
- items=[],
113
- attachments=[]
 
 
 
 
 
 
114
  )
115
  ]
116
  for t in tenders_to_add:
 
109
  region="Valparaíso",
110
  sector="Cloud",
111
  source="Mercado Público",
112
+ items=[
113
+ {"name": "Migration Service", "quantity": 1, "unit": "Unit"},
114
+ {"name": "Cloud Storage 100TB", "quantity": 1, "unit": "Year"}
115
+ ],
116
+ attachments=[
117
+ {"name": "Bases_Tecnicas.pdf", "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"},
118
+ {"name": "Anexo_Economico.docx", "url": "https://calibre-ebook.com/downloads/demos/demo.docx"}
119
+ ]
120
  )
121
  ]
122
  for t in tenders_to_add:
backend/app/routers/tenders.py CHANGED
@@ -29,7 +29,9 @@ async def search_tender_opportunities(
29
  TenderModel.name.ilike(search_filter),
30
  TenderModel.code.ilike(search_filter),
31
  TenderModel.description.ilike(search_filter),
32
- TenderModel.buyer.ilike(search_filter)
 
 
33
  )
34
  )
35
 
 
29
  TenderModel.name.ilike(search_filter),
30
  TenderModel.code.ilike(search_filter),
31
  TenderModel.description.ilike(search_filter),
32
+ TenderModel.buyer.ilike(search_filter),
33
+ TenderModel.sector.ilike(search_filter),
34
+ TenderModel.region.ilike(search_filter)
35
  )
36
  )
37
 
frontend/components/TenderSearch.tsx CHANGED
@@ -177,11 +177,17 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
177
  <tbody className="divide-y divide-white/5">
178
  {filteredTenders.map((tender) => (
179
  <Fragment key={tender.code}>
180
- <tr className="hover:bg-white/[0.02] transition-colors group">
 
 
 
181
  <td className="px-6 py-5">
182
  <div className="flex items-center gap-3">
183
  <button
184
- onClick={() => toggleFollow(tender.code)}
 
 
 
185
  className={`text-lg transition-all hover:scale-125 ${followedCodes.includes(tender.code) ? 'text-purple-400 drop-shadow-[0_0_8px_rgba(168,85,247,0.4)]' : 'text-slate-600 hover:text-slate-400'}`}
186
  >
187
  {followedCodes.includes(tender.code) ? "★" : "☆"}
@@ -191,7 +197,10 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
191
  </td>
192
  <td className="px-6 py-5 max-w-xs">
193
  <div className="font-semibold text-white group-hover:text-purple-400 transition-colors truncate">{tender.name}</div>
194
- <div className="text-[10px] text-slate-500">{tender.region || "Multiregional"}</div>
 
 
 
195
  </td>
196
  <td className="px-6 py-5 text-slate-400 text-xs">{tender.buyer}</td>
197
  <td className="px-6 py-5 text-center">
@@ -209,13 +218,10 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
209
  <td className="px-6 py-5 text-right pr-10">
210
  <div className="flex items-center justify-end gap-3">
211
  <button
212
- onClick={() => toggleExpanded(tender.code)}
213
- className="text-[11px] font-bold text-slate-400 hover:text-white transition"
214
- >
215
- {expandedTenderCodes.includes(tender.code) ? "Close" : "Detail"}
216
- </button>
217
- <button
218
- onClick={() => onAnalyze(tender)}
219
  className="bg-white/10 hover:bg-white/20 text-white text-[11px] font-bold px-4 py-2 rounded-lg transition-all border border-white/10"
220
  >
221
  Analyze
@@ -249,9 +255,17 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
249
  <h4 className="text-[10px] font-bold uppercase tracking-widest text-purple-400 mb-3">Resources & Direct Links</h4>
250
  <div className="grid gap-3">
251
  {tender.attachments?.map((att, i) => (
252
- <a key={i} href={att.url} target="_blank" className="flex items-center gap-3 p-3 rounded-xl bg-white/[0.03] hover:bg-white/[0.06] border border-white/5 transition group">
253
- <span className="text-lg">📄</span>
254
- <span className="text-xs text-slate-300 group-hover:text-white truncate">{att.name}</span>
 
 
 
 
 
 
 
 
255
  </a>
256
  ))}
257
  <a
 
177
  <tbody className="divide-y divide-white/5">
178
  {filteredTenders.map((tender) => (
179
  <Fragment key={tender.code}>
180
+ <tr
181
+ className="hover:bg-white/[0.04] cursor-pointer transition-colors group"
182
+ onClick={() => toggleExpanded(tender.code)}
183
+ >
184
  <td className="px-6 py-5">
185
  <div className="flex items-center gap-3">
186
  <button
187
+ onClick={(e) => {
188
+ e.stopPropagation();
189
+ toggleFollow(tender.code);
190
+ }}
191
  className={`text-lg transition-all hover:scale-125 ${followedCodes.includes(tender.code) ? 'text-purple-400 drop-shadow-[0_0_8px_rgba(168,85,247,0.4)]' : 'text-slate-600 hover:text-slate-400'}`}
192
  >
193
  {followedCodes.includes(tender.code) ? "★" : "☆"}
 
197
  </td>
198
  <td className="px-6 py-5 max-w-xs">
199
  <div className="font-semibold text-white group-hover:text-purple-400 transition-colors truncate">{tender.name}</div>
200
+ <div className="flex items-center gap-2 mt-1">
201
+ <span className="text-[10px] text-slate-500">{tender.region || "Multiregional"}</span>
202
+ <span className="text-[8px] px-1.5 py-0.5 rounded-md bg-white/5 text-slate-600 border border-white/5 uppercase tracking-tighter">{tender.sector}</span>
203
+ </div>
204
  </td>
205
  <td className="px-6 py-5 text-slate-400 text-xs">{tender.buyer}</td>
206
  <td className="px-6 py-5 text-center">
 
218
  <td className="px-6 py-5 text-right pr-10">
219
  <div className="flex items-center justify-end gap-3">
220
  <button
221
+ onClick={(e) => {
222
+ e.stopPropagation();
223
+ onAnalyze(tender);
224
+ }}
 
 
 
225
  className="bg-white/10 hover:bg-white/20 text-white text-[11px] font-bold px-4 py-2 rounded-lg transition-all border border-white/10"
226
  >
227
  Analyze
 
255
  <h4 className="text-[10px] font-bold uppercase tracking-widest text-purple-400 mb-3">Resources & Direct Links</h4>
256
  <div className="grid gap-3">
257
  {tender.attachments?.map((att, i) => (
258
+ <a key={i} href={att.url} target="_blank" className="flex items-center justify-between p-4 rounded-2xl bg-white/[0.03] hover:bg-white/[0.08] border border-white/5 transition-all group/file">
259
+ <div className="flex items-center gap-4">
260
+ <span className="text-2xl">
261
+ {att.name.endsWith('.pdf') ? "📕" : "📘"}
262
+ </span>
263
+ <div className="flex flex-col">
264
+ <span className="text-xs font-bold text-slate-200 group-hover/file:text-white transition-colors">{att.name}</span>
265
+ <span className="text-[10px] text-slate-500 uppercase tracking-tighter">Official Document</span>
266
+ </div>
267
+ </div>
268
+ <span className="text-[10px] font-black text-purple-400 opacity-0 group-hover/file:opacity-100 transition-all">DOWNLOAD</span>
269
  </a>
270
  ))}
271
  <a