import { Middleware } from '@reduxjs/toolkit'; import { RootState } from '../store'; import { setOnlineStatus } from '../slices/networkSlice'; import { addPendingAction, removePendingAction, incrementRetryCount } from '../slices/offlineSlice'; /** * Offline middleware - intercepts actions and queues them when offline */ export const offlineMiddleware: Middleware<{}, RootState> = (store) => (next) => (action: any) => { const state = store.getState(); const isOnline = state.network?.isOnline ?? true; // Check if this is an async action that should be queued const isOfflineableAction = action.type?.includes('/create') || action.type?.includes('/update') || action.type?.includes('/delete'); // If offline and action should be queued if (!isOnline && isOfflineableAction && action.meta?.requestId) { console.log('[Offline Middleware] Queuing action:', action.type); // Queue the action store.dispatch( addPendingAction({ type: action.type, payload: action.payload, }) ); // Still process the optimistic update return next(action); } // If online, process normally return next(action); }; /** * Network status detector - listens for online/offline events */ export const setupNetworkDetection = (dispatch: any) => { if (typeof window === 'undefined') return; const handleOnline = () => { console.log('[Network] Connection restored'); dispatch(setOnlineStatus(true)); }; const handleOffline = () => { console.log('[Network] Connection lost'); dispatch(setOnlineStatus(false)); }; // Listen to browser online/offline events window.addEventListener('online', handleOnline); window.addEventListener('offline', handleOffline); // Periodic connectivity check const checkConnectivity = async () => { try { const startTime = Date.now(); const response = await fetch('/api/health', { method: 'HEAD', cache: 'no-cache', }); const latency = Date.now() - startTime; // Consider online if we got ANY response (even 404) // Only mark offline on actual network errors dispatch(setOnlineStatus(true)); } catch (error) { // Only network errors (no connection) should mark as offline dispatch(setOnlineStatus(false)); } }; // Check connectivity every 30 seconds const intervalId = setInterval(checkConnectivity, 30000); // Initial check checkConnectivity(); // Cleanup function return () => { window.removeEventListener('online', handleOnline); window.removeEventListener('offline', handleOffline); clearInterval(intervalId); }; };