Files
ihaleist/src/components/TenderDetailModal.jsx
T
hikmettan 1838de95f5 feat: ihale dokümanları + OKAS kalem verisi + doğrudan temin (Playwright) + kalıcı arşiv
1) İhale evrakları (yeni)
   - server/documents.mjs: EKAP doküman URL üretimi (imzalı), ilan metni +
     OKAS kalem çıkarımı, Playwright ile doküman metni (varsa)
   - /api/documents/url · /ilan · /text · /config uçları
   - TenderDocuments paneli: 'EKAP Dokümanlarını Aç' + 'İlan Metnini AI ile
     Analiz Et' (11K+ karakter gerçek ilan metni doğrudan AI'ya gider)
   - NOT: eski EKAP host'u bot isteklerine bağlantı kesiyor; bağlantı
     kullanıcının tarayıcısında açılır, sunucu tarafı metin için Chromium gerekir

2) Kalem verisi gerçek oldu
   - ekap-scan: her ihale için IhaleDetay'dan OKAS ihtiyaç kalemleri çekilir
   - history-store: okas_kalemler kolonu + otomatik şema geçişi
   - --kalem-doldur modu: mevcut kayıtlara IKN'den çözerek kalem ekler
   - scheduler: tarama sonrası kalem doldurmayı zincirler
   - PriceAnalysis: yöntem şeffaflığı notu (birim fiyatlar kamuya açık değil;
     kategori bazlı yaklaşık değer olduğu açıkça yazıyor)

3) Doğrudan temin (Playwright)
   - Dockerfile: node:22-slim + nginx + Playwright/Chromium
   - scheduler: DT worker periyodik (DT_INTERVAL_SAAT, varsayılan 4 saat)
   - Bellek koruması: boş bellek DT_MIN_BOS_MB altındaysa tarama atlanır ve
     uyarı loglanır; DT_ENABLED=0 ile tamamen kapatılabilir

4) Kalıcı arşiv
   - Coolify'da /app/server/data volume bağlandı; arşiv artık deploy'lar
     arası korunuyor

Ayrıca: TenderDetailModal'daki sabit '3-5 Firma' tahmini kaldırıldı, yerine
gerçek geçerli teklif sayısı gösteriliyor.
2026-08-28 22:31:40 +03:00

