Kullanıcı testi hataları: sabit tarihler, kişisel varsayılanlar, kılavuz düğmesi, mobil başlık, AI taslak çökmesi
- Günlük Bülten ve İhale Takvimi sabit "10.08.2026" yerine bugünden hesaplar; takvim 7 günü gerçek ihale tarihleriyle sayar - Ekip/üye/firma varsayılanları oturumdaki kullanıcıdan; sahte "Ekip Notları" ve sabit "%94 Uyum" rozeti kaldırıldı (gerçek uyum skoru varsa gösterilir) - Kılavuz düğmesi document.body'ye portal (ekran dışına düşüyordu) - Detay modalı havuzdaki güncel kaydı okur: Takip Et / Görev aç etiketleri güncellenir - Mobil: başlıkta ikincil düğmeler md altında gizli, arama formu küçülebilir - PWA sayfası: sahte önbellek sayıları yerine Cache API ve bellek sayımı - Sözleşme sorgula pazar payı bir ondalık (hep %0 görünüyordu) - Rakip Radar "SMS" vaadi düzeltildi; sektör=CPV etiketi tekrarı gizlendi; Stripe kurulum uyarısı yalnız yöneticiye - Açılışta 7 gereksiz PUT /api/me/data: ilk yükleme yazımı atlanır - server: teklif taslağı çökmesi (kalemOku nesne döndürür), denetim yanıtından model adı kaldırıldı, gereklilikler satır bazlı; derin analiz 12k token + kesik JSON onarımı Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+24
-15
@@ -1,4 +1,4 @@
|
||||
import React, {createContext, useContext, useState, useEffect, useMemo } from 'react';
|
||||
import React, {createContext, useContext, useState, useEffect, useMemo, useRef } from 'react';
|
||||
import { parseWebsiteCapabilitiesDynamically } from '../services/webScraperService';
|
||||
import { havuzuPuanla, profilMetni, profilTerimleri } from '../services/uyum';
|
||||
import { getToken } from '../services/auth';
|
||||
@@ -168,6 +168,15 @@ export const AppProvider = ({ children }) => {
|
||||
// localStorage yalnızca çevrimdışı önbellek; kaynak doğruluk sunucuda.
|
||||
const [plan, setPlan] = useState(null);
|
||||
const [veriSenkron, setVeriSenkron] = useState(false);
|
||||
// Sunucu verisi yüklendiğinde her effect bir kez tetiklenir; bu ilk turda
|
||||
// yazmak gereksiz (aynı veri) ve boş istemci state'iyle ezme riski taşır.
|
||||
const ilkYazmaAtlanan = useRef(new Set());
|
||||
// İlk tetiklenme (sunucu verisi yüklenirken) yazılmaz; sonrakiler yazılır.
|
||||
const ilkYazmaDegil = (anahtar, deger) => {
|
||||
if (ilkYazmaAtlanan.current.has(anahtar)) { sunucuyaYaz(anahtar, deger); return; }
|
||||
ilkYazmaAtlanan.current.add(anahtar);
|
||||
};
|
||||
|
||||
|
||||
const sunucuyaYaz = (anahtar, deger) => {
|
||||
if (!authUser) return;
|
||||
@@ -253,7 +262,7 @@ export const AppProvider = ({ children }) => {
|
||||
});
|
||||
useEffect(() => {
|
||||
yerelKaydet('ihaleist_rakip_izleme', competitorWatchlist);
|
||||
if (veriSenkron) sunucuyaYaz('rakip_izleme', competitorWatchlist);
|
||||
if (veriSenkron) ilkYazmaDegil('rakip_izleme', competitorWatchlist);
|
||||
}, [competitorWatchlist, veriSenkron]);
|
||||
|
||||
// --- Favori kurumlar (localStorage, gerçek) ---
|
||||
@@ -262,7 +271,7 @@ export const AppProvider = ({ children }) => {
|
||||
});
|
||||
useEffect(() => {
|
||||
yerelKaydet('ihaleist_favori_kurumlar', favoriteKurumlar);
|
||||
if (veriSenkron) sunucuyaYaz('favori_kurumlar', favoriteKurumlar);
|
||||
if (veriSenkron) ilkYazmaDegil('favori_kurumlar', favoriteKurumlar);
|
||||
}, [favoriteKurumlar, veriSenkron]);
|
||||
const toggleFavoriteKurum = (kurum) => {
|
||||
const ad = (kurum || '').trim();
|
||||
@@ -276,13 +285,12 @@ export const AppProvider = ({ children }) => {
|
||||
const saved = localStorage.getItem('ihaleist_ekip');
|
||||
if (saved) return JSON.parse(saved);
|
||||
} catch { /* yoksay */ }
|
||||
return [
|
||||
{ id: 'tm-1', name: 'Hikmet Tanrıverdi', email: 'hikmet044@gmail.com', role: 'Yönetici' },
|
||||
];
|
||||
const u = getStoredUser();
|
||||
return u ? [{ id: 'tm-1', name: u.name || u.email, email: u.email || '', role: 'Yönetici' }] : [];
|
||||
});
|
||||
useEffect(() => {
|
||||
yerelKaydet('ihaleist_ekip', teamMembers);
|
||||
if (veriSenkron) sunucuyaYaz('ekip', teamMembers);
|
||||
if (veriSenkron) ilkYazmaDegil('ekip', teamMembers);
|
||||
}, [teamMembers, veriSenkron]);
|
||||
const addTeamMember = (m) => setTeamMembers((prev) => [...prev, { id: 'tm-' + Date.now(), ...m }]);
|
||||
const removeTeamMember = (id) => setTeamMembers((prev) => prev.filter((m) => m.id !== id));
|
||||
@@ -309,7 +317,7 @@ export const AppProvider = ({ children }) => {
|
||||
});
|
||||
useEffect(() => {
|
||||
yerelKaydet('ihaleist_reminder', reminderSettings);
|
||||
if (veriSenkron) sunucuyaYaz('reminder', reminderSettings);
|
||||
if (veriSenkron) ilkYazmaDegil('reminder', reminderSettings);
|
||||
}, [reminderSettings, veriSenkron]);
|
||||
|
||||
// Şu an sessiz saat aralığında mıyız (gece yarısını geçen aralıkları da destekler)
|
||||
@@ -416,11 +424,12 @@ export const AppProvider = ({ children }) => {
|
||||
// Yetkinlikler uyum skorunun girdisi — sayfa yenilenince sıfırlanmasın
|
||||
let kayitli = null;
|
||||
try { kayitli = JSON.parse(localStorage.getItem('ihaleist_firma_profil') || 'null'); } catch { /* yoksay */ }
|
||||
const u = getStoredUser();
|
||||
return {
|
||||
name: 'Hikmet Tanrıverdi',
|
||||
username: 'tanriverdi',
|
||||
company: kayitli?.company || 'Tanrıverdi Medikal & Sağlık Teknolojileri A.Ş.',
|
||||
website: kayitli?.website || 'https://www.tanriverdimedikal.com.tr',
|
||||
name: u?.name || u?.email || 'Kullanıcı',
|
||||
username: (u?.email || '').split('@')[0] || 'kullanici',
|
||||
company: kayitli?.company || '',
|
||||
website: kayitli?.website || '',
|
||||
trialDaysLeft: 7,
|
||||
role: 'Yönetici Tedarikçi',
|
||||
scrapedCapabilities: { ...BOS_YETKINLIK, ...(kayitli?.scrapedCapabilities || {}) },
|
||||
@@ -434,7 +443,7 @@ export const AppProvider = ({ children }) => {
|
||||
scrapedCapabilities: userProfile.scrapedCapabilities, uyumEsigi: userProfile.uyumEsigi,
|
||||
};
|
||||
yerelKaydet('ihaleist_firma_profil', veri);
|
||||
if (veriSenkron) sunucuyaYaz('firma_profil', veri);
|
||||
if (veriSenkron) ilkYazmaDegil('firma_profil', veri);
|
||||
}, [userProfile.company, userProfile.website, userProfile.scrapedCapabilities, userProfile.uyumEsigi, veriSenkron]);
|
||||
const setUyumEsigi = (v) => setUserProfile((p) => ({ ...p, uyumEsigi: Math.max(0, Math.min(100, Number(v) || 0)) }));
|
||||
|
||||
@@ -548,7 +557,7 @@ export const AppProvider = ({ children }) => {
|
||||
|
||||
useEffect(() => {
|
||||
yerelKaydet('ihaleist_saved_filters', savedFilters);
|
||||
if (veriSenkron) sunucuyaYaz('saved_filters', savedFilters);
|
||||
if (veriSenkron) ilkYazmaDegil('saved_filters', savedFilters);
|
||||
}, [savedFilters, veriSenkron]);
|
||||
|
||||
// (Sahte "online kullanıcı" rastgele sayacı kaldırıldı — canlı istatistikler
|
||||
@@ -571,7 +580,7 @@ export const AppProvider = ({ children }) => {
|
||||
);
|
||||
const takipImza = takipIknler.join('|');
|
||||
useEffect(() => {
|
||||
if (veriSenkron) sunucuyaYaz('takip', takipIknler);
|
||||
if (veriSenkron) ilkYazmaDegil('takip', takipIknler);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [takipImza, veriSenkron]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user