fix: 12 bin ihalelik havuz localStorage kotasını aşıp uygulamayı beyaz ekranla çökertiyordu
This commit is contained in:
+53
-12
@@ -6,11 +6,44 @@ import { getAllUserData, setUserData, getPlan } from '../services/account';
|
|||||||
|
|
||||||
const AppContext = createContext();
|
const AppContext = createContext();
|
||||||
|
|
||||||
|
// İhale önbelleği: tam havuz (10.000+ kayıt) localStorage kotasına sığmaz.
|
||||||
|
const TENDER_CACHE_KEY = 'ihaleist_tenders';
|
||||||
|
const TENDER_CACHE_LIMIT = 300;
|
||||||
|
|
||||||
|
// localStorage her zaman yazılabilir değildir (kota dolu, gizli sekme, site
|
||||||
|
// verisi kapalı). Yazma hatası uygulamayı çökertmemeli.
|
||||||
|
const yerelKaydet = (anahtar, deger) => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(anahtar, JSON.stringify(deger));
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const yerelOku = (anahtar, varsayilan) => {
|
||||||
|
try {
|
||||||
|
const ham = localStorage.getItem(anahtar);
|
||||||
|
if (!ham) return varsayilan;
|
||||||
|
const v = JSON.parse(ham);
|
||||||
|
return v == null ? varsayilan : v;
|
||||||
|
} catch {
|
||||||
|
return varsayilan;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const AppProvider = ({ children }) => {
|
export const AppProvider = ({ children }) => {
|
||||||
const [activeTab, setActiveTab] = useState('list'); // 'list', 'bulten', 'sonuc', 'takvim', 'sozlesme', 'kdv', 'fiyat', 'kanban', 'smart_filter_builder'
|
const [activeTab, setActiveTab] = useState('list'); // 'list', 'bulten', 'sonuc', 'takvim', 'sozlesme', 'kdv', 'fiyat', 'kanban', 'smart_filter_builder'
|
||||||
const [tenders, setTenders] = useState(() => {
|
const [tenders, setTenders] = useState(() => {
|
||||||
const saved = localStorage.getItem('ihaleist_tenders');
|
// Sadece ilk boyama için küçük bir önbellek; asıl kaynak sunucudur.
|
||||||
return saved ? JSON.parse(saved) : [];
|
// Bozuk/eski kayıt uygulamayı çökertmemeli.
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem(TENDER_CACHE_KEY);
|
||||||
|
const parsed = saved ? JSON.parse(saved) : null;
|
||||||
|
return Array.isArray(parsed) ? parsed : [];
|
||||||
|
} catch {
|
||||||
|
try { localStorage.removeItem(TENDER_CACHE_KEY); } catch { /* yok say */ }
|
||||||
|
return [];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const [liveStats, setLiveStats] = useState({ toplamIhale: 0, bugunEklenen: 0, arsiv: 0 });
|
const [liveStats, setLiveStats] = useState({ toplamIhale: 0, bugunEklenen: 0, arsiv: 0 });
|
||||||
@@ -23,8 +56,8 @@ export const AppProvider = ({ children }) => {
|
|||||||
const [quickFilter, setQuickFilter] = useState('all');
|
const [quickFilter, setQuickFilter] = useState('all');
|
||||||
|
|
||||||
const [savedFilters, setSavedFilters] = useState(() => {
|
const [savedFilters, setSavedFilters] = useState(() => {
|
||||||
const saved = localStorage.getItem('ihaleist_saved_filters');
|
const v = yerelOku('ihaleist_saved_filters', []);
|
||||||
return saved ? JSON.parse(saved) : [];
|
return Array.isArray(v) ? v : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isLiveMode, setIsLiveMode] = useState(true);
|
const [isLiveMode, setIsLiveMode] = useState(true);
|
||||||
@@ -142,7 +175,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
try { return JSON.parse(localStorage.getItem('ihaleist_rakip_izleme') || '[]'); } catch { return []; }
|
try { return JSON.parse(localStorage.getItem('ihaleist_rakip_izleme') || '[]'); } catch { return []; }
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_rakip_izleme', JSON.stringify(competitorWatchlist));
|
yerelKaydet('ihaleist_rakip_izleme', competitorWatchlist);
|
||||||
if (veriSenkron) sunucuyaYaz('rakip_izleme', competitorWatchlist);
|
if (veriSenkron) sunucuyaYaz('rakip_izleme', competitorWatchlist);
|
||||||
}, [competitorWatchlist, veriSenkron]);
|
}, [competitorWatchlist, veriSenkron]);
|
||||||
|
|
||||||
@@ -151,7 +184,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
try { return JSON.parse(localStorage.getItem('ihaleist_favori_kurumlar') || '[]'); } catch { return []; }
|
try { return JSON.parse(localStorage.getItem('ihaleist_favori_kurumlar') || '[]'); } catch { return []; }
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_favori_kurumlar', JSON.stringify(favoriteKurumlar));
|
yerelKaydet('ihaleist_favori_kurumlar', favoriteKurumlar);
|
||||||
if (veriSenkron) sunucuyaYaz('favori_kurumlar', favoriteKurumlar);
|
if (veriSenkron) sunucuyaYaz('favori_kurumlar', favoriteKurumlar);
|
||||||
}, [favoriteKurumlar, veriSenkron]);
|
}, [favoriteKurumlar, veriSenkron]);
|
||||||
const toggleFavoriteKurum = (kurum) => {
|
const toggleFavoriteKurum = (kurum) => {
|
||||||
@@ -171,7 +204,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
];
|
];
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_ekip', JSON.stringify(teamMembers));
|
yerelKaydet('ihaleist_ekip', teamMembers);
|
||||||
if (veriSenkron) sunucuyaYaz('ekip', teamMembers);
|
if (veriSenkron) sunucuyaYaz('ekip', teamMembers);
|
||||||
}, [teamMembers, veriSenkron]);
|
}, [teamMembers, veriSenkron]);
|
||||||
const addTeamMember = (m) => setTeamMembers((prev) => [...prev, { id: 'tm-' + Date.now(), ...m }]);
|
const addTeamMember = (m) => setTeamMembers((prev) => [...prev, { id: 'tm-' + Date.now(), ...m }]);
|
||||||
@@ -182,7 +215,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
try { return JSON.parse(localStorage.getItem('ihaleist_belgeler') || '[]'); } catch { return []; }
|
try { return JSON.parse(localStorage.getItem('ihaleist_belgeler') || '[]'); } catch { return []; }
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_belgeler', JSON.stringify(vaultDocuments));
|
yerelKaydet('ihaleist_belgeler', vaultDocuments);
|
||||||
}, [vaultDocuments]);
|
}, [vaultDocuments]);
|
||||||
|
|
||||||
const [reminderSettings, setReminderSettings] = useState(() => {
|
const [reminderSettings, setReminderSettings] = useState(() => {
|
||||||
@@ -198,7 +231,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
} catch { return def; }
|
} catch { return def; }
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_reminder', JSON.stringify(reminderSettings));
|
yerelKaydet('ihaleist_reminder', reminderSettings);
|
||||||
if (veriSenkron) sunucuyaYaz('reminder', reminderSettings);
|
if (veriSenkron) sunucuyaYaz('reminder', reminderSettings);
|
||||||
}, [reminderSettings, veriSenkron]);
|
}, [reminderSettings, veriSenkron]);
|
||||||
|
|
||||||
@@ -266,7 +299,7 @@ export const AppProvider = ({ children }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_ai_model_config', JSON.stringify(aiModelConfig));
|
yerelKaydet('ihaleist_ai_model_config', aiModelConfig);
|
||||||
}, [aiModelConfig]);
|
}, [aiModelConfig]);
|
||||||
|
|
||||||
const getModelById = (id) => AI_MODEL_CATALOG.find(m => m.id === id);
|
const getModelById = (id) => AI_MODEL_CATALOG.find(m => m.id === id);
|
||||||
@@ -353,12 +386,20 @@ export const AppProvider = ({ children }) => {
|
|||||||
const markNotificationsRead = () => setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
const markNotificationsRead = () => setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
||||||
|
|
||||||
// Persist state to localstorage
|
// Persist state to localstorage
|
||||||
|
// Havuz on binlerce kayda çıkabiliyor; tamamı localStorage kotasını (≈5 MB)
|
||||||
|
// aşar ve yakalanmazsa uygulama beyaz ekranla çöker. Bu yüzden yalnızca ilk
|
||||||
|
// boyamaya yetecek kadarını, hataya dayanıklı biçimde saklıyoruz.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_tenders', JSON.stringify(tenders));
|
try {
|
||||||
|
localStorage.setItem(TENDER_CACHE_KEY, JSON.stringify(tenders.slice(0, TENDER_CACHE_LIMIT)));
|
||||||
|
} catch {
|
||||||
|
// Kota dolduysa önbelleği bırak — veri zaten sunucudan geliyor.
|
||||||
|
try { localStorage.removeItem(TENDER_CACHE_KEY); } catch { /* yok say */ }
|
||||||
|
}
|
||||||
}, [tenders]);
|
}, [tenders]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('ihaleist_saved_filters', JSON.stringify(savedFilters));
|
yerelKaydet('ihaleist_saved_filters', savedFilters);
|
||||||
if (veriSenkron) sunucuyaYaz('saved_filters', savedFilters);
|
if (veriSenkron) sunucuyaYaz('saved_filters', savedFilters);
|
||||||
}, [savedFilters, veriSenkron]);
|
}, [savedFilters, veriSenkron]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user