refactoring
This commit is contained in:
178
src/App.js
178
src/App.js
@@ -10,6 +10,7 @@ import useNotificationSettings from './hooks/useNotificationSettings';
|
||||
import useConfigManager from './hooks/useConfigManager';
|
||||
import useStoreSync from './hooks/useStoreSync';
|
||||
import useDirtyNavigationGuard from './hooks/useDirtyNavigationGuard';
|
||||
import useSessionManager from './hooks/useSessionManager';
|
||||
import NavigationTabs from './components/NavigationTabs';
|
||||
import LoginView from './components/LoginView';
|
||||
import DashboardView from './components/DashboardView';
|
||||
@@ -20,10 +21,7 @@ import ConfirmationDialog from './components/ConfirmationDialog';
|
||||
import StoreSyncOverlay from './components/StoreSyncOverlay';
|
||||
import RangePickerModal from './components/RangePickerModal';
|
||||
|
||||
const TOKEN_STORAGE_KEY = 'pickupConfigToken';
|
||||
|
||||
function App() {
|
||||
const [session, setSession] = useState(null);
|
||||
const [credentials, setCredentials] = useState({ email: '', password: '' });
|
||||
const [stores, setStores] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -40,6 +38,10 @@ function App() {
|
||||
const minSelectableDate = useMemo(() => startOfDay(new Date()), []);
|
||||
|
||||
const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'];
|
||||
const unauthorizedResetRef = useRef(() => {});
|
||||
const notifyUnauthorized = useCallback(() => {
|
||||
unauthorizedResetRef.current?.();
|
||||
}, []);
|
||||
|
||||
const normalizeConfigEntries = useCallback((entries) => {
|
||||
if (!Array.isArray(entries)) {
|
||||
@@ -117,27 +119,21 @@ function App() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleUnauthorizedRef = useRef(() => {});
|
||||
|
||||
const authorizedFetch = useCallback(
|
||||
async (url, options = {}, tokenOverride) => {
|
||||
const activeToken = tokenOverride || session?.token;
|
||||
if (!activeToken) {
|
||||
throw new Error('Keine aktive Session');
|
||||
}
|
||||
const headers = {
|
||||
Authorization: `Bearer ${activeToken}`,
|
||||
...(options.headers || {})
|
||||
};
|
||||
const response = await fetch(url, { ...options, headers });
|
||||
if (response.status === 401) {
|
||||
handleUnauthorizedRef.current();
|
||||
throw new Error('Nicht autorisiert');
|
||||
}
|
||||
return response;
|
||||
},
|
||||
[session?.token]
|
||||
);
|
||||
const {
|
||||
session,
|
||||
authorizedFetch,
|
||||
bootstrapSession,
|
||||
performLogout,
|
||||
handleUnauthorized,
|
||||
storeToken,
|
||||
getStoredToken
|
||||
} = useSessionManager({
|
||||
normalizeConfigEntries,
|
||||
normalizeAdminSettings,
|
||||
onUnauthorized: notifyUnauthorized,
|
||||
setError,
|
||||
setLoading
|
||||
});
|
||||
|
||||
const {
|
||||
config,
|
||||
@@ -185,8 +181,20 @@ function App() {
|
||||
onDiscard: () => setIsDirty(false)
|
||||
});
|
||||
|
||||
const applyBootstrapResult = useCallback(
|
||||
(result = {}) => {
|
||||
if (!result) {
|
||||
return {};
|
||||
}
|
||||
setStores(Array.isArray(result.stores) ? result.stores : []);
|
||||
setAdminSettings(result.adminSettings ?? null);
|
||||
setConfig(Array.isArray(result.config) ? result.config : []);
|
||||
return result;
|
||||
},
|
||||
[setStores, setAdminSettings, setConfig]
|
||||
);
|
||||
|
||||
const resetSessionState = useCallback(() => {
|
||||
setSession(null);
|
||||
setConfig([]);
|
||||
setStores([]);
|
||||
setStatus('');
|
||||
@@ -195,73 +203,20 @@ function App() {
|
||||
setAdminSettingsLoading(false);
|
||||
setAvailableCollapsed(true);
|
||||
setInitializing(false);
|
||||
}, [setConfig]);
|
||||
|
||||
const handleUnauthorized = useCallback(() => {
|
||||
resetSessionState();
|
||||
try {
|
||||
localStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
} catch (storageError) {
|
||||
console.warn('Konnte Token nicht aus dem Speicher entfernen:', storageError);
|
||||
}
|
||||
}, [resetSessionState]);
|
||||
}, [
|
||||
setConfig,
|
||||
setStores,
|
||||
setStatus,
|
||||
setError,
|
||||
setAdminSettings,
|
||||
setAdminSettingsLoading,
|
||||
setAvailableCollapsed,
|
||||
setInitializing
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
handleUnauthorizedRef.current = handleUnauthorized;
|
||||
}, [handleUnauthorized]);
|
||||
|
||||
const bootstrapSession = useCallback(
|
||||
async (token, { progress } = {}) => {
|
||||
if (!token) {
|
||||
return {};
|
||||
}
|
||||
setLoading(true);
|
||||
setError('');
|
||||
progress?.update?.('Session wird aufgebaut...', 20);
|
||||
try {
|
||||
const response = await fetch('/api/auth/session', {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
if (response.status === 401) {
|
||||
handleUnauthorized();
|
||||
return;
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
setSession({ token, profile: data.profile, isAdmin: data.isAdmin });
|
||||
progress?.update?.('Betriebe werden geprüft...', 45);
|
||||
setStores(Array.isArray(data.stores) ? data.stores : []);
|
||||
setAdminSettings(data.isAdmin ? normalizeAdminSettings(data.adminSettings) : null);
|
||||
|
||||
const configResponse = await fetch('/api/config', {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
if (configResponse.status === 401) {
|
||||
handleUnauthorized();
|
||||
return;
|
||||
}
|
||||
if (!configResponse.ok) {
|
||||
throw new Error(`HTTP ${configResponse.status}`);
|
||||
}
|
||||
const configData = await configResponse.json();
|
||||
progress?.update?.('Konfiguration wird geladen...', 75);
|
||||
setConfig(normalizeConfigEntries(Array.isArray(configData) ? configData : []));
|
||||
progress?.update?.('Synchronisierung abgeschlossen', 95);
|
||||
return {
|
||||
storeRefreshJob: data.storeRefreshJob,
|
||||
storesFresh: data.storesFresh
|
||||
};
|
||||
} catch (err) {
|
||||
setError(`Session konnte nicht wiederhergestellt werden: ${err.message}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
return {};
|
||||
},
|
||||
[handleUnauthorized, normalizeAdminSettings, normalizeConfigEntries, setConfig]
|
||||
);
|
||||
unauthorizedResetRef.current = resetSessionState;
|
||||
}, [resetSessionState]);
|
||||
|
||||
const {
|
||||
notificationSettings,
|
||||
@@ -339,14 +294,12 @@ function App() {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
try {
|
||||
localStorage.setItem(TOKEN_STORAGE_KEY, data.token);
|
||||
} catch (storageError) {
|
||||
console.warn('Konnte Token nicht speichern:', storageError);
|
||||
}
|
||||
storeToken(data.token);
|
||||
clearInterval(ticker);
|
||||
updateSyncProgress('Zugang bestätigt. Session wird aufgebaut...', 45);
|
||||
const bootstrapResult = await bootstrapSession(data.token, { progress: { update: updateSyncProgress } });
|
||||
const bootstrapResult = applyBootstrapResult(
|
||||
await bootstrapSession(data.token, { progress: { update: updateSyncProgress } })
|
||||
);
|
||||
const needsStoreSync = !bootstrapResult?.storesFresh || !!bootstrapResult?.storeRefreshJob;
|
||||
if (needsStoreSync) {
|
||||
await syncStoresWithProgress({
|
||||
@@ -370,20 +323,6 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const performLogout = useCallback(async () => {
|
||||
if (!session?.token) {
|
||||
handleUnauthorized();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await authorizedFetch('/api/auth/logout', { method: 'POST' });
|
||||
} catch (err) {
|
||||
console.warn('Logout fehlgeschlagen:', err);
|
||||
} finally {
|
||||
handleUnauthorized();
|
||||
}
|
||||
}, [session?.token, authorizedFetch, handleUnauthorized]);
|
||||
|
||||
const handleLogout = () => {
|
||||
requestNavigation('dich abzumelden', performLogout);
|
||||
};
|
||||
@@ -417,12 +356,7 @@ function App() {
|
||||
let ticker;
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
let storedToken = null;
|
||||
try {
|
||||
storedToken = localStorage.getItem(TOKEN_STORAGE_KEY);
|
||||
} catch (err) {
|
||||
console.warn('Konnte gespeicherten Token nicht lesen:', err);
|
||||
}
|
||||
const storedToken = getStoredToken();
|
||||
if (!storedToken) {
|
||||
return;
|
||||
}
|
||||
@@ -430,7 +364,9 @@ function App() {
|
||||
try {
|
||||
startSyncProgress('Session wird wiederhergestellt...', 5, true);
|
||||
ticker = setInterval(() => nudgeSyncProgress('Session wird wiederhergestellt...', 1, 40), 1000);
|
||||
const result = await bootstrapSession(storedToken, { progress: { update: updateSyncProgress } });
|
||||
const result = applyBootstrapResult(
|
||||
await bootstrapSession(storedToken, { progress: { update: updateSyncProgress } })
|
||||
);
|
||||
if (ticker) {
|
||||
clearInterval(ticker);
|
||||
ticker = null;
|
||||
@@ -462,12 +398,14 @@ function App() {
|
||||
}
|
||||
};
|
||||
}, [
|
||||
applyBootstrapResult,
|
||||
bootstrapSession,
|
||||
startSyncProgress,
|
||||
updateSyncProgress,
|
||||
finishSyncProgress,
|
||||
getStoredToken,
|
||||
nudgeSyncProgress,
|
||||
syncStoresWithProgress
|
||||
startSyncProgress,
|
||||
syncStoresWithProgress,
|
||||
updateSyncProgress
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user