import React, { useState } from 'react'; import { MessageSquareText, ClipboardCheck, PenLine, Loader2, Copy, Upload } from 'lucide-react'; import { getToken } from '../services/auth'; import { listDocuments } from '../services/account'; /** * Teklif Asistanı sekmesi — üç araç (İhaleAB'den taşındı): * 1) Belgeye Sor: doküman/ilan metninde soru → [n] atıflı yanıt * 2) Taslağı Denetle: teklif taslağı × gereklilikler → karşılanıyor / eksik / belirsiz * 3) Taslak Üret: kapak / teknik / ticari / tam dosya (rakam uydurmaz, [DOLDURUN]) * Doküman metni sunucuda EKAP'tan alınır; yoksa buradan .txt/.pdf metni yapıştırılır. */ const post = async (url, body) => { const r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${getToken()}` }, body: JSON.stringify(body) }); const d = await r.json().catch(() => ({})); if (!r.ok || d.success === false) throw new Error(d.error || `HTTP ${r.status}`); return d; }; const ORNEKLER = ['Geçici teminat oranı ve süresi nedir?', 'Teslim süresi kaç gün?', 'Gecikme cezası ne kadar?', 'Hangi belgeler istenmiş?', 'Numune isteniyor mu?']; const DURUM = { karsilaniyor: ['Karşılanıyor', 'bg-emerald-100 text-emerald-800 border-emerald-200'], eksik: ['Eksik', 'bg-red-100 text-red-800 border-red-200'], belirsiz: ['Belirsiz', 'bg-amber-100 text-amber-800 border-amber-200'] }; export const TeklifAsistani = ({ tender }) => { const [arac, setArac] = useState('sor'); const [metin, setMetin] = useState(''); // isteğe bağlı: yapıştırılan doküman metni const [soru, setSoru] = useState(''); const [cevap, setCevap] = useState(null); const [taslak, setTaslak] = useState(''); const [denetim, setDenetim] = useState(null); const [tur, setTur] = useState('tam'); const [bolumler, setBolumler] = useState([]); const [mesgul, setMesgul] = useState(false); const [hata, setHata] = useState(null); const calistir = async (fn) => { setMesgul(true); setHata(null); try { await fn(); } catch (e) { setHata(e.message); } finally { setMesgul(false); } }; const sor = (q) => calistir(async () => { setCevap(await post('/api/ai/belge-sor', { ikn: tender.ikn, soru: q, text: metin || undefined, tender })); }); const denetle = () => calistir(async () => { setDenetim(await post('/api/ai/teklif-denetim', { ikn: tender.ikn, taslak, tender, text: metin || undefined })); }); const uret = () => calistir(async () => { const belgeler = await listDocuments().then((d) => (d.belgeler || []).map((b) => ({ ad: b.ad, kategori: b.kategori }))).catch(() => []); setBolumler((await post('/api/ai/teklif-taslak', { ikn: tender.ikn, tur, tender, belgeler, text: metin || undefined })).bolumler || []); }); const kopyala = (t) => navigator.clipboard?.writeText(t).catch(() => {}); const dosyaOku = async (f) => { if (!f) return; try { const { extractText } = await import('../services/pdfText'); const r = await extractText(f); setMetin(r.text || ''); } catch (e) { setHata('Dosya okunamadı: ' + e.message); } }; const Sekme = ({ id, icon: Icon, children }) => ( ); return (
Metin sağlanmazsa sunucu EKAP dokümanını / ilan metnini kullanır. Yanıtlar yalnızca belgeden; rakamlar aynen aktarılır, model uydurmaz.
{hata &&{hata}
} {arac === 'sor' && ({cevap.cevap}
{cevap.kaynaklar?.map((k) => ({k.alinti}
Kaynak: {cevap.kaynak}
}