From 7701ce43e36b16221fe74639a41892004136b449 Mon Sep 17 00:00:00 2001 From: ht Date: Sun, 30 Aug 2026 16:57:01 +0300 Subject: [PATCH] feat: ihale listesi sayfalama yerine sonsuz kaydirma (10 bin kayitta 1000+ sayfa dugmesi de kalkti) --- src/components/TenderList.jsx | 92 +++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/src/components/TenderList.jsx b/src/components/TenderList.jsx index c0c35be..2c658af 100644 --- a/src/components/TenderList.jsx +++ b/src/components/TenderList.jsx @@ -1,7 +1,7 @@ -import React, { useState, useMemo } from 'react'; +import React, { useState, useMemo, useEffect, useRef, useCallback } from 'react'; import { useApp } from '../context/AppContext'; import { TenderCard } from './TenderCard'; -import { Download, SlidersHorizontal, Layers, ChevronLeft, ChevronRight } from 'lucide-react'; +import { Download, SlidersHorizontal, Layers, Loader2 } from 'lucide-react'; import confetti from 'canvas-confetti'; // İl adları kaynaklar arasında farklı yazılabiliyor (Ankara / ANKARA); @@ -23,8 +23,12 @@ export const TenderList = () => { } = useApp(); const [sortBy, setSortBy] = useState('newest'); // 'newest', 'urgent', 'distant' - const [currentPage, setCurrentPage] = useState(1); - const itemsPerPage = 10; + + // Sonsuz kaydırma: sayfa yerine aşağı indikçe liste büyür. + // (Sayfalama 10 bin kayıtta 1000+ sayfa düğmesi basıyordu.) + const SAYFA_ADIM = 20; + const [gosterilen, setGosterilen] = useState(SAYFA_ADIM); + const dipRef = useRef(null); // Filter logic const filteredTenders = useMemo(() => { @@ -66,8 +70,33 @@ export const TenderList = () => { }); }, [tenders, searchQuery, selectedCity, selectedAlimTuru, selectedSektorler, selectedCpvler, selectedKurumTipi, quickFilter, sortBy]); - const totalPages = Math.max(1, Math.ceil(filteredTenders.length / itemsPerPage)); - const paginatedTenders = filteredTenders.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage); + const gorunenTenders = filteredTenders.slice(0, gosterilen); + const dahaVar = gosterilen < filteredTenders.length; + + // Baştan başlama YALNIZCA filtre/sıralama değişiminde olmalı. filteredTenders + // dizisine bağlansaydı havuz her yenilendiğinde (10 dk) kullanıcı listenin + // başına fırlardı. + useEffect(() => { setGosterilen(SAYFA_ADIM); }, [ + searchQuery, selectedCity, selectedAlimTuru, selectedSektorler, + selectedCpvler, selectedKurumTipi, quickFilter, sortBy, + ]); + + const dahaGoster = useCallback(() => { + setGosterilen((n) => Math.min(n + SAYFA_ADIM, filteredTenders.length)); + }, [filteredTenders.length]); + + // Dipteki işaretçi görünür olunca yükle. IntersectionObserver yoksa + // (eski tarayıcı) aşağıdaki "Daha fazla göster" düğmesi devreye girer. + useEffect(() => { + const el = dipRef.current; + if (!el || !dahaVar || typeof IntersectionObserver === 'undefined') return; + const gozlemci = new IntersectionObserver( + (girisler) => { if (girisler[0]?.isIntersecting) dahaGoster(); }, + { rootMargin: '600px 0px' }, // ekrana girmeden önce yükle + ); + gozlemci.observe(el); + return () => gozlemci.disconnect(); + }, [dahaVar, dahaGoster]); const handleExportExcel = () => { confetti({ particleCount: 80, spread: 60, origin: { y: 0.6 } }); @@ -128,7 +157,7 @@ export const TenderList = () => { {/* Tender Cards List */} - {paginatedTenders.length === 0 ? ( + {gorunenTenders.length === 0 ? (

Arama kriterlerine uygun ihale bulunamadı

@@ -136,43 +165,34 @@ export const TenderList = () => {
) : (
- {paginatedTenders.map(tender => ( + {gorunenTenders.map(tender => ( ))}
)} - {/* Pagination Bar */} - {totalPages > 1 && ( -
- Sayfa {currentPage} / {totalPages} (Toplam {filteredTenders.length} Kayıt) -
- - {Array.from({ length: totalPages }).map((_, i) => ( + {/* Sonsuz kaydırma dibi — sayfa yok, aşağı indikçe dolar */} + {filteredTenders.length > 0 && ( +
+ {dahaVar ? ( + <> +
+ + {gorunenTenders.length.toLocaleString('tr-TR')} / {filteredTenders.length.toLocaleString('tr-TR')} ihale gösteriliyor +
+ {/* Gözlemci çalışmazsa elle yükleme yolu açık kalsın */} - ))} - -
+ + ) : ( +

+ Tüm kayıtlar gösterildi — {filteredTenders.length.toLocaleString('tr-TR')} ihale +

+ )}
)}