# ADR-0005 Master Migration Status **Last Updated**: 2026-01-08 This document tracks the complete migration status of all data fetching patterns in the application to TanStack Query (React Query) as specified in ADR-0005. ## Migration Overview | Category | Total | Migrated | Remaining | % Complete | |----------|-------|----------|-----------|------------| | **User Features** | 5 queries + 7 mutations | 12/12 | 0 | ✅ 100% | | **Admin Features** | 3 queries | 0/3 | 3 | ❌ 0% | | **Analytics Features** | 2 queries | 0/2 | 2 | ❌ 0% | | **Legacy Hooks** | 3 hooks | 0/3 | 3 | ❌ 0% | | **TOTAL** | 20 items | 12/20 | 8 | 🟡 60% | --- ## ✅ COMPLETED: User-Facing Features (Phase 1-3) ### Query Hooks (5) | Hook | File | Query Key | Status | Phase | |------|------|-----------|--------|-------| | useFlyersQuery | [src/hooks/queries/useFlyersQuery.ts](../src/hooks/queries/useFlyersQuery.ts) | `['flyers', { limit, offset }]` | ✅ Done | 1 | | useFlyerItemsQuery | [src/hooks/queries/useFlyerItemsQuery.ts](../src/hooks/queries/useFlyerItemsQuery.ts) | `['flyer-items', flyerId]` | ✅ Done | 2 | | useMasterItemsQuery | [src/hooks/queries/useMasterItemsQuery.ts](../src/hooks/queries/useMasterItemsQuery.ts) | `['master-items']` | ✅ Done | 2 | | useWatchedItemsQuery | [src/hooks/queries/useWatchedItemsQuery.ts](../src/hooks/queries/useWatchedItemsQuery.ts) | `['watched-items']` | ✅ Done | 1 | | useShoppingListsQuery | [src/hooks/queries/useShoppingListsQuery.ts](../src/hooks/queries/useShoppingListsQuery.ts) | `['shopping-lists']` | ✅ Done | 1 | ### Mutation Hooks (7) | Hook | File | Invalidates | Status | Phase | |------|------|-------------|--------|-------| | useAddWatchedItemMutation | [src/hooks/mutations/useAddWatchedItemMutation.ts](../src/hooks/mutations/useAddWatchedItemMutation.ts) | `['watched-items']` | ✅ Done | 3 | | useRemoveWatchedItemMutation | [src/hooks/mutations/useRemoveWatchedItemMutation.ts](../src/hooks/mutations/useRemoveWatchedItemMutation.ts) | `['watched-items']` | ✅ Done | 3 | | useCreateShoppingListMutation | [src/hooks/mutations/useCreateShoppingListMutation.ts](../src/hooks/mutations/useCreateShoppingListMutation.ts) | `['shopping-lists']` | ✅ Done | 3 | | useDeleteShoppingListMutation | [src/hooks/mutations/useDeleteShoppingListMutation.ts](../src/hooks/mutations/useDeleteShoppingListMutation.ts) | `['shopping-lists']` | ✅ Done | 3 | | useAddShoppingListItemMutation | [src/hooks/mutations/useAddShoppingListItemMutation.ts](../src/hooks/mutations/useAddShoppingListItemMutation.ts) | `['shopping-lists']` | ✅ Done | 3 | | useUpdateShoppingListItemMutation | [src/hooks/mutations/useUpdateShoppingListItemMutation.ts](../src/hooks/mutations/useUpdateShoppingListItemMutation.ts) | `['shopping-lists']` | ✅ Done | 3 | | useRemoveShoppingListItemMutation | [src/hooks/mutations/useRemoveShoppingListItemMutation.ts](../src/hooks/mutations/useRemoveShoppingListItemMutation.ts) | `['shopping-lists']` | ✅ Done | 3 | ### Providers Migrated (4) | Provider | Uses | Status | |----------|------|--------| | [AppProviders.tsx](../src/providers/AppProviders.tsx) | QueryClientProvider wrapper | ✅ Done | | [FlyersProvider.tsx](../src/providers/FlyersProvider.tsx) | useFlyersQuery | ✅ Done | | [MasterItemsProvider.tsx](../src/providers/MasterItemsProvider.tsx) | useMasterItemsQuery | ✅ Done | | [UserDataProvider.tsx](../src/providers/UserDataProvider.tsx) | useWatchedItemsQuery + useShoppingListsQuery | ✅ Done | --- ## ❌ NOT MIGRATED: Admin & Analytics Features ### High Priority - Admin Features | Feature | Component/Hook | Current Pattern | API Calls | Priority | |---------|----------------|-----------------|-----------|----------| | **Activity Log** | [ActivityLog.tsx](../src/components/ActivityLog.tsx) | useState + useEffect | `fetchActivityLog(20, 0)` | 🔴 HIGH | | **Admin Stats** | [AdminStatsPage.tsx](../src/pages/AdminStatsPage.tsx) | useState + useEffect | `getApplicationStats()` | 🔴 HIGH | | **Corrections** | [CorrectionsPage.tsx](../src/pages/CorrectionsPage.tsx) | useState + useEffect + Promise.all | `getSuggestedCorrections()`, `fetchMasterItems()`, `fetchCategories()` | 🔴 HIGH | **Issues:** - Manual state management with useState/useEffect - No caching - data refetches on every mount - No automatic refetching or background updates - Manual loading/error state handling - Duplicate API calls (CorrectionsPage fetches master items separately) **Recommended Query Hooks to Create:** ```typescript // src/hooks/queries/useActivityLogQuery.ts queryKey: ['activity-log', { limit, offset }] staleTime: 30 seconds (frequently updated) // src/hooks/queries/useApplicationStatsQuery.ts queryKey: ['application-stats'] staleTime: 2 minutes (changes moderately) // src/hooks/queries/useSuggestedCorrectionsQuery.ts queryKey: ['suggested-corrections'] staleTime: 1 minute // src/hooks/queries/useCategoriesQuery.ts queryKey: ['categories'] staleTime: 10 minutes (rarely changes) ``` ### Medium Priority - Analytics Features | Feature | Component/Hook | Current Pattern | API Calls | Priority | |---------|----------------|-----------------|-----------|----------| | **My Deals** | [MyDealsPage.tsx](../src/pages/MyDealsPage.tsx) | useState + useEffect | `fetchBestSalePrices()` | 🟡 MEDIUM | | **Active Deals** | [useActiveDeals.tsx](../src/hooks/useActiveDeals.tsx) | useApi hook | `countFlyerItemsForFlyers()`, `fetchFlyerItemsForFlyers()` | 🟡 MEDIUM | **Issues:** - useActiveDeals uses old `useApi` hook pattern - MyDealsPage has manual state management - No caching for best sale prices - No relationship to watched-items cache (could be optimized) **Recommended Query Hooks to Create:** ```typescript // src/hooks/queries/useBestSalePricesQuery.ts queryKey: ['best-sale-prices', watchedItemIds] staleTime: 2 minutes // Should invalidate when flyers or flyer-items update // Refactor useActiveDeals to use TanStack Query // Could share cache with flyer-items query ``` ### Low Priority - Voice Lab | Feature | Component | Current Pattern | Priority | |---------|-----------|-----------------|----------| | **Voice Lab** | [VoiceLabPage.tsx](../src/pages/VoiceLabPage.tsx) | Direct async/await | 🟢 LOW | **Notes:** - Event-driven API calls (not data fetching) - Speech generation and voice sessions - Mutation-like operations, not query-like - Could create mutations but not critical for caching --- ## ⚠️ LEGACY HOOKS STILL IN USE ### Hooks to Deprecate/Remove | Hook | File | Used By | Status | |------|------|---------|--------| | **useApi** | [src/hooks/useApi.ts](../src/hooks/useApi.ts) | useActiveDeals, useWatchedItems, useShoppingLists | ⚠️ Active | | **useApiOnMount** | [src/hooks/useApiOnMount.ts](../src/hooks/useApiOnMount.ts) | None (deprecated) | ⚠️ Remove | | **useInfiniteQuery** | [src/hooks/useInfiniteQuery.ts](../src/hooks/useInfiniteQuery.ts) | None (deprecated) | ⚠️ Remove | **Plan:** - Phase 4: Refactor useWatchedItems/useShoppingLists to use TanStack Query mutations - Phase 5: Refactor useActiveDeals to use TanStack Query - Phase 6: Remove useApi, useApiOnMount, custom useInfiniteQuery --- ## 📊 MIGRATION PHASES ### ✅ Phase 1: Core Queries (Complete) - Infrastructure setup (QueryClientProvider) - Flyers, Watched Items, Shopping Lists queries - Providers refactored ### ✅ Phase 2: Additional Queries (Complete) - Master Items query - Flyer Items query - Per-resource caching strategies ### ✅ Phase 3: Mutations (Complete) - All watched items mutations - All shopping list mutations - Automatic cache invalidation ### 🔄 Phase 4: Hook Refactoring (Planned) - [ ] Refactor useWatchedItems to use mutation hooks - [ ] Refactor useShoppingLists to use mutation hooks - [ ] Remove deprecated setters from context ### ⏳ Phase 5: Admin Features (Not Started) - [ ] Create useActivityLogQuery - [ ] Create useApplicationStatsQuery - [ ] Create useSuggestedCorrectionsQuery - [ ] Create useCategoriesQuery - [ ] Migrate ActivityLog.tsx - [ ] Migrate AdminStatsPage.tsx - [ ] Migrate CorrectionsPage.tsx ### ⏳ Phase 6: Analytics Features (Not Started) - [ ] Create useBestSalePricesQuery - [ ] Migrate MyDealsPage.tsx - [ ] Refactor useActiveDeals to use TanStack Query ### ⏳ Phase 7: Cleanup (Not Started) - [ ] Remove useApi hook - [ ] Remove useApiOnMount hook - [ ] Remove custom useInfiniteQuery hook - [ ] Remove all stub implementations - [ ] Update all tests --- ## 🎯 RECOMMENDED NEXT STEPS ### Option A: Complete User Features First (Phase 4) Focus on finishing the user-facing feature migration by refactoring the remaining custom hooks. This provides a complete, polished user experience. **Pros:** - Completes the user-facing story - Simplifies codebase for user features - Sets pattern for admin features **Cons:** - Admin features still use old patterns ### Option B: Migrate Admin Features (Phase 5) Create query hooks for admin features to improve admin user experience and establish complete ADR-0005 coverage. **Pros:** - Faster admin pages with caching - Consistent patterns across entire app - Better for admin users **Cons:** - User-facing hooks still partially old pattern ### Option C: Parallel Migration (Phase 4 + 5) Work on both user hook refactoring and admin feature migration simultaneously. **Pros:** - Fastest path to complete migration - Comprehensive coverage quickly **Cons:** - Larger scope, more testing needed --- ## 📝 NOTES ### Query Key Organization Currently using literal strings for query keys. Consider creating a centralized query keys file: ```typescript // src/config/queryKeys.ts export const queryKeys = { flyers: (limit: number, offset: number) => ['flyers', { limit, offset }] as const, flyerItems: (flyerId: number) => ['flyer-items', flyerId] as const, masterItems: () => ['master-items'] as const, watchedItems: () => ['watched-items'] as const, shoppingLists: () => ['shopping-lists'] as const, // Add admin keys activityLog: (limit: number, offset: number) => ['activity-log', { limit, offset }] as const, applicationStats: () => ['application-stats'] as const, suggestedCorrections: () => ['suggested-corrections'] as const, categories: () => ['categories'] as const, bestSalePrices: (itemIds: number[]) => ['best-sale-prices', itemIds] as const, }; ``` ### Cache Invalidation Strategy Admin features may need different invalidation strategies: - Activity log should refetch after mutations - Stats should refetch after significant operations - Corrections should refetch after approving/rejecting ### Stale Time Recommendations | Data Type | Stale Time | Reasoning | |-----------|------------|-----------| | Master Items | 10 minutes | Rarely changes | | Categories | 10 minutes | Rarely changes | | Flyers | 2 minutes | Moderate changes | | Flyer Items | 5 minutes | Static once created | | User Lists | 1 minute | Frequent changes | | Admin Stats | 2 minutes | Moderate changes | | Activity Log | 30 seconds | Frequently updated | | Corrections | 1 minute | Moderate changes | | Best Prices | 2 minutes | Recalculated periodically | --- ## 📚 DOCUMENTATION - [ADR-0005 Main Document](../docs/adr/0005-frontend-state-management-and-server-cache-strategy.md) - [Phase 1 Implementation Plan](./adr-0005-implementation-plan.md) - [Phase 2 Summary](./adr-0005-phase-2-summary.md) - [Phase 3 Summary](./adr-0005-phase-3-summary.md) - [This Document](./adr-0005-master-migration-status.md)