feat: İhaleist - Akıllı İhale Takip ve Analiz Platformu (Full PRD + 7 Enterprise Modül)

This commit is contained in:
2026-08-07 16:30:24 +03:00
commit ece74feefe
35 changed files with 7820 additions and 0 deletions
+180
View File
@@ -0,0 +1,180 @@
import React from 'react';
import { useApp } from '../../context/AppContext';
import { BarChart3, TrendingUp, Trophy, Target, MapPin, Building2, Award, ArrowUpRight, DollarSign } from 'lucide-react';
import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, PieChart, Pie, Cell } from 'recharts';
export const AnalyticsDashboard = () => {
const { tenders, userProfile } = useApp();
const monthlyData = [
{ month: 'Ocak', kazanim: 380000, katilim: 550000 },
{ month: 'Şubat', kazanim: 420000, katilim: 600000 },
{ month: 'Mart', kazanim: 510000, katilim: 720000 },
{ month: 'Nisan', kazanim: 490000, katilim: 680000 },
{ month: 'Mayıs', kazanim: 610000, katilim: 850000 },
{ month: 'Haziran', kazanim: 580000, katilim: 810000 },
{ month: 'Temmuz', kazanim: 410000, katilim: 590000 }
];
const pieData = [
{ name: 'Tıbbi Malzeme', value: 45, color: '#2563eb' },
{ name: 'Kırtasiye & Büro', value: 25, color: '#059669' },
{ name: 'Temizlik & Hijyen', value: 18, color: '#7c3aed' },
{ name: 'Bilişim & Donanım', value: 12, color: '#d97706' }
];
const cityHeatmap = [
{ city: 'Ankara', ihaleSayisi: 1420, ortalamaMaliyet: '₺240.000', yogunluk: 'Çok Yüksek (%88)', color: 'bg-red-500 text-white' },
{ city: 'Kayseri', ihaleSayisi: 850, ortalamaMaliyet: '₺180.000', yogunluk: 'Yüksek (%74)', color: 'bg-amber-500 text-white' },
{ city: 'İstanbul', ihaleSayisi: 2100, ortalamaMaliyet: '₺410.000', yogunluk: 'Çok Yüksek (%94)', color: 'bg-red-600 text-white' },
{ city: 'İzmir', ihaleSayisi: 980, ortalamaMaliyet: '₺210.000', yogunluk: 'Orta (%62)', color: 'bg-emerald-500 text-white' },
{ city: 'Antalya', ihaleSayisi: 640, ortalamaMaliyet: '₺165.000', yogunluk: 'Orta (%55)', color: 'bg-blue-500 text-white' }
];
return (
<div className="space-y-6 animate-fade-in">
{/* Header Banner */}
<div className="bg-linear-to-r from-slate-900 via-purple-950 to-indigo-900 text-white p-6 rounded-2xl shadow-lg border border-purple-800/40 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-2xl bg-purple-600 text-white flex items-center justify-center font-black shadow-md">
<BarChart3 className="w-6 h-6" />
</div>
<div>
<h2 className="font-extrabold text-xl">Analitik Dashboard & Fiyat Isı Haritası</h2>
<p className="text-xs text-purple-200 mt-0.5">{userProfile.company} firmasına özel kazanma oranı, ciro hedefleri ve il bazlı ihale yoğunluk analizi.</p>
</div>
</div>
</div>
{/* KPI Cards & Ciro Target */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div className="bg-white p-5 rounded-2xl border border-slate-200 shadow-xs space-y-2">
<span className="text-xs font-bold text-slate-500 uppercase tracking-wider block">Katıldığımız İhaleler</span>
<div className="flex items-center justify-between">
<span className="text-2xl font-black text-slate-900">34 İhale</span>
<div className="w-8 h-8 rounded-lg bg-blue-50 text-blue-600 flex items-center justify-center">
<Trophy className="w-4 h-4" />
</div>
</div>
</div>
<div className="bg-white p-5 rounded-2xl border border-slate-200 shadow-xs space-y-2">
<span className="text-xs font-bold text-slate-500 uppercase tracking-wider block">İhale Kazanma Oranımız</span>
<div className="flex items-center justify-between">
<span className="text-2xl font-black text-emerald-600">%68</span>
<span className="bg-emerald-100 text-emerald-800 font-extrabold text-[10px] px-2 py-0.5 rounded-full flex items-center gap-0.5">
<ArrowUpRight className="w-3 h-3" /> +%12
</span>
</div>
</div>
<div className="bg-white p-5 rounded-2xl border border-slate-200 shadow-xs space-y-2">
<span className="text-xs font-bold text-slate-500 uppercase tracking-wider block">Toplam Kazanılan Bedel</span>
<div className="flex items-center justify-between">
<span className="text-2xl font-black text-indigo-900">₺3.400.000</span>
<div className="w-8 h-8 rounded-lg bg-indigo-50 text-indigo-600 flex items-center justify-center">
<Award className="w-4 h-4" />
</div>
</div>
</div>
{/* Target Progress Card */}
<div className="bg-linear-to-br from-blue-900 to-indigo-900 text-white p-5 rounded-2xl shadow-xs space-y-2">
<div className="flex justify-between items-center text-xs font-bold">
<span className="text-blue-200 uppercase tracking-wider flex items-center gap-1">
<Target className="w-3.5 h-3.5 text-amber-300" /> 2026 Ciro Hedefi
</span>
<span className="text-amber-300 font-black">%68</span>
</div>
<span className="text-xl font-black text-white block">₺3.4M / ₺5.0M</span>
<div className="w-full bg-blue-950 rounded-full h-2 overflow-hidden border border-blue-700">
<div className="bg-amber-400 h-2 rounded-full" style={{ width: '68%' }} />
</div>
</div>
</div>
{/* Recharts Row */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Monthly Revenue Chart */}
<div className="lg:col-span-2 bg-white p-5 rounded-2xl border border-slate-200 shadow-xs space-y-4">
<h3 className="font-extrabold text-sm text-slate-900 flex items-center gap-2">
<TrendingUp className="w-4 h-4 text-blue-600" /> Aylık İhale Kazanım ve Teklif Hacmi (TL)
</h3>
<div className="h-64 w-full">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={monthlyData}>
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#f1f5f9" />
<XAxis dataKey="month" tick={{ fontSize: 11 }} />
<YAxis tick={{ fontSize: 10 }} width={60} tickFormatter={(val) => `₺${val/1000}k`} />
<Tooltip formatter={(value) => [`₺${value.toLocaleString('tr-TR')}`, '']} />
<Bar dataKey="katilim" fill="#94a3b8" name="Toplam Verilen Teklif" radius={[4, 4, 0, 0]} />
<Bar dataKey="kazanim" fill="#2563eb" name="Kazanılan İhale Hacmi" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
</div>
</div>
{/* Sector Distribution Pie */}
<div className="bg-white p-5 rounded-2xl border border-slate-200 shadow-xs space-y-4">
<h3 className="font-extrabold text-sm text-slate-900">Sektörel İhale Kazanım Dağılımı</h3>
<div className="h-48 w-full">
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie data={pieData} dataKey="value" nameKey="name" cx="50%" cy="50%" innerRadius={40} outerRadius={70} paddingAngle={4}>
{pieData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
<Tooltip formatter={(value) => [`%${value}`, 'Oran']} />
</PieChart>
</ResponsiveContainer>
</div>
<div className="space-y-1.5 pt-2">
{pieData.map(item => (
<div key={item.name} className="flex justify-between items-center text-xs font-semibold">
<span className="flex items-center gap-2">
<span className="w-2.5 h-2.5 rounded-full" style={{ backgroundColor: item.color }}></span>
<span>{item.name}</span>
</span>
<span className="font-bold text-slate-900">%{item.value}</span>
</div>
))}
</div>
</div>
</div>
{/* City Price Heatmap Section */}
<div className="bg-white p-6 rounded-2xl border border-slate-200 shadow-xs space-y-4">
<div className="flex items-center justify-between border-b border-slate-100 pb-3">
<div>
<h3 className="font-extrabold text-sm text-slate-900 flex items-center gap-2">
<MapPin className="w-4 h-4 text-red-600" /> Şehir & Kurum Bazlı İhale Yoğunluk Isı Haritası
</h3>
<p className="text-xs text-slate-500">Bölgelere göre ihale sayıları ve ortalama idare yaklaşık maliyet seviyeleri.</p>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-5 gap-3">
{cityHeatmap.map(item => (
<div key={item.city} className="bg-slate-50 p-4 rounded-xl border border-slate-200 space-y-2">
<div className="flex items-center justify-between">
<span className="font-extrabold text-sm text-slate-900">{item.city}</span>
<span className={`text-[9px] font-black px-2 py-0.5 rounded-full ${item.color}`}>
{item.yogunluk}
</span>
</div>
<p className="text-xs text-slate-600 font-medium">İhale Sayısı: <strong className="text-slate-900">{item.ihaleSayisi}</strong></p>
<p className="text-xs text-slate-600 font-medium">Ort. Bedel: <strong className="text-indigo-900">{item.ortalamaMaliyet}</strong></p>
</div>
))}
</div>
</div>
</div>
);
};