fix: guide EKAP human verification

This commit is contained in:
2026-09-15 17:41:51 +03:00
parent 242e7d8c2e
commit e5e1b12185
10 changed files with 372 additions and 56 deletions
+14 -3
View File
@@ -4,11 +4,20 @@
* Dev'de Vite proxy'si /api isteklerini localhost:3001'e yönlendirir.
*/
function sourceError(data, temporaryMessage) {
if (data.code === 'HUMAN_VERIFICATION_REQUIRED' && data.manualAction) {
return new Error(data.error || 'EKAP güvenlik doğrulaması gerekiyor. EKAP’ı kendi tarayıcınızda açın.');
}
if (data.code === 'SOURCE_UNAVAILABLE' && data.retryable) return new Error(temporaryMessage);
return null;
}
export async function fetchLiveTenders({ refresh = false } = {}) {
const res = await fetch(`/api/tenders${refresh ? '?refresh=1' : ''}`);
const data = await res.json().catch(() => ({}));
if (!res.ok) {
if (data.code === 'SOURCE_UNAVAILABLE' && data.retryable) throw new Error('İhale kaynağı geçici olarak erişilemiyor. Birkaç dakika sonra yeniden deneyin.');
const failure = sourceError(data, 'İhale kaynağı geçici olarak erişilemiyor. Birkaç dakika sonra yeniden deneyin.');
if (failure) throw failure;
throw new Error(`API hatası: HTTP ${res.status}`);
}
if (!data.success) throw new Error(data.error || 'API başarısız yanıt döndü');
@@ -28,7 +37,8 @@ export async function fetchTenderDetail(tenderId, {signal, timeoutMs = 30000} =
const res = await fetch(url, {signal:controller.signal});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
if (data.code === 'SOURCE_UNAVAILABLE' && data.retryable) throw new Error('Resmi ihale kaynağı geçici olarak erişilemiyor. Birkaç dakika sonra yeniden deneyin.');
const failure = sourceError(data, 'Resmi ihale kaynağı geçici olarak erişilemiyor. Birkaç dakika sonra yeniden deneyin.');
if (failure) throw failure;
throw new Error(`Detay API hatası: HTTP ${res.status}`);
}
if (!data.success) throw new Error(data.error || 'Detay alınamadı');
@@ -69,7 +79,8 @@ export async function fetchOfficialTenderDetail(ikn, {signal, timeoutMs = 30000}
const res = await fetch(`/api/documents/ilan?ikn=${encodeURIComponent(cleanIkn)}`, { signal: controller.signal });
const data = await res.json().catch(() => ({}));
if (!res.ok) {
if (data.code === 'SOURCE_UNAVAILABLE' && data.retryable) throw new Error('Resmî ihale kaynağı geçici olarak erişilemiyor.');
const failure = sourceError(data, 'Resmî ihale kaynağı geçici olarak erişilemiyor.');
if (failure) throw failure;
throw new Error(`Resmî detay API hatası: HTTP ${res.status}`);
}
if (!data.success || data.ikn !== cleanIkn) throw new Error('Resmî detay yanıtı aranan İKN ile uyuşmuyor.');