fix: order new tenders by validated publication time
This commit is contained in:
@@ -5,7 +5,7 @@ import { Download, SlidersHorizontal, Layers, Loader2 } from 'lucide-react';
|
||||
import { createTenderWorkbook } from '../services/tenderWorkbook';
|
||||
import { getToken } from '../services/auth';
|
||||
import { useDeadlineClock } from '../hooks/useDeadlineClock';
|
||||
import { acikIhale, hizliFiltreGecer, GECMIS_FILTRELER, compareTenderDeadlines } from '../services/ihaleTarih';
|
||||
import { acikIhale, hizliFiltreGecer, GECMIS_FILTRELER, compareTenderDeadlines, compareTenderPublications } 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.
|
||||
@@ -72,8 +72,8 @@ export const TenderList = () => {
|
||||
|
||||
return true;
|
||||
}).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 === 'uyum') return (b.aiMatchScore ?? -1) - (a.aiMatchScore ?? -1) || compareTenderPublications(a,b);
|
||||
if (sortBy === 'newest') return compareTenderPublications(a,b);
|
||||
if (sortBy === 'urgent') return compareTenderDeadlines(a,b);
|
||||
if (sortBy === 'distant') return compareTenderDeadlines(a,b,-1);
|
||||
return 0;
|
||||
@@ -164,7 +164,7 @@ export const TenderList = () => {
|
||||
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"
|
||||
>
|
||||
<option value="uyum">Şirketime En Uyumlu</option>
|
||||
<option value="newest">En Yeni Eklenenler</option>
|
||||
<option value="newest">Yayın Tarihi: En Yeni</option>
|
||||
<option value="urgent">Tarihi Yaklaşanlar (Acil)</option>
|
||||
<option value="distant">Tarihi Uzak Olanlar</option>
|
||||
</select>
|
||||
@@ -179,6 +179,7 @@ export const TenderList = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{sortBy === 'newest' && <p className="text-xs text-slate-500">Yayın tarihi bilinmeyen kayıtlar sonda gösterilir. Aynı gün içinde saati bilinen kayıtlar önce gelir.</p>}
|
||||
{exportError && <p role="alert" className="text-sm text-red-700">{exportError}</p>}
|
||||
{/* Tender Cards List */}
|
||||
{gorunenTenders.length === 0 ? (
|
||||
|
||||
+31
-12
@@ -16,22 +16,41 @@ export const ihaleGunu = (v) => {
|
||||
return key ? new Date(key+'T00:00:00+03:00') : null;
|
||||
};
|
||||
|
||||
// Her biçimi "yyyy-aa-gg" dizesine indirger (karşılaştırma için).
|
||||
export const ilanTarihiISO = (t) => {
|
||||
const v = String(t?.ilanTarihi || '').trim();
|
||||
let m = /^(\d{4})-(\d{2})-(\d{2})/.exec(v);
|
||||
if (m) return `${m[1]}-${m[2]}-${m[3]}`;
|
||||
m = /^(\d{2})\.(\d{2})\.(\d{4})/.exec(v);
|
||||
if (m) return `${m[3]}-${m[2]}-${m[1]}`;
|
||||
return '';
|
||||
};
|
||||
// Publication metadata is distinct from the tender deadline.
|
||||
export function publicationInfo(t) {
|
||||
for (const value of [t?.yayinZamani,t?.ilanTarihi]) {
|
||||
const v=String(value || '').trim();
|
||||
const m=/^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,7}))?)?(Z|[+-]\d{2}:\d{2})?)?$/.exec(v);
|
||||
const tr=/^(\d{2})\.(\d{2})\.(\d{4})$/.exec(v);
|
||||
const key=m ? tenderDateKey({tarih:`${m[3]}.${m[2]}.${m[1]}`}) : tr ? tenderDateKey({tarih:v}) : null;
|
||||
if (!key) continue;
|
||||
if (!m?.[4]) return {dateKey:key,timestamp:null};
|
||||
if (+m[4]>23 || +m[5]>59 || +(m[6] || 0)>59) continue;
|
||||
// Offset-free Turkish source timestamps use Istanbul, never the browser timezone.
|
||||
const stamp=Date.parse(`${key}T${m[4]}:${m[5]}:${m[6] || '00'}${m[7] ? '.'+m[7].slice(0,3) : ''}${m[8] || '+03:00'}`);
|
||||
if (Number.isFinite(stamp)) return {dateKey:istanbulDateKey(new Date(stamp)),timestamp:stamp};
|
||||
}
|
||||
return {dateKey:null,timestamp:null};
|
||||
}
|
||||
export const ilanTarihiISO = t => publicationInfo(t).dateKey || '';
|
||||
export function compareTenderPublications(a,b) {
|
||||
const x=publicationInfo(a),y=publicationInfo(b);
|
||||
if (!x.dateKey || !y.dateKey) return x.dateKey ? -1 : y.dateKey ? 1 : 0;
|
||||
const day=y.dateKey.localeCompare(x.dateKey);
|
||||
if (day) return day;
|
||||
if (x.timestamp === null || y.timestamp === null) return x.timestamp !== null ? -1 : y.timestamp !== null ? 1 : 0;
|
||||
return y.timestamp-x.timestamp;
|
||||
}
|
||||
|
||||
const iso = istanbulDateKey;
|
||||
|
||||
export const bugunISO = () => iso(new Date());
|
||||
export const bugunISO = (now = new Date()) => iso(now);
|
||||
|
||||
// Bugün yayımlanan ilan. Sunucunun isYeni bayrağı esas; o yoksa ilan tarihine bakılır.
|
||||
export const bugunEklendi = (t) => Boolean(t?.isYeni) || (ilanTarihiISO(t) !== '' && ilanTarihiISO(t) === bugunISO());
|
||||
// Bugün yayımlanan ilan. Bilinen yayın tarihi esas; yalnız tarih yoksa kaynak bayrağı kullanılır.
|
||||
export const bugunEklendi = (t, now = new Date()) => {
|
||||
const day=ilanTarihiISO(t);
|
||||
return day ? day === bugunISO(now) : Boolean(t?.isYeni);
|
||||
};
|
||||
|
||||
// Önceki ziyaretten (ms) sonra yayımlanan ilan. Kayıt yoksa "bugün" kabul edilir.
|
||||
export const girisSonrasiEklendi = (t, oncekiGirisMs) => {
|
||||
|
||||
Reference in New Issue
Block a user