> ## Documentation Index
> Fetch the complete documentation index at: https://system.muzemus.online/llms.txt
> Use this file to discover all available pages before exploring further.

# React Query

> How the frontend uses TanStack React Query for server state management

## React Query in MUZE

The frontend uses **TanStack React Query v5** for all server state management. This replaces traditional Redux/Zustand patterns for API data.

## Provider setup

```typescript theme={null}
// frontend/src/App.tsx
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 1000 * 60 * 2,   // 2 minutes
      retry: 1,
      refetchOnWindowFocus: false,
    },
  },
});
```

The provider wraps the app in `App.tsx` together with `SessionProvider` and the toast mount point.

## Query patterns

### Fetching data

```typescript theme={null}
// Custom hook using React Query
export function useEmployees(storeId?: string) {
  return useQuery({
    queryKey: ['employees', storeId],
    queryFn: () => api.get(`/employees`, { params: { storeId } }),
    enabled: !!storeId,
  });
}
```

### Creating data

```typescript theme={null}
export function useCreateEmployee() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: CreateEmployeeDto) =>
      api.post('/employees', data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['employees'] });
    },
  });
}
```

### Updating data

```typescript theme={null}
export function useUpdateOrderStatus() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, status }: { id: string; status: OrderStatus }) =>
      api.patch(`/orders/${id}/status`, { status }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['orders'] });
    },
  });
}
```

## Cache invalidation strategy

| Action        | Invalidation                               |
| ------------- | ------------------------------------------ |
| Create entity | Invalidate list query for that entity type |
| Update entity | Invalidate both list and detail queries    |
| Delete entity | Invalidate list query                      |
| Import CSV    | Invalidate list query                      |
| Status change | Invalidate order list and detail queries   |

## Query key conventions

```typescript theme={null}
// List queries
['employees', storeId]
['orders', { storeId, status }]
['rule-sets', clientId]

// Detail queries
['employee', employeeId]
['order', orderId]

// Aggregation queries
['reports', 'store-ops', { dateRange }]
['entitlements', employeeId, categoryId]
```

## Error handling

React Query errors are handled at the component level:

```typescript theme={null}
const { data, error, isLoading } = useEmployees();

if (isLoading) return <LoadingSpinner />;
if (error) return <ErrorMessage error={error} />;
if (!data) return <EmptyState />;

return <EmployeeTable employees={data} />;
```

## Optimistic updates

For critical UI responsiveness, some mutations use optimistic updates:

```typescript theme={null}
return useMutation({
  mutationFn: updateOrderStatus,
  onMutate: async (newStatus) => {
    await queryClient.cancelQueries({ queryKey: ['orders'] });
    const previous = queryClient.getQueryData(['orders']);
    queryClient.setQueryData(['orders'], (old) =>
      old.map(order => order.id === newStatus.id
        ? { ...order, status: newStatus.status }
        : order
      )
    );
    return { previous };
  },
  onError: (err, newStatus, context) => {
    queryClient.setQueryData(['orders'], context.previous);
  },
  onSettled: () => {
    queryClient.invalidateQueries({ queryKey: ['orders'] });
  },
});
```

## What React Query does not manage

| State                      | Managed by                    |
| -------------------------- | ----------------------------- |
| Authentication session     | better-auth + local state     |
| UI state (modals, drawers) | React component state         |
| Form state                 | React Hook Form               |
| Theme / dark mode          | CSS variables + React context |
| Global app settings        | React context                 |
