diff --git a/server/dt-store.mjs b/server/dt-store.mjs index e4a3462..64b73cc 100644 --- a/server/dt-store.mjs +++ b/server/dt-store.mjs @@ -110,6 +110,7 @@ function mapDtRow(row) { brans: (det.bransKodlari || []).join(', ') || row.turu || 'Genel', kurumTipi: classifyKurum(kurum), eklenmeZamani: row.yayim_tarihi ? `Yayım: ${row.yayim_tarihi}` : '', + ilanTarihi: row.yayim_tarihi || '', isYeni: false, isLiveFeed: true, aciliyetBadge: null, diff --git a/server/history-store.mjs b/server/history-store.mjs index e3d493e..a256bbb 100644 --- a/server/history-store.mjs +++ b/server/history-store.mjs @@ -204,6 +204,7 @@ function rowToTender(r) { items, // Arayüzün beklediği alanlar (geçmiş kayıtta karşılığı yok — güvenli varsayılan) eklenmeZamani: 'arşivden', + ilanTarihi: r.ilan_tarihi || '', isYeni: false, aciliyetBadge: null, usul: r.ihale_tipi || 'İhale', diff --git a/server/index.js b/server/index.js index fc0e8b4..5785aef 100644 --- a/server/index.js +++ b/server/index.js @@ -150,6 +150,7 @@ function mapAd(ad) { brans: ihaleTuru || 'Genel', kurumTipi: classify(INSTITUTION_RULES, ad.advertiserName || '', 'Diğer Kamu Kurumları'), eklenmeZamani: relativeTimeTr(ad.publishStartDate), + ilanTarihi: ad.publishStartDate ? String(ad.publishStartDate).slice(0, 10) : '', isYeni: Boolean(publishedToday), isLiveFeed: true, aciliyetBadge, diff --git a/src/components/TenderCard.jsx b/src/components/TenderCard.jsx index 762665c..dabc1df 100644 --- a/src/components/TenderCard.jsx +++ b/src/components/TenderCard.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { useApp } from '../context/AppContext'; -import { Star, MapPin, Clock, Tag, Package, Building2, AlertTriangle, Sparkles } from 'lucide-react'; +import { Star, MapPin, Clock, Tag, Package, Building2, AlertTriangle, Sparkles, CalendarDays, Megaphone } from 'lucide-react'; export const TenderCard = ({ tender }) => { const { toggleTrackTender, setActiveTenderDetail, favoriteKurumlar, toggleFavoriteKurum } = useApp(); @@ -9,6 +9,18 @@ export const TenderCard = ({ tender }) => { const [day, monthYear] = tender.tarih ? tender.tarih.split('.') : ['01', '01.2026']; const monthYearFormatted = monthYear ? `${monthYear}` : '08.2026'; + // İlan (yayım) tarihi kaynaklara göre farklı biçimde geliyor: + // canlı akış ISO (2026-08-30), DT/arşiv gg.aa.yyyy. İkisini de gösterebilelim. + const ilanTarihiGoster = (() => { + const v = tender.ilanTarihi; + if (!v) return null; + if (/^\d{4}-\d{2}-\d{2}/.test(v)) { + const [y, a, g] = v.slice(0, 10).split('-'); + return `${g}.${a}.${y}`; + } + return v; + })(); + return (
@@ -17,7 +29,8 @@ export const TenderCard = ({ tender }) => { onClick={() => setActiveTenderDetail(tender)} className="bg-[#edf4ff] group-hover:bg-[#e2edff] text-blue-900 md:w-36 p-4 flex flex-col items-center justify-center shrink-0 border-b md:border-b-0 md:border-r border-blue-100 cursor-pointer select-none transition-colors" > - {day} + İhale + {day} {monthYearFormatted} {tender.saat} @@ -75,10 +88,30 @@ export const TenderCard = ({ tender }) => { {tender.sehir} - - - {tender.eklenmeZamani} - + {ilanTarihiGoster && ( + + + İlan: {ilanTarihiGoster} + + )} + {tender.tarih && ( + + + İhale: {tender.tarih}{tender.saat ? ` ${tender.saat}` : ''} + + )} + {tender.eklenmeZamani && !ilanTarihiGoster && ( + + + {tender.eklenmeZamani} + + )} # {tender.ikn} diff --git a/src/components/TenderList.jsx b/src/components/TenderList.jsx index 2c658af..9d94839 100644 --- a/src/components/TenderList.jsx +++ b/src/components/TenderList.jsx @@ -8,6 +8,14 @@ import confetti from 'canvas-confetti'; // filtre büyük-küçük harf ve Türkçe karakter duyarlılığına takılmasın. const normTr = (v) => String(v || '').trim().toLocaleUpperCase('tr-TR'); +// "gg.aa.yyyy" → Date. Ayrıştırılamayanı GEÇMİŞ SAYMAYIZ: tarihi belirsiz bir +// ihaleyi sessizce gizlemek, geçmiş bir ihaleyi göstermekten daha kötüdür. +const ihaleGunu = (v) => { + const m = /^(\d{2})\.(\d{2})\.(\d{4})/.exec(String(v || '').trim()); + if (!m) return null; + return new Date(Number(m[3]), Number(m[2]) - 1, Number(m[1])); +}; + export const TenderList = () => { const { tenders, @@ -19,6 +27,7 @@ export const TenderList = () => { selectedKurumTipi, quickFilter, onlyValidOnly, + setOnlyValidOnly, favoriteKurumlar } = useApp(); @@ -30,6 +39,9 @@ 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; }, []); + // Filter logic const filteredTenders = useMemo(() => { return tenders.filter(tender => { @@ -43,6 +55,13 @@ export const TenderList = () => { if (!matchTitle && !matchKurum && !matchIkn && !matchItems) return false; } + // 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. + if (onlyValidOnly) { + const gun = ihaleGunu(tender.tarih); + if (gun && gun < bugun) return false; + } + // Quick Filter if (quickFilter === 'favori_kurumlar' && !(favoriteKurumlar || []).includes((tender.kurum || '').trim())) return false; if (quickFilter === 'dogrudan_temin' && tender.alimTuru !== 'Doğrudan Temin') return false; @@ -68,7 +87,7 @@ export const TenderList = () => { if (sortBy === 'distant') return b.tarih.localeCompare(a.tarih); return 0; }); - }, [tenders, searchQuery, selectedCity, selectedAlimTuru, selectedSektorler, selectedCpvler, selectedKurumTipi, quickFilter, sortBy]); + }, [tenders, searchQuery, selectedCity, selectedAlimTuru, selectedSektorler, selectedCpvler, selectedKurumTipi, quickFilter, sortBy, onlyValidOnly, bugun]); const gorunenTenders = filteredTenders.slice(0, gosterilen); const dahaVar = gosterilen < filteredTenders.length; @@ -78,7 +97,7 @@ export const TenderList = () => { // başına fırlardı. useEffect(() => { setGosterilen(SAYFA_ADIM); }, [ searchQuery, selectedCity, selectedAlimTuru, selectedSektorler, - selectedCpvler, selectedKurumTipi, quickFilter, sortBy, + selectedCpvler, selectedKurumTipi, quickFilter, sortBy, onlyValidOnly, ]); const dahaGoster = useCallback(() => { @@ -136,6 +155,20 @@ export const TenderList = () => {
+ {/* Varsayılan: yalnızca ihale tarihi geçmemiş ilanlar */} + +