245 lines
12 KiB
React
245 lines
12 KiB
React
import React, { useState } from 'react';
|
||
import { useApp } from '../context/AppContext';
|
||
import { Package, Bot, Search, SlidersHorizontal, Gift, Bell, User, ChevronDown, CheckCircle, LogOut, Globe, Sparkles, RefreshCw } from 'lucide-react';
|
||
|
||
export const Header = () => {
|
||
const {
|
||
searchQuery,
|
||
setSearchQuery,
|
||
setIsDetailedSearchOpen,
|
||
setIsUrunAramaOpen,
|
||
setIsCompanyScannerOpen,
|
||
setIsAiSpecAnalyzerOpen,
|
||
userProfile,
|
||
notifications,
|
||
setActiveTab,
|
||
clearAllFilters,
|
||
isRefreshingLive,
|
||
refreshLiveEKAPData,
|
||
authUser,
|
||
isAdmin,
|
||
plan,
|
||
handleLogout
|
||
} = useApp();
|
||
|
||
// Rozet SATIN ALINAN aboneliği gösterir. Yönetici hesapları her özelliğe
|
||
// erişir ama bu bir abonelik değildir; ikisini karıştırmamak için ayrı yazılır.
|
||
const planAdi = plan?.abonelikVar ? plan.abonelikAdi : (plan?.yonetici ? 'Yönetici' : 'Ücretsiz');
|
||
|
||
const [showNotifications, setShowNotifications] = useState(false);
|
||
const [showUserMenu, setShowUserMenu] = useState(false);
|
||
|
||
const handleSearchSubmit = (e) => {
|
||
e.preventDefault();
|
||
setActiveTab('list');
|
||
};
|
||
|
||
return (
|
||
<header className="bg-[#1f2937] text-white border-b border-slate-700 sticky top-0 z-40 shadow-sm">
|
||
<div className="max-w-[1600px] mx-auto px-3 sm:px-4 py-2 xl:py-0 xl:h-16 flex flex-wrap xl:flex-nowrap items-center justify-between gap-2 sm:gap-4">
|
||
|
||
{/* Logo */}
|
||
<div
|
||
onClick={() => { setActiveTab('list'); clearAllFilters(); }}
|
||
className="flex shrink-0 items-center gap-1.5 sm:gap-2.5 cursor-pointer select-none group"
|
||
>
|
||
<div className="w-8 h-8 sm:w-10 sm:h-10 rounded-xl bg-blue-600 flex items-center justify-center shadow-md group-hover:bg-blue-500 transition-colors">
|
||
<Bot className="w-6 h-6 text-white" />
|
||
</div>
|
||
<div className="flex flex-col">
|
||
<span className="font-black text-xl sm:text-2xl tracking-tight text-white flex items-center gap-1">
|
||
İhale<span className="text-blue-400 font-extrabold">ist</span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Search Bar */}
|
||
<form onSubmit={handleSearchSubmit} className="order-3 xl:order-none w-full xl:w-auto xl:flex-1 min-w-0 xl:max-w-2xl flex items-center gap-2">
|
||
<div className="relative flex-1 min-w-0">
|
||
<input
|
||
type="text"
|
||
value={searchQuery}
|
||
onChange={(e) => setSearchQuery(e.target.value)}
|
||
placeholder="İhale, kurum veya İKN no ile arayın..."
|
||
className="w-full bg-[#374151] text-white placeholder-slate-400 pl-4 pr-10 py-2 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 border border-slate-600 transition-all"
|
||
/>
|
||
{searchQuery && (
|
||
<button
|
||
type="button"
|
||
onClick={() => setSearchQuery('')}
|
||
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white text-xs"
|
||
>
|
||
✕
|
||
</button>
|
||
)}
|
||
</div>
|
||
<button
|
||
type="submit"
|
||
className="bg-slate-700 hover:bg-slate-600 text-white font-medium px-4 py-2 rounded-lg text-sm flex items-center gap-1.5 transition-colors border border-slate-600 shrink-0"
|
||
>
|
||
<Search className="w-4 h-4" />
|
||
<span className="font-semibold text-xs tracking-wider">ARA</span>
|
||
</button>
|
||
<button
|
||
type="button"
|
||
data-product-search-trigger="true"
|
||
onClick={() => setIsUrunAramaOpen(true)}
|
||
title="Ürün Arama — ürün adınızı ihale dokümanlarının içinde arar"
|
||
className="bg-amber-400 hover:bg-amber-300 text-slate-950 font-black px-3 py-2 rounded-lg text-xs flex items-center gap-1.5 transition-colors shrink-0"
|
||
>
|
||
<Package className="w-4 h-4" />
|
||
<span className="hidden sm:inline tracking-wide">ÜRÜN ARA</span>
|
||
</button>
|
||
<button
|
||
type="button"
|
||
onClick={() => setIsDetailedSearchOpen(true)}
|
||
title="Detaylı İhale Arama"
|
||
className="bg-blue-600 hover:bg-blue-500 text-white p-2 rounded-lg text-sm flex items-center justify-center transition-colors shadow-sm shrink-0"
|
||
>
|
||
<SlidersHorizontal className="w-4 h-4" />
|
||
</button>
|
||
</form>
|
||
|
||
{/* Right Action Icons */}
|
||
<div className="ml-auto flex items-center gap-1 sm:gap-3 shrink-0">
|
||
|
||
{/* Real Live EKAP Mode Badge */}
|
||
<button
|
||
onClick={refreshLiveEKAPData}
|
||
disabled={isRefreshingLive}
|
||
className="bg-emerald-600 hover:bg-emerald-500 text-white font-extrabold px-3 py-1.5 rounded-lg text-xs hidden md:hidden md:flex items-center gap-1.5 shadow-xs transition-colors shrink-0 disabled:opacity-50"
|
||
title="Canlı EKAP ve Doğrudan Temin Verilerini Anlık Güncelleyin"
|
||
>
|
||
<RefreshCw className={`w-3.5 h-3.5 text-white ${isRefreshingLive ? 'animate-spin' : ''}`} />
|
||
<span className="hidden lg:inline">{isRefreshingLive ? 'EKAP Çekiliyor...' : '🔴 CANLI EKAP VERİSİ'}</span>
|
||
</button>
|
||
|
||
{/* AI Şartname Analizi */}
|
||
<button
|
||
onClick={() => setIsAiSpecAnalyzerOpen(true)}
|
||
className="bg-purple-600 hover:bg-purple-500 text-white font-extrabold px-3 py-1.5 rounded-lg text-xs flex items-center gap-1.5 shadow-xs transition-colors shrink-0"
|
||
title="Teknik şartnameyi AI ile analiz edin"
|
||
>
|
||
<Sparkles className="w-4 h-4 text-amber-300" />
|
||
<span className="hidden md:inline">AI Şartname Analizi</span>
|
||
</button>
|
||
|
||
{/* Company Web Scanner Button */}
|
||
<button
|
||
onClick={() => setIsCompanyScannerOpen(true)}
|
||
className="bg-blue-600 hover:bg-blue-500 text-white font-bold px-3 py-1.5 rounded-lg text-xs hidden md:flex items-center gap-1.5 shadow-xs transition-colors shrink-0"
|
||
title="Web Sitenizi Tarayın & AI İhale Profiline İşleyin"
|
||
>
|
||
<Globe className="w-4 h-4 text-blue-200" />
|
||
<span className="hidden sm:inline">Web Siteni Tara (AI)</span>
|
||
</button>
|
||
|
||
{/* Trial Badge */}
|
||
<div className="bg-amber-400 text-slate-900 font-bold px-3 py-1.5 rounded-lg text-xs flex items-center gap-1.5 shadow-sm">
|
||
<Gift className="w-4 h-4 text-slate-900" />
|
||
<span>{userProfile.trialDaysLeft} gün</span>
|
||
</div>
|
||
|
||
{/* Notifications Dropdown */}
|
||
<div className="relative">
|
||
<button
|
||
aria-label="Bildirimler"
|
||
onClick={() => setShowNotifications(!showNotifications)}
|
||
className="relative p-2 text-slate-300 hover:text-white hover:bg-slate-700 rounded-lg transition-colors"
|
||
>
|
||
<Bell className="w-5 h-5" />
|
||
{notifications.some(n => !n.read) && (
|
||
<span className="absolute top-1 right-1 w-2.5 h-2.5 bg-blue-500 rounded-full ring-2 ring-[#1f2937]" />
|
||
)}
|
||
</button>
|
||
|
||
{showNotifications && (
|
||
<div className="absolute right-0 mt-2 w-80 bg-white text-slate-800 rounded-xl shadow-xl border border-slate-200 py-2 z-50 animate-fade-in">
|
||
<div className="px-4 py-2 border-b border-slate-100 flex items-center justify-between">
|
||
<h4 className="font-bold text-sm">Bildirimler</h4>
|
||
<span className="text-xs text-blue-600 cursor-pointer hover:underline">Tümünü Okundu İşaretle</span>
|
||
</div>
|
||
<div className="max-h-64 overflow-y-auto divide-y divide-slate-100">
|
||
{notifications.map(n => (
|
||
<div key={n.id} className="p-3 hover:bg-slate-50 transition-colors cursor-pointer text-xs">
|
||
<div className="font-semibold text-slate-900 flex justify-between">
|
||
<span>{n.title}</span>
|
||
<span className="text-slate-400 font-normal text-[10px]">{n.time}</span>
|
||
</div>
|
||
<p className="text-slate-600 mt-1 leading-relaxed">{n.text}</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* User Profile */}
|
||
<div className="relative">
|
||
<button
|
||
aria-label="Hesap menüsü"
|
||
onClick={() => setShowUserMenu(!showUserMenu)}
|
||
className="bg-slate-700 hover:bg-slate-600 text-white px-3 py-1.5 rounded-lg text-xs font-semibold flex items-center gap-2 transition-colors border border-slate-600"
|
||
>
|
||
{authUser?.picture ? (
|
||
<img src={authUser.picture} alt="" className="w-6 h-6 rounded-full object-cover" referrerPolicy="no-referrer" />
|
||
) : (
|
||
<div className="w-6 h-6 rounded-full bg-blue-600 flex items-center justify-center text-white font-bold text-xs">
|
||
{(authUser?.name || userProfile.username).charAt(0).toUpperCase()}
|
||
</div>
|
||
)}
|
||
<span className="hidden sm:inline">{(authUser?.name || userProfile.username).split(' ')[0]}</span>
|
||
<ChevronDown className="w-3.5 h-3.5 text-slate-400" />
|
||
</button>
|
||
|
||
{showUserMenu && (
|
||
<div className="absolute right-0 mt-2 w-60 bg-white text-slate-800 rounded-xl shadow-xl border border-slate-200 py-2 z-50 animate-fade-in">
|
||
<div className="px-4 py-2 border-b border-slate-100">
|
||
<p className="font-bold text-sm text-slate-900 flex items-center gap-1.5">
|
||
{authUser?.name || userProfile.name}
|
||
{isAdmin && <span className="text-[9px] font-black px-1.5 py-0.5 rounded bg-indigo-600 text-white">ADMIN</span>}
|
||
</p>
|
||
<p className="text-xs text-slate-500 truncate">{authUser?.email || userProfile.company}</p>
|
||
</div>
|
||
<div className="py-1 text-xs">
|
||
<button
|
||
onClick={() => { setShowUserMenu(false); setActiveTab('list'); }}
|
||
className="w-full text-left px-4 py-2 hover:bg-slate-50 flex items-center gap-2 text-slate-700"
|
||
>
|
||
<User className="w-4 h-4 text-slate-400" /> Firma Bilgileri & Üyeler
|
||
</button>
|
||
<button
|
||
onClick={() => { setShowUserMenu(false); setActiveTab('planlar'); }}
|
||
className="w-full text-left px-4 py-2 hover:bg-slate-50 flex items-center gap-2 text-slate-700"
|
||
>
|
||
<Gift className="w-4 h-4 text-amber-500" />
|
||
<span>Abonelik & Planlar</span>
|
||
<span className="ml-auto text-[10px] font-bold px-1.5 py-0.5 rounded-full bg-slate-100 text-slate-600 border border-slate-200">
|
||
{planAdi}
|
||
</span>
|
||
</button>
|
||
<button
|
||
onClick={() => { setShowUserMenu(false); setActiveTab('pwa_settings'); }}
|
||
className="w-full text-left px-4 py-2 hover:bg-slate-50 flex items-center gap-2 text-slate-700"
|
||
>
|
||
<CheckCircle className="w-4 h-4 text-slate-400" /> Bildirim Tercihleri
|
||
</button>
|
||
</div>
|
||
<div className="border-t border-slate-100 pt-1 text-xs">
|
||
<button
|
||
onClick={handleLogout}
|
||
className="w-full text-left px-4 py-2 text-red-600 hover:bg-red-50 flex items-center gap-2"
|
||
>
|
||
<LogOut className="w-4 h-4" /> Çıkış Yap
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</header>
|
||
);
|
||
};
|