# ADR-005: Frontend State Management and Server Cache Strategy

**Date**: 2025-12-12
**Implementation Date**: 2026-01-08

**Status**: Accepted and Fully Implemented (Phases 1-8 complete, 100% coverage)

## Context

The frontend currently uses React's built-in hooks (`useState`, `useEffect`, `useContext`) for state management, as seen in `useAuth.tsx`. While effective for simple cases, this manual approach becomes complex and error-prone when fetching, caching, and synchronizing data with the server. It often leads to custom logic for loading states, errors, re-fetching, and optimistic updates.

## Decision

We will adopt a dedicated library for managing server state, such as **TanStack Query (formerly React Query)** or **SWR**, for all server-side data fetching on the client. This will abstract away the complexities of caching, background re-validation, and request deduplication.

## Consequences

**Positive**: Leads to a more performant, predictable, and simpler frontend codebase. Standardizes how the client-side communicates with the server and handles loading/error states. Improves user experience through intelligent caching.
**Negative**: Introduces a new frontend dependency. Requires a learning curve for developers unfamiliar with the library. Requires refactoring of existing data-fetching logic.

## Implementation Status

### Phase 1: Infrastructure & Core Queries (✅ Complete - 2026-01-08)

**Files Created:**

- [src/config/queryClient.ts](../../src/config/queryClient.ts) - Global QueryClient configuration
- [src/hooks/queries/useFlyersQuery.ts](../../src/hooks/queries/useFlyersQuery.ts) - Flyers data query
- [src/hooks/queries/useWatchedItemsQuery.ts](../../src/hooks/queries/useWatchedItemsQuery.ts) - Watched items query
- [src/hooks/queries/useShoppingListsQuery.ts](../../src/hooks/queries/useShoppingListsQuery.ts) - Shopping lists query

**Files Modified:**

- [src/providers/AppProviders.tsx](../../src/providers/AppProviders.tsx) - Added QueryClientProvider wrapper
- [src/providers/FlyersProvider.tsx](../../src/providers/FlyersProvider.tsx) - Refactored to use TanStack Query
- [src/providers/UserDataProvider.tsx](../../src/providers/UserDataProvider.tsx) - Refactored to use TanStack Query
- [src/services/apiClient.ts](../../src/services/apiClient.ts) - Added pagination params to fetchFlyers

**Benefits Achieved:**

- ✅ Removed ~150 lines of custom state management code
- ✅ Automatic caching of server data
- ✅ Background refetching for stale data
- ✅ React Query Devtools available in development
- ✅ Automatic data invalidation on user logout
- ✅ Better error handling and loading states

### Phase 2: Remaining Queries (✅ Complete - 2026-01-08)

**Files Created:**

- [src/hooks/queries/useMasterItemsQuery.ts](../../src/hooks/queries/useMasterItemsQuery.ts) - Master grocery items query
- [src/hooks/queries/useFlyerItemsQuery.ts](../../src/hooks/queries/useFlyerItemsQuery.ts) - Flyer items query

**Files Modified:**

- [src/providers/MasterItemsProvider.tsx](../../src/providers/MasterItemsProvider.tsx) - Refactored to use TanStack Query
- [src/hooks/useFlyerItems.ts](../../src/hooks/useFlyerItems.ts) - Refactored to use TanStack Query

**Benefits Achieved:**

- ✅ Removed additional ~50 lines of custom state management code
- ✅ Per-flyer item caching (items cached separately for each flyer)
- ✅ Longer cache times for infrequently changing data (master items)
- ✅ Automatic query disabling when dependencies are not met

### Phase 3: Mutations (✅ Complete - 2026-01-08)

**Files Created:**

- [src/hooks/mutations/useAddWatchedItemMutation.ts](../../src/hooks/mutations/useAddWatchedItemMutation.ts) - Add watched item mutation
- [src/hooks/mutations/useRemoveWatchedItemMutation.ts](../../src/hooks/mutations/useRemoveWatchedItemMutation.ts) - Remove watched item mutation
- [src/hooks/mutations/useCreateShoppingListMutation.ts](../../src/hooks/mutations/useCreateShoppingListMutation.ts) - Create shopping list mutation
- [src/hooks/mutations/useDeleteShoppingListMutation.ts](../../src/hooks/mutations/useDeleteShoppingListMutation.ts) - Delete shopping list mutation
- [src/hooks/mutations/useAddShoppingListItemMutation.ts](../../src/hooks/mutations/useAddShoppingListItemMutation.ts) - Add shopping list item mutation
- [src/hooks/mutations/useUpdateShoppingListItemMutation.ts](../../src/hooks/mutations/useUpdateShoppingListItemMutation.ts) - Update shopping list item mutation
- [src/hooks/mutations/useRemoveShoppingListItemMutation.ts](../../src/hooks/mutations/useRemoveShoppingListItemMutation.ts) - Remove shopping list item mutation
- [src/hooks/mutations/index.ts](../../src/hooks/mutations/index.ts) - Barrel export for all mutation hooks

