Skip to content

feat(frontend): separate server state from mutable UI state - #25

Open
Fabluchy wants to merge 1 commit into
Vaulty-X:mainfrom
Fabluchy:feat/server-state-separation-19
Open

feat(frontend): separate server state from mutable UI state#25
Fabluchy wants to merge 1 commit into
Vaulty-X:mainfrom
Fabluchy:feat/server-state-separation-19

Conversation

@Fabluchy

Copy link
Copy Markdown

Summary

Resolves the architectural issue where Zustand was used as both a UI state store and a server data cache for financial data (vault balances, streaks, discipline scores). This created race conditions between optimistic updates and refreshes, and prevented proper cache invalidation when the wallet or network changed.

Changes

New dependencies

  • @tanstack/react-query@^5 — server-state caching layer

New files

File Purpose
src/lib/QueryProvider.tsx Sets up QueryClient with sensible defaults (30 s stale time, 5 min GC, 2 retries, window-focus refetch) and wraps the app
src/hooks/useStreak.ts useStreak, useDisciplineScore, useAchievements hooks via React Query

Modified files

File What changed
src/app/layout.tsx Wraps children in <QueryProvider>
src/types/index.ts Added UIPreferences type, queryKeys factory; dates changed from Date to string for safe JSON round-trips
src/lib/api.ts Replaced class methods with plain async functions covering vaults, streak, discipline score, achievements, and fiat flows
src/stores/index.ts Zustand now stores only wallet connection state and UIPreferences; financial data removed entirely; uses persist middleware
src/hooks/useVault.ts Replaced Zustand reads with useVaults, useVaultById, useCreateVault, useDeposit, useWithdraw; mutations invalidate relevant query keys
src/hooks/useWallet.ts connect/disconnect invalidate all financial query caches, preventing stale data from bleeding across wallet sessions
src/features/vaults/VaultList.tsx Full implementation: loading skeletons, error state with retry button, empty state, vault progress cards
src/features/streaks/StreakTracker.tsx Full implementation: stat cards with loading skeletons, error state, savings calendar (last 30 days)
src/lib/stellar.ts Fixed pre-existing type error (invalid StellarWallet named import that blocked the build)

Acceptance criteria

  • Server-state query/cache layer introduced — TanStack Query v5 with QueryProvider in root layout
  • Financial data invalidated on wallet/account/network changesuseWallet clears all financial query caches on connect and disconnect
  • Only safe UI preferences persisted — Zustand persist middleware is scoped to UIPreferences and wallet connection state; no vault balances, streaks, or scores
  • Race conditions eliminated — no optimistic Zustand updates for financial data; server is the single source of truth; cache invalidation is explicit and tied to mutations

Testing

cd Frontend && npm run build   # exits 0 — compiled + type-checked successfully

Closes #19

- Install @tanstack/react-query v5 as the server-state caching layer
- Add QueryProvider wrapper (lib/QueryProvider.tsx) and mount in layout.tsx
- Refactor lib/api.ts: replace class methods with plain async functions
  covering vaults, streak, discipline score, achievements, and fiat flows
- Refactor types/index.ts: introduce UIPreferences type and queryKeys
  factory; keep server types (Vault, Streak, DisciplineScore, etc.) separate
- Refactor stores/index.ts: Zustand now stores only wallet connection state
  and UIPreferences (persisted via zustand/middleware persist); all financial
  data removed from the store
- Refactor hooks/useVault.ts: useVaults, useVaultById, useCreateVault,
  useDeposit, useWithdraw all use useQuery / useMutation; mutations
  invalidate the relevant query keys on success
- Refactor hooks/useWallet.ts: connect/disconnect invalidate all financial
  query caches to prevent stale data bleeding across wallet sessions
- Add hooks/useStreak.ts: useStreak, useDisciplineScore, useAchievements
- Update features/vaults/VaultList.tsx: full implementation with loading
  skeletons, error state with retry, empty state, and vault cards
- Update features/streaks/StreakTracker.tsx: full implementation with stat
  cards, loading skeletons, error state, and savings calendar
- Fix lib/stellar.ts: remove invalid StellarWallet named import (pre-existing
  type error that blocked the build)

Closes Vaulty-X#19
@Nabeelahh

Copy link
Copy Markdown
Contributor

please resolve conflicts

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.

[Frontend] Separate server data from mutable UI state

2 participants