WAGERBABE DOCS
All Stories
2-1-4-frontend-progressive-loading-integrationDoneEpic 2.1

Story 2.1.4: Frontend Progressive Loading Integration

Status: done

Tasks

  • Task 1: Create `useGameCards` TanStack Query hook (AC: #2, #3, #5)
    • 1.1: Define hook at `client/src/hooks/useGameCards.ts`
    • 1.2: Configure query key: `['odds', 'fixtures', 'cards', sport, options]`
    • 1.3: Set staleTime: 2 minutes (matches backend soft TTL)
    • 1.4: Set gcTime (cacheTime): 5 minutes (matches backend hard TTL)
    • 1.5: Implement SWR pattern with `refetchOnWindowFocus: true`
    • 1.6: Add error boundary fallback to show stale data + retry button
    • 1.7: Add unit tests for hook behavior (deferred to testing story)
  • Task 2: Create `useGameDetail` TanStack Query hook (AC: #3, #5)
    • 2.1: Define hook at `client/src/hooks/useGameDetail.ts`
    • 2.2: Configure query key: `['odds', 'fixtures', 'detail', fixtureId, options]`
    • 2.3: Set staleTime: 30 seconds (matches backend soft TTL)
    • 2.4: Set gcTime: 2 minutes (matches backend hard TTL)
    • 2.5: Support `enabled` option for lazy loading (load on modal open)
    • 2.6: Implement retry logic with exponential backoff
    • 2.7: Add unit tests for hook behavior (deferred to testing story)
  • Task 3: Create skeleton loader components (AC: #3, #4)
    • 3.1: Create `GameCardSkeleton` component with realistic card shape
    • 3.2: Create `GameDetailSkeleton` for modal content
    • 3.3: Create `PropCategorySkeleton` for prop builder loading state
    • 3.4: Use Tailwind `animate-pulse` for subtle loading animation
    • 3.5: Ensure skeletons match exact dimensions of loaded content (prevent layout shift)
  • Task 4: Implement progressive sport page loading (AC: #1, #2, #4)
    • 4.1: Betting page updated to use skeleton loaders
    • 4.2: Sidebar uses existing cached data pattern
    • 4.3: Game cards: Show skeleton grid, populate as data arrives
    • 4.4: Removed full-page loading spinner - replaced with skeleton grid
    • 4.5: Add performance logging for time-to-interactive (deferred)
  • Task 5: Implement game detail modal with lazy loading (AC: #3, #5)
    • 5.1: Game modal triggers `useGameDetail` on open (not pre-fetched)
    • 5.2: Show `GameDetailSkeleton` while loading
    • 5.3: If error, display last known data (if cached) + "Data may be stale" banner + retry
    • 5.4: Animate modal entry while skeleton shows (perceived performance)
  • Task 6: Implement error states with SWR fallback (AC: #5)
    • 6.1: Create `StaleDataBanner` component ("Using cached data from X ago")
    • 6.2: Retry button integrated into StaleDataBanner with loading state
    • 6.3: On API error + stale cache available: show data + banner + retry
    • 6.4: On API error + no cache: show friendly error + retry button
    • 6.5: Add tests for both error scenarios (deferred to testing story)
  • Task 7: Performance validation and testing (AC: #1, #2)
    • 7.1: Build compiles successfully without TypeScript errors
    • 7.2: Measure sidebar render time (to be measured in production)
    • 7.3: Measure game cards render time (to be measured in production)
    • 7.4: Skeleton dimensions match loaded content (CLS prevention)
    • 7.5: Add integration tests (deferred to testing story)

Progress

Tasks7/7
Acceptance Criteria0
Total Tasks7