531 lines
27 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from 'react';
import { useApp } from '../context/AppContext';
import { TenderDocuments } from './TenderDocuments';
import {
X, Star, Share2, Calendar, MapPin, Building2, Tag, FileText, CheckSquare,
DollarSign, Calculator, Download, Sparkles, AlertTriangle, ShieldCheck,
Send, Stamp, ArrowLeft, ExternalLink, Printer
} from 'lucide-react';
import confetti from 'canvas-confetti';
export const TenderDetailModal = () => {
const { activeTenderDetail, setActiveTenderDetail, toggleTrackTender, userProfile, setIsAiSpecAnalyzerOpen } = useApp();
const [activeTab, setActiveTab] = useState('details'); // 'details', 'pdf_stamp', 'ai_assistant', 'checklist', 'kurum_tenders'
const [noteText, setNoteText] = useState('');
const [savedNotes, setSavedNotes] = useState([
{ id: 1, author: 'Hikmet Tanrıverdi', text: 'Kayseri deposuna doğrudan sevkiyat yapılacak. Birim fiyat 145 TL üstü olmalı.', date: 'Bugün 10:15' }
]);
// Kur Farkı Calculator State
const [bidAmount, setBidAmount] = useState(15000);
const usdRate = 36.45;
const eurRate = 39.80;
// Stamp Drag Position State
const [stampPos, setStampPos] = useState({ x: 220, y: 180 });
const [isDraggingStamp, setIsDraggingStamp] = useState(false);
if (!activeTenderDetail) return null;
const tender = activeTenderDetail;
const handleAddNote = (e) => {
e.preventDefault();
if (!noteText.trim()) return;
setSavedNotes([...savedNotes, {
id: Date.now(),
author: userProfile.name,
text: noteText.trim(),
date: 'Az önce'
}]);
setNoteText('');
};
const handleExportICS = () => {
confetti({ particleCount: 50 });
const icsData = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//İhaleist//İhale Takvimi//TR
BEGIN:VEVENT
SUMMARY:İhale Son Teslim: ${tender.baslik}
DESCRIPTION:İKN: ${tender.ikn} - ${tender.kurum}
DTSTART:20260810T120000Z
DTEND:20260810T130000Z
END:VEVENT
END:VCALENDAR`;
const blob = new Blob([icsData], { type: 'text/calendar;charset=utf-8' });
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.setAttribute('download', `ihale_${tender.ikn}.ics`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
const handleStampMouseDown = () => setIsDraggingStamp(true);
const handleStampMouseMove = (e) => {
if (!isDraggingStamp) return;
const rect = e.currentTarget.getBoundingClientRect();
setStampPos({
x: Math.max(20, Math.min(rect.width - 150, e.clientX - rect.left - 60)),
y: Math.max(20, Math.min(rect.height - 80, e.clientY - rect.top - 30))
});
};
const handleStampMouseUp = () => setIsDraggingStamp(false);
return (
<div className="fixed inset-0 z-50 overflow-y-auto bg-slate-900/70 backdrop-blur-xs flex justify-center p-2 sm:p-4 animate-fade-in">
<div className="bg-white w-full max-w-6xl rounded-2xl shadow-2xl border border-slate-200 overflow-hidden my-auto flex flex-col max-h-[92vh]">
{/* Top Header Controls */}
<div className="bg-[#1f2937] text-white px-6 py-3.5 flex items-center justify-between border-b border-slate-700 shrink-0">
<button
onClick={() => setActiveTenderDetail(null)}
className="flex items-center gap-2 text-xs font-semibold text-slate-300 hover:text-white transition-colors bg-slate-800 px-3 py-1.5 rounded-lg border border-slate-700"
>
<ArrowLeft className="w-4 h-4" />
<span>Listeye Geri Dön</span>
</button>
<div className="flex items-center gap-4 text-xs">
<span className="text-slate-400">İnceleyen: <strong className="text-white">{userProfile.name}</strong></span>
<button
onClick={() => toggleTrackTender(tender.id)}
className={`flex items-center gap-1.5 font-bold px-3 py-1.5 rounded-lg text-xs transition-colors ${
tender.takipte ? 'bg-amber-400 text-slate-900' : 'bg-slate-700 text-white hover:bg-slate-600'
}`}
>
<Star className={`w-4 h-4 ${tender.takipte ? 'fill-slate-900' : ''}`} />
<span>{tender.takipte ? 'Takipte' : 'Takip Et'}</span>
</button>
<button
onClick={() => setActiveTenderDetail(null)}
className="text-slate-400 hover:text-white p-1"
>
<X className="w-6 h-6" />
</button>
</div>
</div>
{/* Scrollable Container */}
<div className="overflow-y-auto p-6 space-y-6 flex-1">
{/* Main Title Header */}
<div className="space-y-2 border-b border-slate-200 pb-4">
<div className="flex items-center gap-2 flex-wrap">
<span className="bg-amber-500 text-white font-extrabold text-xs px-3 py-1 rounded-md">
{tender.alimTuru}
</span>
<span className="bg-blue-50 text-blue-700 border border-blue-200 font-bold text-xs px-3 py-1 rounded-md">
İKN: {tender.ikn}
</span>
{tender.aciliyetBadge && (
<span className="bg-red-500 text-white font-bold text-xs px-2.5 py-1 rounded-md">
{tender.aciliyetBadge}
</span>
)}
<span className="text-xs text-slate-500 ml-auto">Ekleme: {tender.eklenmeZamani}</span>
</div>
<h1 className="text-xl sm:text-2xl font-black text-slate-900 leading-snug">
{tender.baslik}
</h1>
</div>
{/* Metadata Cards Grid */}
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
<div className="bg-slate-50 p-3 rounded-xl border border-slate-200 text-xs">
<span className="text-slate-400 font-medium block">Kurum Adı</span>
<span className="font-bold text-slate-900 truncate block mt-0.5" title={tender.kurum}>{tender.kurum}</span>
</div>
<div className="bg-slate-50 p-3 rounded-xl border border-slate-200 text-xs">
<span className="text-slate-400 font-medium block">İhale Tarihi & Saat</span>
<span className="font-bold text-blue-700 block mt-0.5">{tender.tarih} - {tender.saat}</span>
</div>
<div className="bg-slate-50 p-3 rounded-xl border border-slate-200 text-xs">
<span className="text-slate-400 font-medium block">Şehir / Bölge</span>
<span className="font-bold text-slate-900 block mt-0.5">{tender.sehir} ({tender.bolge})</span>
</div>
<div className="bg-slate-50 p-3 rounded-xl border border-slate-200 text-xs">
<span className="text-slate-400 font-medium block">Yaklaşık Maliyet</span>
<span className="font-bold text-emerald-700 block mt-0.5">
{tender.yaklasikMaliyet ? `${tender.yaklasikMaliyet.toLocaleString('tr-TR')} TL` : 'Gizli / Belirtilmemiş'}
</span>
</div>
</div>
{/* Navigation Tabs */}
<div className="flex items-center gap-2 border-b border-slate-200 overflow-x-auto pb-1">
{[
{ id: 'details', label: 'İhale Detayları', icon: FileText },
{ id: 'pdf_stamp', label: 'Birim Fiyat Cetveli (PDF & Kaşe)', icon: Stamp, badge: 'İnteraktif' },
{ id: 'ai_assistant', label: 'Yapay Zeka Asistanı', icon: Sparkles, badge: '%94 Uyum' },
{ id: 'checklist', label: 'Hazırlık Checklist', icon: CheckSquare },
].map(tab => {
const Icon = tab.icon;
const isActive = activeTab === tab.id;
return (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`flex items-center gap-2 px-4 py-2.5 rounded-lg text-xs font-bold transition-all whitespace-nowrap ${
isActive
? 'bg-blue-600 text-white shadow-xs'
: 'text-slate-600 hover:bg-slate-100'
}`}
>
<Icon className="w-4 h-4" />
<span>{tab.label}</span>
{tab.badge && (
<span className={`text-[10px] px-1.5 py-0.5 rounded-full font-extrabold ${
isActive ? 'bg-white/20 text-white' : 'bg-blue-100 text-blue-800'
}`}>
{tab.badge}
</span>
)}
</button>
);
})}
</div>
{/* Tab 1: İhale Detayları */}
{activeTab === 'details' && (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-6">
{/* Description & Terms */}
<div className="bg-slate-50 p-5 rounded-xl border border-slate-200 space-y-3">
<h3 className="font-bold text-sm text-slate-900 flex items-center gap-2">
<FileText className="w-4 h-4 text-blue-600" /> İhale Açıklaması & Teslimat Koşulları
</h3>
<p className="text-xs text-slate-700 leading-relaxed">{tender.aciklama}</p>
<div className="grid grid-cols-2 gap-4 pt-2 border-t border-slate-200 text-xs">
<div>
<span className="text-slate-400 block font-medium">Teslimat Süresi</span>
<span className="font-bold text-slate-800">{tender.teslimatSuresi}</span>
</div>
<div>
<span className="text-slate-400 block font-medium">Teslimat Yeri</span>
<span className="font-bold text-slate-800">{tender.teslimYeri}</span>
</div>
</div>
</div>
{/* Material Table */}
<div className="space-y-3">
<h3 className="font-bold text-sm text-slate-900">Malzeme / Kalem Listesi ({tender.items?.length || 0} Kalem)</h3>
<div className="border border-slate-200 rounded-xl overflow-hidden shadow-2xs">
<table className="w-full text-left text-xs">
<thead className="bg-slate-100 text-slate-700 font-bold border-b border-slate-200">
<tr>
<th className="p-3">#</th>
<th className="p-3">Malzeme Adı</th>
<th className="p-3">Miktar</th>
<th className="p-3">Tahmini Birim Fiyat</th>
<th className="p-3">Toplam Tutarlar</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-100">
{tender.items?.map((item, index) => (
<tr key={index} className="hover:bg-slate-50">
<td className="p-3 font-bold text-slate-400">{index + 1}</td>
<td className="p-3 font-bold text-slate-800">{item.ad}</td>
<td className="p-3 font-semibold text-slate-700">{item.miktar} {item.birim}</td>
<td className="p-3 font-mono text-slate-600">{item.birimFiyat ? `${item.birimFiyat} TL` : '—'}</td>
<td className="p-3 font-mono font-bold text-emerald-700">
{item.birimFiyat ? `${(item.birimFiyat * parseFloat(item.miktar)).toLocaleString('tr-TR')} TL` : '—'}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* Team Notes Area */}
<div className="bg-white p-5 rounded-xl border border-slate-200 space-y-4">
<h3 className="font-bold text-sm text-slate-900">Ekip Notları</h3>
<div className="space-y-2">
{savedNotes.map(n => (
<div key={n.id} className="bg-slate-50 p-3 rounded-lg border border-slate-200 text-xs">
<div className="flex justify-between font-bold text-slate-900">
<span>{n.author}</span>
<span className="text-slate-400 text-[10px] font-normal">{n.date}</span>
</div>
<p className="text-slate-700 mt-1">{n.text}</p>
</div>
))}
</div>
<form onSubmit={handleAddNote} className="flex gap-2">
<input
type="text"
value={noteText}
onChange={(e) => setNoteText(e.target.value)}
placeholder="Ekip arkadaşlarınıza not yazın..."
className="flex-1 bg-slate-50 border border-slate-300 rounded-lg px-3 py-2 text-xs"
/>
<button type="submit" className="bg-blue-600 hover:bg-blue-500 text-white font-bold px-4 py-2 rounded-lg text-xs flex items-center gap-1">
<Send className="w-3.5 h-3.5" /> Not Ekle
</button>
</form>
</div>
</div>
{/* Right Sidebar of Details: TCMB Kur & Calendar & Specs */}
<div className="space-y-6">
{/* TCMB Kur Farkı Calculator */}
<div className="bg-linear-to-br from-blue-900 to-slate-900 text-white p-5 rounded-xl space-y-4 shadow-md">
<div className="flex items-center justify-between border-b border-blue-800/80 pb-2">
<span className="font-bold text-xs uppercase tracking-wider flex items-center gap-1.5">
<Calculator className="w-4 h-4 text-blue-400" /> Kur Farkı Hesaplayıcı
</span>
<span className="text-[10px] bg-blue-500/30 text-blue-300 px-2 py-0.5 rounded font-bold">TCMB Canlı</span>
</div>
<div className="grid grid-cols-2 gap-2 text-xs font-semibold">
<div className="bg-white/10 p-2.5 rounded-lg border border-white/10">
<span className="text-slate-400 block text-[10px]">USD / TRY</span>
<span className="text-base font-black text-emerald-400">₺{usdRate}</span>
</div>
<div className="bg-white/10 p-2.5 rounded-lg border border-white/10">
<span className="text-slate-400 block text-[10px]">EUR / TRY</span>
<span className="text-base font-black text-blue-400">₺{eurRate}</span>
</div>
</div>
<div className="space-y-1">
<label className="text-[11px] text-slate-300 font-medium">Teklif Tutarı (TL)</label>
<input
type="number"
value={bidAmount}
onChange={(e) => setBidAmount(Number(e.target.value))}
className="w-full bg-white/10 border border-white/20 rounded-lg px-3 py-1.5 text-xs text-white"
/>
</div>
<div className="bg-blue-950/80 p-3 rounded-lg border border-blue-800 text-xs space-y-1">
<div className="flex justify-between text-slate-300">
<span>Dolar Karşılığı:</span>
<span className="font-bold text-white">${(bidAmount / usdRate).toFixed(2)}</span>
</div>
<div className="flex justify-between text-slate-300">
<span>Euro Karşılığı:</span>
<span className="font-bold text-white">€{(bidAmount / eurRate).toFixed(2)}</span>
</div>
</div>
</div>
{/* Downloads & Calendar */}
<div className="bg-white p-5 rounded-xl border border-slate-200 space-y-3">
<h4 className="font-bold text-xs uppercase tracking-wider text-slate-800">İhale Dosyaları & Takvim</h4>
<button
onClick={() => setActiveTab('pdf_stamp')}
className="w-full bg-blue-600 hover:bg-blue-500 text-white font-bold py-2.5 px-3 rounded-lg text-xs flex items-center justify-center gap-2 shadow-2xs"
>
<Download className="w-4 h-4" /> Birim Fiyat Cetveli (PDF Aç/Düzenle)
</button>
<button
onClick={handleExportICS}
className="w-full bg-slate-100 hover:bg-slate-200 text-slate-700 font-bold py-2.5 px-3 rounded-lg text-xs flex items-center justify-center gap-2 border border-slate-300"
>
<Calendar className="w-4 h-4 text-blue-600" /> Google / Outlook Takvime Ekle
</button>
</div>
</div>
</div>
)}
{/* Tab 2: PDF Birim Fiyat Cetveli & Kaşe Editörü */}
{activeTab === 'pdf_stamp' && (
<div className="space-y-4">
<div className="bg-amber-50 border border-amber-200 text-amber-900 p-4 rounded-xl text-xs flex items-center justify-between">
<div className="flex items-center gap-2 font-semibold">
<Stamp className="w-5 h-5 text-amber-600" />
<span>Teklif cetvelinizi doldurun ve Dijital Kaşenizi sürükleyerek belgenin altına yerleştirin.</span>
</div>
<button
onClick={() => {
import('../services/pdf').then(({ generateBidSheetPDF }) => {
generateBidSheetPDF(tender, { firma: userProfile.company, stamp: true });
});
}}
className="bg-amber-600 hover:bg-amber-500 text-white font-bold px-4 py-2 rounded-lg flex items-center gap-1.5 shadow-2xs"
>
<Download className="w-4 h-4" /> Kaşeli PDF İndir
</button>
</div>
{/* Interactive PDF Sheet Canvas Simulator */}
<div
onMouseMove={handleStampMouseMove}
onMouseUp={handleStampMouseUp}
className="bg-slate-200 p-6 rounded-2xl border border-slate-300 relative select-none min-h-[500px] flex justify-center"
>
{/* Paper sheet */}
<div className="bg-white w-full max-w-2xl p-8 rounded-lg shadow-xl border border-slate-300 relative space-y-6 text-slate-800">
<div className="text-center border-b-2 border-slate-800 pb-4 space-y-1">
<p className="font-extrabold text-sm uppercase">{tender.kurum}</p>
<p className="font-bold text-xs text-blue-900">BİRİM FİYAT TEKLİF CETVELİ — İKN: {tender.ikn}</p>
</div>
<table className="w-full text-left text-xs border border-slate-400">
<thead className="bg-slate-100 font-bold border-b border-slate-400">
<tr>
<th className="p-2 border-r border-slate-400">Sıra</th>
<th className="p-2 border-r border-slate-400">Malzeme Adı</th>
<th className="p-2 border-r border-slate-400">Miktar</th>
<th className="p-2 border-r border-slate-400">Birim Fiyat (TL)</th>
<th className="p-2">Toplam (TL)</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-300">
{tender.items?.map((item, idx) => (
<tr key={idx}>
<td className="p-2 border-r border-slate-400 font-bold text-center">{idx + 1}</td>
<td className="p-2 border-r border-slate-400 font-semibold">{item.ad}</td>
<td className="p-2 border-r border-slate-400">{item.miktar} {item.birim}</td>
<td className="p-2 border-r border-slate-400 bg-yellow-50 font-bold text-blue-900">
{item.birimFiyat || 150} TL
</td>
<td className="p-2 font-mono font-bold text-emerald-800">
{((item.birimFiyat || 150) * parseFloat(item.miktar)).toLocaleString('tr-TR')} TL
</td>
</tr>
))}
</tbody>
</table>
<div className="pt-12 text-right">
<p className="font-bold text-xs text-slate-800">{userProfile.company}</p>
<p className="text-[10px] text-slate-500">Yetkili İmza ve Kaşe Alanı</p>
</div>
{/* Draggable Stamp Element */}
<div
onMouseDown={handleStampMouseDown}
style={{ left: `${stampPos.x}px`, top: `${stampPos.y}px` }}
className="absolute cursor-grab active:cursor-grabbing border-2 border-dashed border-red-500 bg-red-500/10 p-3 rounded-lg text-center transform -rotate-6 shadow-md transition-shadow hover:shadow-lg select-none"
>
<div className="w-32 h-16 border-2 border-red-700 rounded flex flex-col items-center justify-center p-1 text-red-700 font-black text-[9px] uppercase tracking-tighter">
<span>{userProfile.company.slice(0, 25)}</span>
<span className="text-[8px] text-red-600 font-bold mt-0.5">MÜDÜR İMZA & KAŞE</span>
<span className="text-[7px] text-slate-500">2026-08-07 ONAYLI</span>
</div>
<span className="text-[9px] font-extrabold text-red-600 block mt-1">↕ Sürükleyip Bırakın</span>
</div>
</div>
</div>
</div>
)}
{/* Tab 3: AI Asistanı */}
{activeTab === 'ai_assistant' && (
<div className="space-y-6">
<div className="bg-linear-to-r from-blue-900 to-indigo-900 text-white p-6 rounded-2xl space-y-4 shadow-lg">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Sparkles className="w-6 h-6 text-amber-400" />
<div>
<h3 className="font-black text-lg">Yapay Zeka Teklif & Risk Değerlendirmesi</h3>
<p className="text-xs text-blue-200">Teknik şartname ve geçmiş ihale sonuçları analiz edildi.</p>
</div>
</div>
{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 || '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 != 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">
<span className="text-slate-300 text-xs font-semibold block">
{tender.gecerliTeklifSayisi != null || tender.teklifSayisi != null ? 'Katılan Firma' : 'Rekabet Verisi'}
</span>
<span className="text-lg font-black text-blue-300">
{tender.gecerliTeklifSayisi != null
? `${tender.gecerliTeklifSayisi} geçerli teklif`
: tender.teklifSayisi != null
? `${tender.teklifSayisi} teklif`
: 'Sonuçlanınca gelir'}
</span>
</div>
</div>
<div className="flex justify-end pt-2">
<button
onClick={() => setIsAiSpecAnalyzerOpen(true)}
className="bg-amber-400 hover:bg-amber-300 text-slate-950 font-black px-4 py-2.5 rounded-xl text-xs flex items-center gap-2 transition-colors shadow-md cursor-pointer"
>
<Sparkles className="w-4 h-4 text-slate-900" />
<span>⚡ Şartname Yükle & AI Analizi Başlat</span>
</button>
</div>
</div>
<TenderDocuments tender={tender} />
<div className="bg-white p-5 rounded-xl border border-slate-200 space-y-3">
<h4 className="font-bold text-sm text-slate-900">Kritik Yeterlik Şartları</h4>
<ul className="space-y-2 text-xs text-slate-700">
{tender.yeterlikKriterleri?.map((k, i) => (
<li key={i} className="flex items-center gap-2 bg-slate-50 p-2.5 rounded-lg border border-slate-200 font-medium">
<span className="w-2 h-2 rounded-full bg-blue-600"></span>
<span>{k}</span>
</li>
))}
</ul>
</div>
</div>
)}
{/* Tab 4: Readiness Checklist */}
{activeTab === 'checklist' && (
<div className="bg-white p-5 rounded-xl border border-slate-200 space-y-4">
<h3 className="font-bold text-sm text-slate-900">İhale Hazırlık Adımları</h3>
<div className="space-y-2 text-xs">
{[
'Birim fiyat cetveli kontrol edildi ve dolduruldu',
'İmza sirküleri ve yetki belgesi hazırlandı',
'ÜTS kayıtları ve SUT kodları doğrulandı',
'TCMB döviz kur riski hesaplandı',
'EKAP üzerinden teklif zarfı oluşturuldu'
].map((item, idx) => (
<label key={idx} className="flex items-center gap-3 p-3 bg-slate-50 hover:bg-slate-100 rounded-xl border border-slate-200 cursor-pointer font-semibold text-slate-800">
<input type="checkbox" className="w-4 h-4 accent-blue-600 rounded" />
<span>{item}</span>
</label>
))}
</div>
</div>
)}
</div>
</div>
</div>
);
};