diff --git a/src/App.js b/src/App.js index 60f50c1..71ae577 100644 --- a/src/App.js +++ b/src/App.js @@ -188,205 +188,6 @@ function App() { [handleUnauthorized, session?.token] ); - const fetchConfig = useCallback( - async (tokenOverride, { silent = false } = {}) => { - const tokenToUse = tokenOverride || session?.token; - if (!tokenToUse) { - return; - } - if (!silent) { - setStatus(''); - } - setLoading(true); - setError(''); - try { - const response = await authorizedFetch('/api/config', {}, tokenToUse); - if (!response.ok) { - throw new Error(`HTTP ${response.status}`); - } - const data = await response.json(); - setConfig(Array.isArray(data) ? data : []); - if (!silent) { - setStatus('Konfiguration aktualisiert.'); - setTimeout(() => setStatus(''), 3000); - } - } catch (err) { - setError(`Fehler beim Laden der Konfiguration: ${err.message}`); - } finally { - setLoading(false); - } - }, - [session?.token, authorizedFetch] - ); - - const fetchStoresList = useCallback(async () => { - if (!session?.token) { - return; - } - setStatus(''); - setError(''); - try { - const response = await authorizedFetch('/api/stores'); - if (!response.ok) { - throw new Error(`HTTP ${response.status}`); - } - const data = await response.json(); - setStores(Array.isArray(data) ? data : []); - setStatus('Betriebe aktualisiert.'); - setTimeout(() => setStatus(''), 3000); - } catch (err) { - setError(`Fehler beim Laden der Betriebe: ${err.message}`); - } - }, [session?.token, authorizedFetch]); - - const syncStoresWithProgress = useCallback( - async ({ block = false, reason = 'manual', startJob = true, reuseOverlay = false } = {}) => { - if (!session?.token) { - return; - } - if (!reuseOverlay) { - startSyncProgress('Betriebe werden geprüft...', 5, block); - } else { - updateSyncProgress('Betriebe werden geprüft...', 35); - } - try { - let jobStarted = false; - const triggerRefresh = async () => { - const response = await authorizedFetch('/api/stores/refresh', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ force: true, reason }) - }); - if (!response.ok) { - throw new Error(`HTTP ${response.status}`); - } - await response.json(); - jobStarted = true; - }; - - if (startJob) { - await triggerRefresh(); - } - - let completed = false; - while (!completed) { - const statusResp = await authorizedFetch('/api/stores/refresh/status'); - if (!statusResp.ok) { - throw new Error(`HTTP ${statusResp.status}`); - } - const statusData = await statusResp.json(); - const job = statusData.job; - if (job?.status === 'running') { - const total = job.total || 0; - const processed = job.processed || 0; - const percent = total > 0 ? Math.min(95, 10 + Math.round((processed / total) * 80)) : undefined; - const message = job.currentStore - ? `Prüfe ${job.currentStore} (${processed}/${total || '?'})` - : 'Betriebe werden geprüft...'; - updateSyncProgress(message, percent); - } else if (!job) { - if (statusData.storesFresh) { - updateSyncProgress('Betriebe aktuell.', 90); - completed = true; - } else if (!jobStarted) { - await triggerRefresh(); - await delay(500); - } else { - updateSyncProgress('Warte auf Rückmeldung...', undefined); - } - } else if (job.status === 'done') { - updateSyncProgress('Synchronisierung abgeschlossen', 95); - completed = true; - } else if (job.status === 'error') { - throw new Error(job.error || 'Unbekannter Fehler beim Prüfen der Betriebe.'); - } - if (!completed) { - await delay(1000); - } - } - - await fetchStoresList(); - await fetchConfig(undefined, { silent: true }); - setStatus('Betriebe aktualisiert.'); - setTimeout(() => setStatus(''), 3000); - } catch (err) { - setError(`Aktualisieren der Betriebe fehlgeschlagen: ${err.message}`); - } finally { - if (!reuseOverlay) { - finishSyncProgress(); - } - } - }, - [ - session?.token, - authorizedFetch, - startSyncProgress, - updateSyncProgress, - finishSyncProgress, - delay, - fetchStoresList, - fetchConfig, - setError, - setStatus - ] - ); - - const refreshStoresAndConfig = useCallback( - ({ block = false } = {}) => syncStoresWithProgress({ block, reason: 'manual', startJob: true }), - [syncStoresWithProgress] - ); - - useEffect(() => { - let ticker; - let cancelled = false; - (async () => { - try { - const storedToken = localStorage.getItem(TOKEN_STORAGE_KEY); - if (!storedToken) { - return; - } - startSyncProgress('Session wird wiederhergestellt...', 5, true); - ticker = setInterval(() => nudgeSyncProgress('Session wird wiederhergestellt...', 1, 40), 1000); - const result = await bootstrapSession(storedToken, { progress: { update: updateSyncProgress } }); - if (ticker) { - clearInterval(ticker); - ticker = null; - } - if (!cancelled) { - const needsStoreSync = !result?.storesFresh || !!result?.storeRefreshJob; - if (needsStoreSync) { - await syncStoresWithProgress({ - reason: 'session-auto', - startJob: !result?.storeRefreshJob, - reuseOverlay: true, - block: true - }); - } - } - } catch (err) { - console.warn('Konnte gespeicherten Token nicht lesen oder wiederherstellen:', err); - } finally { - if (ticker) { - clearInterval(ticker); - } - finishSyncProgress(); - } - })(); - return () => { - cancelled = true; - if (ticker) { - clearInterval(ticker); - } - }; - }, [ - bootstrapSession, - startSyncProgress, - updateSyncProgress, - finishSyncProgress, - nudgeSyncProgress, - syncStoresWithProgress - ]); - useEffect(() => { if (!session?.token || !session.isAdmin) { setAdminSettings(null); @@ -631,6 +432,57 @@ function App() { [syncStoresWithProgress] ); + useEffect(() => { + let ticker; + let cancelled = false; + (async () => { + try { + const storedToken = localStorage.getItem(TOKEN_STORAGE_KEY); + if (!storedToken) { + return; + } + startSyncProgress('Session wird wiederhergestellt...', 5, true); + ticker = setInterval(() => nudgeSyncProgress('Session wird wiederhergestellt...', 1, 40), 1000); + const result = await bootstrapSession(storedToken, { progress: { update: updateSyncProgress } }); + if (ticker) { + clearInterval(ticker); + ticker = null; + } + if (!cancelled) { + const needsStoreSync = !result?.storesFresh || !!result?.storeRefreshJob; + if (needsStoreSync) { + await syncStoresWithProgress({ + reason: 'session-auto', + startJob: !result?.storeRefreshJob, + reuseOverlay: true, + block: true + }); + } + } + } catch (err) { + console.warn('Konnte gespeicherten Token nicht lesen oder wiederherstellen:', err); + } finally { + if (ticker) { + clearInterval(ticker); + } + finishSyncProgress(); + } + })(); + return () => { + cancelled = true; + if (ticker) { + clearInterval(ticker); + } + }; + }, [ + bootstrapSession, + startSyncProgress, + updateSyncProgress, + finishSyncProgress, + nudgeSyncProgress, + syncStoresWithProgress + ]); + const saveConfig = async () => { if (!session?.token) { return;