feat: canlı veri — ilan.gov.tr açık ihale + EKAP doğrudan temin (22/d)

- server/index.js: ilan.gov.tr proxy (açık ihale + kira/satış), TLS zincir düzeltmesi
- server/dt-worker.mjs: EKAP doğrudan temin toplayıcı (Playwright, imzasız oturum içi fetch)
- server/dt-store.mjs + il-plaka.mjs: DT verisini tender modeline çevirme
- src/services/tenderApi.js + AppContext: mock veri yerine canlı API
- Doğrudan Temin sekmesi 256 gerçek 22/d kaydıyla dolu
This commit is contained in:
2026-08-26 20:45:02 +03:00
parent d9570fe422
commit 89cfd03d92
14 changed files with 1000 additions and 66 deletions
+11 -4
View File
@@ -91,10 +91,17 @@ export const TenderCard = ({ tender }) => {
<span>{tender.aciliyetBadge}</span>
</span>
)}
<span className="bg-blue-50 text-blue-700 border border-blue-200 text-[11px] font-bold px-2 py-1 rounded-md flex items-center gap-1">
<Sparkles className="w-3 h-3 text-blue-600" />
<span>%{tender.aiMatchScore} Uyumlu</span>
</span>
{tender.aiMatchScore != null && (
<span className="bg-blue-50 text-blue-700 border border-blue-200 text-[11px] font-bold px-2 py-1 rounded-md flex items-center gap-1">
<Sparkles className="w-3 h-3 text-blue-600" />
<span>%{tender.aiMatchScore} Uyumlu</span>
</span>
)}
{tender.kaynak && (
<span className="bg-emerald-50 text-emerald-700 border border-emerald-200 text-[11px] font-bold px-2 py-1 rounded-md">
🟢 {tender.kaynak}
</span>
)}
</div>
{/* Material Items Preview Box */}
+9 -5
View File
@@ -433,22 +433,26 @@ END:VCALENDAR`;
<p className="text-xs text-blue-200">Teknik şartname ve geçmiş ihale sonuçları analiz edildi.</p>
</div>
</div>
<span className="bg-amber-400 text-slate-900 font-black text-xs px-3 py-1.5 rounded-xl shadow-xs">
%{tender.aiMatchScore} Şirket Uyumu
</span>
{tender.aiMatchScore != null && (
<span className="bg-amber-400 text-slate-900 font-black text-xs px-3 py-1.5 rounded-xl shadow-xs">
%{tender.aiMatchScore} Şirket Uyumu
</span>
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 pt-2">
<div className="bg-white/10 p-4 rounded-xl border border-white/10 space-y-1">
<span className="text-slate-300 text-xs font-semibold block">Risk Skoru</span>
<span className="text-lg font-black text-emerald-400 flex items-center gap-1">
<ShieldCheck className="w-5 h-5" /> {tender.aiRiskScore} Risk
<ShieldCheck className="w-5 h-5" /> {tender.aiRiskScore || 'Analiz Bekliyor'}{tender.aiRiskScore ? ' Risk' : ''}
</span>
</div>
<div className="bg-white/10 p-4 rounded-xl border border-white/10 space-y-1">
<span className="text-slate-300 text-xs font-semibold block">Önerilen Teklif Aralığı</span>
<span className="text-base font-black text-amber-300">
₺{tender.aiBidRange?.recommended.toLocaleString('tr-TR')}
{tender.aiBidRange?.recommended != null
? `₺${tender.aiBidRange.recommended.toLocaleString('tr-TR')}`
: '—'}
</span>
</div>
<div className="bg-white/10 p-4 rounded-xl border border-white/10 space-y-1">