**Benefits Achieved:**

- ✅ Standardized mutation pattern across all data modifications
- ✅ Automatic cache invalidation after successful mutations
- ✅ Built-in success/error notifications
- ✅ Consistent error handling
- ✅ Full TypeScript type safety
- ✅ Comprehensive documentation with usage examples

**See**: [plans/adr-0005-phase-3-summary.md](../../plans/adr-0005-phase-3-summary.md) for detailed documentation

### Phase 4: Hook Refactoring (✅ Complete)

**Goal:** Refactor user-facing hooks to use TanStack Query mutation hooks.

**Files Modified:**

- [src/hooks/useWatchedItems.tsx](../../src/hooks/useWatchedItems.tsx) - Refactored to use mutation hooks
- [src/hooks/useShoppingLists.tsx](../../src/hooks/useShoppingLists.tsx) - Refactored to use mutation hooks
- [src/contexts/UserDataContext.ts](../../src/contexts/UserDataContext.ts) - Clean read-only interface (no setters)
- [src/providers/UserDataProvider.tsx](../../src/providers/UserDataProvider.tsx) - Uses query hooks, no setter stubs

**Benefits Achieved:**

- ✅ Both hooks now use TanStack Query mutations
- ✅ Automatic cache invalidation after mutations
- ✅ Consistent error handling via mutation hooks
- ✅ Clean context interface (read-only server state)
- ✅ Backward compatible API for hook consumers

### Phase 5: Admin Features (✅ Complete)

**Goal:** Create query hooks for admin features.

**Files Created:**

- [src/hooks/queries/useActivityLogQuery.ts](../../src/hooks/queries/useActivityLogQuery.ts) - Activity log with pagination
- [src/hooks/queries/useApplicationStatsQuery.ts](../../src/hooks/queries/useApplicationStatsQuery.ts) - Application statistics
- [src/hooks/queries/useSuggestedCorrectionsQuery.ts](../../src/hooks/queries/useSuggestedCorrectionsQuery.ts) - Corrections data
- [src/hooks/queries/useCategoriesQuery.ts](../../src/hooks/queries/useCategoriesQuery.ts) - Categories (public endpoint)

**Components Migrated:**

- [src/pages/admin/ActivityLog.tsx](../../src/pages/admin/ActivityLog.tsx) - Uses useActivityLogQuery
- [src/pages/admin/AdminStatsPage.tsx](../../src/pages/admin/AdminStatsPage.tsx) - Uses useApplicationStatsQuery
- [src/pages/admin/CorrectionsPage.tsx](../../src/pages/admin/CorrectionsPage.tsx) - Uses useSuggestedCorrectionsQuery, useMasterItemsQuery, useCategoriesQuery

**Benefits Achieved:**

- ✅ Automatic caching of admin data
- ✅ Parallel fetching (CorrectionsPage fetches 3 queries simultaneously)
- ✅ Consistent stale times (30s to 2 min based on data volatility)
- ✅ Shared cache across components (useMasterItemsQuery reused)

### Phase 6: Analytics Features (✅ Complete - 2026-01-10)

**Goal:** Migrate analytics and deals features.

**Files Created:**

- [src/hooks/queries/useBestSalePricesQuery.ts](../../src/hooks/queries/useBestSalePricesQuery.ts) - Best sale prices for watched items
- [src/hooks/queries/useFlyerItemsForFlyersQuery.ts](../../src/hooks/queries/useFlyerItemsForFlyersQuery.ts) - Batch fetch items for multiple flyers
- [src/hooks/queries/useFlyerItemCountQuery.ts](../../src/hooks/queries/useFlyerItemCountQuery.ts) - Count items across flyers

**Files Modified:**

- [src/pages/MyDealsPage.tsx](../../src/pages/MyDealsPage.tsx) - Now uses useBestSalePricesQuery
- [src/hooks/useActiveDeals.tsx](../../src/hooks/useActiveDeals.tsx) - Refactored to use TanStack Query hooks

**Benefits Achieved:**

- ✅ Removed useApi dependency from analytics features
- ✅ Automatic caching of deal data (2-5 minute stale times)
- ✅ Consistent error handling via TanStack Query
- ✅ Batch fetching for flyer items (single query for multiple flyers)

### Phase 7: Cleanup (✅ Complete - 2026-01-10)

**Goal:** Remove legacy hooks once migration is complete.

**Files Created:**

