feat(fe-027): Add fallback behavior for offline mode when API base URL unreachable#1829
Open
rindicomfort wants to merge 2 commits into
Open
Conversation
- Add isApiReachable field to uiSlice (Zustand store) - Rewrite useNetworkStatus to sync both isOnline and isApiReachable into the global store, listen to network-unreachable custom events from Axios, and expose recheckApi() for on-demand probing - Add ApiUnreachableFallback component shown when device is online but the backend API cannot be reached (distinct from OfflineFallback) - Add OfflineModeProvider that wraps children and gates them behind connectivity checks, rendering the correct fallback automatically - Wire OfflineModeProvider into RootProviders - Update OfflineFallback with aria-live and aria-hidden attributes - Export ApiUnreachableFallback from components/error/index.ts - Add unit tests for useNetworkStatus, ApiUnreachableFallback, and OfflineModeProvider Closes EarnQuestOne#816
|
@rindicomfort Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Contributor
|
Great job so far There’s just one blocker — the workflow is failing. Could you take a look and fix it so all checks pass? |
Author
|
okay @RUKAYAT-CODER |
- Remove self-referential ReturnType in buildStoreMock (caused TS2456 'overrides is referenced in its own type annotation') - Use explicit StoreMockState interface instead - Use stable mock state object in tests to avoid infinite re-renders caused by new function references on every useStore selector call - Make probeApi useCallback stable (empty deps) via setApiReachableRef to break the setInterval -> setApiReachable -> re-render -> effect infinite loop reported in CI (10000 timer limit hit)
Author
|
done @RUKAYAT-CODER |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #816
This PR implements [FE-027] — proper fallback behaviour when the application is offline or the API base URL is unreachable, replacing the previous no-op state with a fully wired, store-backed solution.
Problem
Previously the app had no cohesive handling for the two distinct connectivity failure modes:
navigator.onLine === falseERR_NETWORK/ timeoutThe existing
useNetworkStatushook tracked these states locally but never synced them to the global store, so no UI could react to them. TheOfflineFallbackcomponent existed but was never mounted anywhere.Changes
lib/store/slices/uiSlice.tsisApiReachable: booleanfield andsetApiReachable()action to the Zustand store so any component tree can subscribe to API reachability without prop drilling.lib/hooks/useNetworkStatus.ts(rewritten)isOnlineandisApiReachableinto the global store.network-unreachablecustom event already dispatched by the Axios client interceptor./healthprobe (every 30 s) when online; fires immediately on reconnect.recheckApi()for on-demand probing (used by retry buttons).components/error/ApiUnreachableFallback.tsx(new)OfflineFallback— different icon, copy, and user guidance.role="status",aria-live="polite", spinner state on retry button.components/error/OfflineFallback.tsxrole="status"andaria-live="polite"for screen-reader compatibility.aria-hiddenon decorative icons.components/providers/OfflineModeProvider.tsx(new)useNetworkStatusonce at the provider level.OfflineFallbackwhen offline,ApiUnreachableFallbackwhen online-but-unreachable, children otherwise.enabledprop (defaultstrue) to opt out in tests/Storybook.app/providers/RootProviders.tsx<A11yAnnouncerProvider>(and therefore all page content) with<OfflineModeProvider>.components/error/index.tsOfflineFallbackandApiUnreachableFallback.Tests
lib/hooks/useNetworkStatus.test.ts— covers initial sync, online/offline events, API probe success/failure,network-unreachableevent, skipping probe when offline, andrecheckApi().components/error/ApiUnreachableFallback.test.tsx— rendering, retry callback, checking state, accessibility attributes.components/providers/OfflineModeProvider.test.tsx— all three render paths (children / offline fallback / API fallback), retry wiring,enabled=falsebypass.Acceptance criteria
OfflineFallbackApiUnreachableFallbackisApiReachablepersisted in global storenetwork-unreachableevent consumed