fix: ust serit tiklaninca donuyordu — Kanban havuzdaki tum ihaleleri (8 bin+ kart) ciziyordu; artik yalnizca takipteki/kolona tasinan ihaleler, sekme gecisi transition ile aninda vurgulaniyor

- KanbanBoard: sunucu her ilana varsayilan 'incelenecek' verdigi icin bos pano 8.372 kart basiyordu; yalnizca takipte veya kolona tasinmis ihaleler kaliyor
- TopNavigation: useTransition + spinner; agir sekmelerde tiklama karsiliksiz kalmiyor
- sunucu: 'yeni liste eskisinden kucukse alma' kurali havuzu 30 Agustos zirvesinde dondurmustu (gunlerce yeni ilan yok); eksiksiz inen liste her zaman devrede
- sunucu: isYeni/bugun eklenen UTC-TR gun farkindan hep 0'di; Europe/Istanbul gunune gore ve her yanitta tazeleniyor (eklenmeZamani da donmuyor)
- ust kartlar: 'bugun eklenenler' tum ilanlari sayiyordu ('once' metnine bakiyordu), 'son giristen beri' sabit 14'tu; sayimlar liste filtresiyle ayni olcut (ihaleTarih.js), arsiv/sonuclanan filtreleri 'sadece acik' kapisina takilmiyor

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-02 13:02:40 +03:00
co-authored by Claude Fable 5.1
parent 3eb0f91823
commit 920a147126
9 changed files with 226 additions and 56 deletions
+22 -5
View File
@@ -1,10 +1,23 @@
import React, { useRef, useState, useEffect, useCallback } from 'react';
import React, { useRef, useState, useEffect, useCallback, useTransition } from 'react';
import { useApp } from '../context/AppContext';
import { Newspaper, Trophy, CalendarDays, FileCheck2, Calculator, TrendingUp, LayoutGrid, Kanban, Radar, FolderKanban, BarChart3, Webhook, Smartphone, Cpu, ShieldAlert, Globe2, Gavel, CreditCard, ChevronLeft, ChevronRight } from 'lucide-react';
import { Newspaper, Trophy, CalendarDays, FileCheck2, Calculator, TrendingUp, LayoutGrid, Kanban, Radar, FolderKanban, BarChart3, Webhook, Smartphone, Cpu, ShieldAlert, Globe2, Gavel, CreditCard, ChevronLeft, ChevronRight, Loader2 } from 'lucide-react';
export const TopNavigation = () => {
const { activeTab, setActiveTab, isAdmin } = useApp();
// Ağır sekmeler (10 bin+ kayıtlı havuzda Kanban, analiz vb.) tıklamadan
// sonra saniyelerce hiçbir tepki vermiyordu — kullanıcı "tıklanmıyor" sanıyordu.
// Sekme değişimi geçiş (transition) olarak yapılır: tıklanan sekme ANINDA
// vurgulanır ve dönen simge gösterilir, ağır görünüm arka planda hazırlanır.
const [isPending, startTransition] = useTransition();
const [hedefTab, setHedefTab] = useState(null);
const sekmeSec = (id) => {
if (id === activeTab) return;
setHedefTab(id);
startTransition(() => setActiveTab(id));
};
const bekleyen = isPending ? hedefTab : null;
const navItems = [
{ id: 'list', label: 'Ana İhale Listesi', icon: LayoutGrid },
{ id: 'bulten', label: 'Günlük Bülten', icon: Newspaper },
@@ -90,19 +103,23 @@ export const TopNavigation = () => {
<div ref={seritRef} className="flex items-center gap-1 overflow-x-auto py-1 scrollbar-none scroll-smooth">
{navItems.map(item => {
const Icon = item.icon;
const isActive = activeTab === item.id;
const isActive = bekleyen ? bekleyen === item.id : activeTab === item.id;
const yukleniyor = bekleyen === item.id;
return (
<button
key={item.id}
data-tab={item.id}
onClick={() => setActiveTab(item.id)}
aria-busy={yukleniyor || undefined}
onClick={() => sekmeSec(item.id)}
className={`flex items-center gap-2 px-3.5 py-2 rounded-lg text-xs font-semibold whitespace-nowrap transition-all select-none ${
isActive
? 'bg-blue-50 text-blue-700 border border-blue-200 shadow-2xs'
: 'text-slate-600 hover:text-slate-900 hover:bg-slate-50'
}`}
>
<Icon className={`w-4 h-4 ${isActive ? 'text-blue-600' : 'text-slate-400'}`} />
{yukleniyor
? <Loader2 className="w-4 h-4 text-blue-600 animate-spin" />
: <Icon className={`w-4 h-4 ${isActive ? 'text-blue-600' : 'text-slate-400'}`} />}
<span>{item.label}</span>
{item.badge && (
<span className="bg-amber-100 text-amber-800 font-bold text-[10px] px-1.5 py-0.5 rounded-full border border-amber-200">