Files
ihaleist/src/components/TenderDetailModal.jsx
T

542 lines
29 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, useEffect, useRef, useId } from 'react';
import { useApp } from '../context/AppContext';
import { BidPackageBuilder } from './BidPackageBuilder';
import { TenderDocuments } from './TenderDocuments';
import { TeklifAsistani } from './TeklifAsistani';
import { TeklifCetveliKalemleri } from './TeklifCetveliKalemleri';
import {
X, Star, Share2, Calendar, MapPin, Building2, Tag, FileText, CheckSquare,
DollarSign, Calculator, Download, Sparkles, AlertTriangle, ShieldCheck,
Send, Stamp, ArrowLeft, ExternalLink, Printer, PenLine } from 'lucide-react';
import { acknowledgeNoteDraft, editNoteDraft } from '../services/noteDrafts';
import { tenderStateKey } from '../services/tenderState';
import { createTenderICS } from '../services/tenderCalendar';
export const TenderDetailModal = () => {
const { activeTenderDetail, setActiveTenderDetail, toggleTrackTender, userProfile, setIsAiSpecAnalyzerOpen, gorevAc, gorevKontrol, aiAnalysisResults, tenders, mutateTender, savingCount, saveError, authUser } = useApp();
const dialogRef = useRef(null);
const dialogTitleId = useId();
const isOpen = Boolean(activeTenderDetail);
useEffect(() => {
if (!isOpen) return;
const opener = document.activeElement;
const root = dialogRef.current;
root?.querySelector('button')?.focus();
return () => { if (opener?.isConnected) opener.focus(); };
}, [isOpen]);
const handleDialogKey = e => {
if (e.defaultPrevented || e.target.closest('[role="dialog"]') !== dialogRef.current) return;
if (e.key === 'Escape') {
e.preventDefault(); e.stopPropagation(); setActiveTenderDetail(null); return;
}
if (e.key !== 'Tab') return;
const focusable = [...dialogRef.current.querySelectorAll('button, a[href], input, select, textarea, [tabindex]')]
.filter(el => el.tabIndex >= 0 && !el.disabled && el.getClientRects().length && !el.closest('[inert]'));
const first = focusable[0], last = focusable.at(-1);
if (!first) { e.preventDefault(); dialogRef.current.focus(); }
else if (e.shiftKey && (document.activeElement === first || document.activeElement === dialogRef.current)) {
e.preventDefault(); last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault(); first.focus();
}
};
const [activeTab, setActiveTab] = useState('details'); // 'details', 'pdf_stamp', 'ai_assistant', 'checklist', 'kurum_tenders'
const noteOwner = authUser?.email || '';
const [noteDrafts, setNoteDrafts] = useState(() => ({ owner: noteOwner, drafts: {} }));
// Discard private drafts on account changes, before rendering another account.
if (noteDrafts.owner !== noteOwner) setNoteDrafts({ owner: noteOwner, drafts: {} });
const noteKey = tenderStateKey(activeTenderDetail);
const noteDraft = noteDrafts.owner === noteOwner ? noteDrafts.drafts[noteKey] : undefined;
const noteText = noteDraft?.text || '';
const setNoteText = text => setNoteDrafts(state => editNoteDraft(state, noteOwner, noteKey, text));
const [actionError, setActionError] = useState(null);
// Kur Farkı Calculator State
const [bidAmount, setBidAmount] = useState(15000);
const [fx, setFx] = useState(null);
const [fxError, setFxError] = useState(null);
useEffect(() => {
if (!activeTenderDetail) return;
let cancelled = false;
fetch('/api/exchange-rates').then(r => r.json()).then(d => {
if (cancelled) return;
if (!d.success) throw new Error(d.error);
setFx(d); setFxError(d.refreshError || null);
}).catch(e => { if (!cancelled) setFxError(e.message); });
return () => { cancelled = true; };
}, [activeTenderDetail?.id]);
const usdRate = fx?.rates?.USD;
const eurRate = fx?.rates?.EUR;
if (!activeTenderDetail) return null;
// Havuzdaki güncel kayıt: takip/görev değişince düğme etiketleri de değişsin.
const tender = (activeTenderDetail && tenders.find((t) => t.id === activeTenderDetail.id)) || activeTenderDetail;
const savedNotes = tender.notes || [];
const handleAddNote = async (e) => {
e.preventDefault();
if (!noteText.trim()) return;
const saved = await mutateTender(tender.id, {notes: [...savedNotes, {
id: Date.now(),
author: userProfile.name,
text: noteText.trim(),
date: new Date().toLocaleString('tr-TR')
}]});
if (saved) setNoteDrafts(state => acknowledgeNoteDraft(state, noteOwner, noteKey, noteDraft));
};
const handleExportICS = () => {
let icsData;
try { icsData = createTenderICS(tender); setActionError(null); }
catch (e) { setActionError(e.message); return; }
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);
setTimeout(() => URL.revokeObjectURL(link.href), 1000);
};
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 ref={dialogRef} role="dialog" aria-modal="true" aria-labelledby={dialogTitleId} tabIndex={-1} onKeyDown={handleDialogKey} 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]">
{(actionError || saveError) && <p role="alert" className="p-3 bg-red-50 text-red-900">{actionError || saveError}</p>}
{savingCount > 0 && <p role="status" className="p-2 bg-blue-50">Kaydediliyor…</p>}
{/* 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">
<button type="button" disabled={savingCount > 0} aria-pressed={Boolean(tender.incelendi)}
onClick={() => mutateTender(tender.id,{incelendi:!tender.incelendi})}
className="text-xs px-3 py-1.5 rounded-lg border border-slate-500 disabled:opacity-50">
{tender.incelendi ? 'İncelendi — yeniden aç' : 'İncelendi olarak işaretle'}
</button>
<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>
{/* İhaleden göreve: teslim tarihi ihale saati; sonuç yayımlanınca bildirim */}
{tender.gorev ? (
<span className="flex items-center gap-1.5 font-bold px-3 py-1.5 rounded-lg text-xs bg-emerald-500/20 text-emerald-200 border border-emerald-400/40"
title={`Hazırlık görevi açık · teslim: ${tender.gorev.teslim || '—'}`}>
✓ Görev açık{tender.gorev.teslim ? ` · ${tender.gorev.teslim}` : ''}
</span>
) : (
<button
type="button"
onClick={() => gorevAc(tender.id, { kontrolListesi: aiAnalysisResults?.documentChecklist || [] })}
title="Hazırlık görevi aç: teslim tarihi ihale saati olur, pano 'Teklif Hazırlanıyor' kolonuna düşer, sonuç yayımlanınca bildirim gelir"
className="flex items-center gap-1.5 font-bold px-3 py-1.5 rounded-lg text-xs transition-colors bg-amber-400 text-slate-950 hover:bg-amber-300"
>
🗂 Hazırlık Görevi Aç
</button>
)}
<button
onClick={() => setActiveTenderDetail(null)}
aria-label="İhale detayını kapat"
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 id={dialogTitleId} 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: tender?.aiMatchScore != null ? `%${tender.aiMatchScore} Uyum` : undefined },
{ id: 'checklist', label: 'Hazırlık Checklist', icon: CheckSquare },
{ id: 'teklif_asistani', label: 'Teklif Asistanı', icon: PenLine, badge: 'AI' },
].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>
{tender.gorev?.kontrolListesi?.length > 0 && (
<div className="bg-amber-50 border border-amber-200 rounded-xl p-4 space-y-2">
<h3 className="font-bold text-sm text-slate-900">Hazırlık görevi — belge kontrol listesi</h3>
<ul className="space-y-1">
{tender.gorev.kontrolListesi.map((k, i) => (
<li key={i}>
<button type="button" onClick={() => gorevKontrol(tender.id, i)}
className={`text-xs text-left flex items-center gap-2 ${k.tamam ? 'line-through text-slate-400' : 'text-slate-800'}`}>
<span className={`w-3.5 h-3.5 rounded border ${k.tamam ? 'bg-emerald-500 border-emerald-500' : 'border-slate-400'}`} />
{k.ad}
</button>
</li>
))}
</ul>
</div>
)}
{/* Ortak havuzdan teklif cetveli kalemleri */}
<TeklifCetveliKalemleri ikn={tender.ikn} />
{/* Material Table */}
{tender.items?.length > 0 && (
<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)}
aria-label="Ekip notu"
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" disabled={savingCount > 0 || !noteText.trim()} className="disabled:opacity-50 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 döviz satış</span>
</div>
{fx && <p className="text-[11px]"><a href={fx.source} target="_blank" rel="noreferrer" className="underline">TCMB bülteni: {fx.bulletinDate}</a> · Alındı: {new Date(fx.fetchedAt).toLocaleString('tr-TR')}</p>}
{fxError && <p role="alert" className="text-xs text-amber-200">{fxError}</p>}
<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 ? `₺${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 ? `₺${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">{usdRate ? '$' + (bidAmount / usdRate).toFixed(2) : 'Kur bekleniyor'}</span>
</div>
<div className="flex justify-between text-slate-300">
<span>Euro Karşılığı:</span>
<span className="font-bold text-white">{eurRate ? '€' + (bidAmount / eurRate).toFixed(2) : 'Kur bekleniyor'}</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' && (
<BidPackageBuilder key={tender.ikn || tender.id} tender={tender}
results={aiAnalysisResults?.tenderKey === (tender.ikn || tender.id) ? aiAnalysisResults : null} />
)}
{/* 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">Analizi başlatarak işlenen kaynağı ve kontrol gerektiren alanları inceleyin.</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>
{/* Skorun nedeni: hangi profil terimi ihalenin neresinde geçiyor */}
{tender.uyumNedenleri?.length > 0 && (
<div className="flex flex-wrap gap-1.5 pt-1">
{tender.uyumNedenleri.map((n, i) => (
<span key={i} className="bg-white/10 border border-white/15 text-[11px] text-amber-100 px-2 py-0.5 rounded-lg">
<strong className="text-white">{n.terim}</strong> · {n.alan}
</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 5: Teklif Asistanı — belgeye sor / taslak denetimi / taslak üretimi */}
{activeTab === 'teklif_asistani' && <TeklifAsistani tender={tender} />}
{/* 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>
);
};