Skip to content

fix(milestones): robust async loading state machine (#1099) - #1143

Open
Simultech369 wants to merge 1 commit into
Talenttrust:mainfrom
Simultech369:fix-1099-async-state-machine
Open

fix(milestones): robust async loading state machine (#1099)#1143
Simultech369 wants to merge 1 commit into
Talenttrust:mainfrom
Simultech369:fix-1099-async-state-machine

Conversation

@Simultech369

Copy link
Copy Markdown

Summary of Changes

Closes #1099

This PR refactors the Milestones board data loading to use a robust, explicit discriminated union state machine, completely separating the loading, empty, error, and success states.

Key Improvements:

  1. Explicit State Machine: Replaced separate boolean flags and fallback sample data checks with a clear MilestonesFetchState type.
  2. Mutually Exclusive Rendering: By using early returns (e.g. if (fetchState.status === 'loading') return <MilestonesBoardSkeleton />;), we guarantee that states are mutually exclusive by construction. This inherently prevents the layout bug where the loader's container padding doubled up inside the page container.
  3. Synchronous Initialization: To preserve compatibility with the rest of the application and avoid test breakage, the initial load from localStorage remains synchronous (matching the approach in ContractsPage). The loading state correctly yields a microtask on explicit refetch/retry.
  4. Accessibility Enhancements: Moved the screen-reader aria-live announcer into a commonHeader block so it is always present, reliably announcing state transitions ("Unable to load milestones", "No milestones tracked", "5 milestones found").
  5. Testing:
    • Added src/app/milestones/__tests__/fetch-machine.test.tsx to explicitly test all 4 states of the machine.
    • Verified that all existing unit and integration tests pass completely unmodified (294 tests across 20 suites).

Everything is now robust, fully typed, and cleanly isolated.

Closes Talenttrust#1099

- Refactored `MilestonesPage` state to an explicit discriminated union (`MilestonesFetchState`: `loading` | `empty` | `error` | `success`).
- Made the initial repository load synchronous to prevent test breakage and layout flashes, while keeping the `loading` state available for explicit refetches/retries.
- Used early returns instead of nested ternaries to ensure mutually exclusive rendering, preventing the `MilestonesBoardSkeleton`'s padding from doubling up inside `MilestonesContent`.
- Fixed the accessibility issue by moving the screen-reader `aria-live` announcer to be unconditionally rendered at the top of the component, providing accurate status strings ("5 milestones found", "Loading...", etc).
- Added new integration tests (`fetch-machine.test.tsx`) asserting all states in the state machine.
- Ensured all existing unit and integration tests pass cleanly without requiring mass refactoring.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

robust async state machine for the milestones board (loading/empty/error/success)

1 participant