fix: align list expiry and date ordering with tender deadlines

This commit is contained in:
2026-09-06 09:18:41 +03:00
parent a87ee758bc
commit 9c7055a543
6 changed files with 64 additions and 28 deletions
+10 -10
View File
@@ -3,7 +3,8 @@ import { useApp } from '../context/AppContext';
import { TenderCard } from './TenderCard';
import { Download, SlidersHorizontal, Layers, Loader2 } from 'lucide-react';
import confetti from 'canvas-confetti';
import { acikIhale, hizliFiltreGecer, GECMIS_FILTRELER } from '../services/ihaleTarih';
import { useDeadlineClock } from '../hooks/useDeadlineClock';
import { acikIhale, hizliFiltreGecer, GECMIS_FILTRELER, compareTenderDeadlines } from '../services/ihaleTarih';
// İl adları kaynaklar arasında farklı yazılabiliyor (Ankara / ANKARA);
// filtre büyük-küçük harf ve Türkçe karakter duyarlılığına takılmasın.
@@ -35,8 +36,7 @@ export const TenderList = () => {
const [gosterilen, setGosterilen] = useState(SAYFA_ADIM);
const dipRef = useRef(null);
// Bugünün başlangıcı — "bugün ihalesi olan" listede kalsın.
const bugun = useMemo(() => { const d = new Date(); d.setHours(0, 0, 0, 0); return d; }, []);
const now = useDeadlineClock();
// Filter logic
const filteredTenders = useMemo(() => {
@@ -57,7 +57,7 @@ export const TenderList = () => {
// Geçmiş ihaleler: varsayılan olarak GİZLİ. Kullanıcı "geçmişi de göster"
// derse (onlyValidOnly=false) hepsi gelir. Tarihi okunamayan kayıt gizlenmez.
// Arşiv / sonuçlananlar gibi geçmişi hedefleyen hızlı filtrelerde kapı kapalı.
if (onlyValidOnly && !GECMIS_FILTRELER.has(quickFilter) && !acikIhale(tender, bugun)) return false;
if (onlyValidOnly && !GECMIS_FILTRELER.has(quickFilter) && !acikIhale(tender, now)) return false;
// Hızlı filtre (üst kartlar + sol menü) — ölçütler ihaleTarih.js'de tek yerde
if (!hizliFiltreGecer(tender, quickFilter, { favoriteKurumlar: favoriteKurumlar || [], oncekiGirisMs: oncekiGiris, uyumEsigi })) return false;
@@ -73,11 +73,11 @@ export const TenderList = () => {
}).sort((a, b) => {
if (sortBy === 'uyum') return (b.aiMatchScore ?? -1) - (a.aiMatchScore ?? -1) || b.id.localeCompare(a.id);
if (sortBy === 'newest') return b.id.localeCompare(a.id);
if (sortBy === 'urgent') return a.tarih.localeCompare(b.tarih);
if (sortBy === 'distant') return b.tarih.localeCompare(a.tarih);
if (sortBy === 'urgent') return compareTenderDeadlines(a,b);
if (sortBy === 'distant') return compareTenderDeadlines(a,b,-1);
return 0;
});
}, [tenders, searchQuery, kalemEslesen, uyumEsigi, selectedCity, selectedAlimTuru, selectedSektorler, selectedCpvler, selectedKurumTipi, quickFilter, sortBy, onlyValidOnly, bugun, favoriteKurumlar, oncekiGiris]);
}, [tenders, searchQuery, kalemEslesen, uyumEsigi, selectedCity, selectedAlimTuru, selectedSektorler, selectedCpvler, selectedKurumTipi, quickFilter, sortBy, onlyValidOnly, now, favoriteKurumlar, oncekiGiris]);
const gorunenTenders = filteredTenders.slice(0, gosterilen);
const dahaVar = gosterilen < filteredTenders.length;
@@ -148,7 +148,7 @@ export const TenderList = () => {
{/* Varsayılan: yalnızca ihale tarihi geçmemiş ilanlar */}
<label
className="flex items-center gap-1.5 text-xs font-semibold text-slate-700 cursor-pointer select-none whitespace-nowrap"
title="Kapalı: ihale tarihi geçmiş ilanlar da listelenir"
title="Süresi geçtiği bilinen, iptal edilen ve sonuçlanan kayıtlar gizlenir. Tarihi veya saati bilinmeyen kayıtlar ayrıca doğrulanmalıdır."
>
<input
type="checkbox"
@@ -156,10 +156,10 @@ export const TenderList = () => {
onChange={(e) => setOnlyValidOnly(e.target.checked)}
className="accent-blue-600"
/>
Sadece açık ihaleler
Süresi geçenleri gizle
</label>
<select
<select aria-label="İhale sıralaması"
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
className="bg-slate-50 border border-slate-300 rounded-lg px-3 py-1.5 text-xs font-semibold text-slate-700 focus:ring-2 focus:ring-blue-500"