- [src/hooks/queries/useUserAddressQuery.ts](../../src/hooks/queries/useUserAddressQuery.ts) - User address fetching
- [src/hooks/queries/useAuthProfileQuery.ts](../../src/hooks/queries/useAuthProfileQuery.ts) - Auth profile fetching
- [src/hooks/mutations/useGeocodeMutation.ts](../../src/hooks/mutations/useGeocodeMutation.ts) - Address geocoding

**Files Modified:**

- [src/hooks/useProfileAddress.ts](../../src/hooks/useProfileAddress.ts) - Refactored to use TanStack Query
- [src/providers/AuthProvider.tsx](../../src/providers/AuthProvider.tsx) - Refactored to use TanStack Query

**Files Removed:**

- ~~src/hooks/useApi.ts~~ - Legacy hook removed
- ~~src/hooks/useApi.test.ts~~ - Test file removed
- ~~src/hooks/useApiOnMount.ts~~ - Legacy hook removed
- ~~src/hooks/useApiOnMount.test.ts~~ - Test file removed

**Benefits Achieved:**

- ✅ Removed all legacy `useApi` and `useApiOnMount` hooks
- ✅ Complete TanStack Query coverage for all data fetching
- ✅ Consistent error handling across the entire application
- ✅ Unified caching strategy for all server state

### Phase 8: Additional Component Migration (✅ Complete - 2026-01-10)

**Goal:** Migrate remaining components with manual data fetching to TanStack Query.

**Files Created:**

- [src/hooks/queries/useUserProfileDataQuery.ts](../../src/hooks/queries/useUserProfileDataQuery.ts) - Combined user profile + achievements query
- [src/hooks/queries/useLeaderboardQuery.ts](../../src/hooks/queries/useLeaderboardQuery.ts) - Public leaderboard data
- [src/hooks/queries/usePriceHistoryQuery.ts](../../src/hooks/queries/usePriceHistoryQuery.ts) - Historical price data for watched items

**Files Modified:**

- [src/hooks/useUserProfileData.ts](../../src/hooks/useUserProfileData.ts) - Refactored to use useUserProfileDataQuery
- [src/components/Leaderboard.tsx](../../src/components/Leaderboard.tsx) - Refactored to use useLeaderboardQuery
- [src/features/charts/PriceHistoryChart.tsx](../../src/features/charts/PriceHistoryChart.tsx) - Refactored to use usePriceHistoryQuery

**Benefits Achieved:**

- ✅ Parallel fetching for profile + achievements data
- ✅ Public leaderboard cached with 2-minute stale time
- ✅ Price history cached with 10-minute stale time (data changes infrequently)
- ✅ Backward-compatible setProfile function via queryClient.setQueryData
- ✅ Stable query keys with sorted IDs for price history

## Migration Status

Current Coverage: **100% complete**

| Category                      | Total | Migrated | Status  |
| ----------------------------- | ----- | -------- | ------- |
| Query Hooks (User)            | 7     | 7        | ✅ 100% |
| Query Hooks (Admin)           | 4     | 4        | ✅ 100% |
| Query Hooks (Analytics)       | 3     | 3        | ✅ 100% |
| Query Hooks (Phase 8)         | 3     | 3        | ✅ 100% |
| Mutation Hooks                | 8     | 8        | ✅ 100% |
| User Hooks                    | 2     | 2        | ✅ 100% |
| Analytics Features            | 2     | 2        | ✅ 100% |
| Component Migration (Phase 8) | 3     | 3        | ✅ 100% |
| Legacy Hook Cleanup           | 4     | 4        | ✅ 100% |

**Completed:**

- ✅ Core query hooks (flyers, flyerItems, masterItems, watchedItems, shoppingLists)
- ✅ Admin query hooks (activityLog, applicationStats, suggestedCorrections, categories)
- ✅ Analytics query hooks (bestSalePrices, flyerItemsForFlyers, flyerItemCount)
- ✅ Auth/Profile query hooks (authProfile, userAddress)
- ✅ Phase 8 query hooks (userProfileData, leaderboard, priceHistory)
- ✅ All mutation hooks (watched items, shopping lists, geocode)
- ✅ Provider refactoring (AppProviders, FlyersProvider, MasterItemsProvider, UserDataProvider, AuthProvider)
- ✅ User hooks refactoring (useWatchedItems, useShoppingLists, useProfileAddress, useUserProfileData)
- ✅ Admin component migration (ActivityLog, AdminStatsPage, CorrectionsPage)
- ✅ Analytics features (MyDealsPage, useActiveDeals)
- ✅ Component migration (Leaderboard, PriceHistoryChart)
- ✅ Legacy hooks removed (useApi, useApiOnMount)

See [plans/adr-0005-master-migration-status.md](../../plans/adr-0005-master-migration-status.md) for complete tracking of all components.

## Implementation Guide

See [plans/adr-0005-implementation-plan.md](../../plans/adr-0005-implementation-plan.md) for detailed implementation steps.
