feat: geçmiş veri motoru + gerçek AI + KİK kararları + TED + kırmızı bayrak + planlar
Roadmap'in 6 maddesi de gerçek çalışır halde:
1) Geçmiş veri motoru (EKAP v2)
- server/ekap-v2.mjs: AES-256-CBC imzalı EKAP v2 istemcisi (zero-dep),
ihale arama + sonuç ilanı parse (kazanan firma, sözleşme bedeli,
yaklaşık maliyet, teklif sayısı), TR firma adı normalize
- server/history-store.mjs: SQLite deposu (IKN+kısım anahtarlı, upsert)
- server/ekap-scan.mjs: tarih aralıklı artımlı tarayıcı (6 paralel)
- server/scheduler.mjs: sunucu içi periyodik tarama (SCAN_* env ile)
- /api/tenders artık geçmiş sonuçları da birleştiriyor → kazanan firma,
rakip ve kırmızı bayrak analizleri gerçek veriyle doluyor
2) Gerçek AI şartname analizi
- server/ai.mjs: 6 sağlayıcılı fallback zinciri (GLM/DeepSeek/Gemini/
Grok/GPT/Claude), JSON şemalı çıktı, uydurma yasak promptu
- pdfjs-dist ile tarayıcıda PDF metin çıkarma (dinamik import)
- AiSpecAnalyzerModal: sahte sonuç kaldırıldı, gerçek dosya + dürüst hata
3) KİK kurul kararları
- server/kik.mjs: EKAP v2 JSON API (Sec-1..6 imzalı), uyuşmazlık/
düzenleyici/mahkeme; karar tam metni (ayrı AES anahtarıyla URL)
- KikDecisions sekmesi: arama + takipteki idarelerden hızlı öneri
4) Fiyatlandırma + ödeme
- server/billing.mjs: Stripe Checkout (zero-dep, form-encoded)
- Pricing sekmesi: 3 plan, aylık/yıllık, yapılandırılmadıysa dürüst uyarı
5) TED (AB ihaleleri)
- server/ted.mjs: anonim TED v3 API, 3 mod (açık/tüm TR/AB'de kazanan TR)
- rate-limit korumalı (429 HTML gövdesi ele alınır), çok dilli alan çözümü
6) Kırmızı bayrak & şeffaflık
- analytics.js: redFlags (tek teklif, düşük kırım, tahmin üstü bedel,
aşırı düşük teklif, tedarikçi yoğunlaşması) + marketConcentration (HHI)
- RedFlags sekmesi: seviyeli uyarılar + yöntem şeffaflığı notu
This commit is contained in:
+19
@@ -23,10 +23,15 @@ import { PriceAnalysis } from './components/tools/PriceAnalysis';
|
||||
import { CompetitorRadar } from './components/tools/CompetitorRadar';
|
||||
import { DocumentVault } from './components/tools/DocumentVault';
|
||||
import { AnalyticsDashboard } from './components/tools/AnalyticsDashboard';
|
||||
import { RedFlags } from './components/tools/RedFlags';
|
||||
import { TedTenders } from './components/tools/TedTenders';
|
||||
import { Pricing } from './components/tools/Pricing';
|
||||
import { KikDecisions } from './components/tools/KikDecisions';
|
||||
import { ApiWebhooks } from './components/tools/ApiWebhooks';
|
||||
import { PwaSettings } from './components/tools/PwaSettings';
|
||||
import { AiModelSettings } from './components/tools/AiModelSettings';
|
||||
import { LoginPage } from './components/LoginPage';
|
||||
import { LandingPage } from './components/LandingPage';
|
||||
|
||||
const MainContent = () => {
|
||||
const { activeTab, isAdmin } = useApp();
|
||||
@@ -57,6 +62,10 @@ const MainContent = () => {
|
||||
{activeTab === 'rakip_radar' && <CompetitorRadar />}
|
||||
{activeTab === 'dokuman_deposu' && <DocumentVault />}
|
||||
{activeTab === 'analitik_dashboard' && <AnalyticsDashboard />}
|
||||
{activeTab === 'kirmizi_bayrak' && <RedFlags />}
|
||||
{activeTab === 'ted_eu' && <TedTenders />}
|
||||
{activeTab === 'kik_kararlari' && <KikDecisions />}
|
||||
{activeTab === 'planlar' && <Pricing />}
|
||||
{activeTab === 'api_webhooks' && <ApiWebhooks />}
|
||||
{activeTab === 'pwa_settings' && <PwaSettings />}
|
||||
{activeTab === 'ai_ayarlari' && isAdmin && <AiModelSettings />}
|
||||
@@ -72,6 +81,13 @@ const MainContent = () => {
|
||||
|
||||
const Gate = () => {
|
||||
const { authReady, isAuthenticated, handleLogin } = useApp();
|
||||
const [showLogin, setShowLogin] = React.useState(() => window.location.hash === '#giris');
|
||||
|
||||
React.useEffect(() => {
|
||||
const onHash = () => setShowLogin(window.location.hash === '#giris');
|
||||
window.addEventListener('hashchange', onHash);
|
||||
return () => window.removeEventListener('hashchange', onHash);
|
||||
}, []);
|
||||
|
||||
if (!authReady) {
|
||||
return (
|
||||
@@ -81,6 +97,9 @@ const Gate = () => {
|
||||
);
|
||||
}
|
||||
if (!isAuthenticated) {
|
||||
if (!showLogin) {
|
||||
return <LandingPage onGiris={() => { window.location.hash = '#giris'; setShowLogin(true); }} />;
|
||||
}
|
||||
return <LoginPage onLogin={handleLogin} />;
|
||||
}
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user