Mutations & Queries
TanStack Query Setup
Section titled “TanStack Query Setup”PinTeach uses TanStack Query 5 for all server state management. The API client is a thin fetch wrapper in apps/web/src/lib/api.ts.
API Client
Section titled “API Client”export const api = { get: <T>(path: string) => apiRequest<T>(path), post: <T>(path: string, body: unknown) => apiRequest<T>(path, { method: 'POST', body: JSON.stringify(body) }), patch: <T>(path: string, body: unknown) => apiRequest<T>(path, { method: 'PATCH', body: JSON.stringify(body) }), put: <T>(path: string, body: unknown) => apiRequest<T>(path, { method: 'PUT', body: JSON.stringify(body) }), delete: <T>(path: string) => apiRequest<T>(path, { method: 'DELETE' }),};Query Pattern
Section titled “Query Pattern”const { data, isLoading } = useQuery({ queryKey: ['teacher-sessions', teacherId], queryFn: () => api.get<Session[]>('/teacher/sessions'),});Common Query Keys
Section titled “Common Query Keys”| Key Pattern | Data |
|---|---|
['teacher-sessions'] | Session list |
['teacher-calendar', start, end] | Calendar events |
['teacher-students'] | Student list |
['teacher-services'] | Service list |
['teacher-reviews'] | Review list |
['teacher-dashboard'] | Dashboard KPIs |
['teacher-payments'] | Payment history |
Mutation Pattern
Section titled “Mutation Pattern”const mutation = useMutation({ mutationFn: (input: CreateInput) => api.post('/teacher/sessions', input), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['teacher-sessions'] }); toast.success(t('sessions.created')); }, onError: () => toast.error(t('common.error')),});Optimistic Mutations
Section titled “Optimistic Mutations”For frequent, low-risk actions, use useOptimisticMutation from hooks/mutations/:
import { useOptimisticMutation } from '@/hooks/mutations';
const mutation = useOptimisticMutation({ mutationFn: (id: string) => api.post(`/teacher/sessions/${id}/complete`), queryKeys: [['teacher-sessions'], ['teacher-calendar']], onOptimisticUpdate: ({ queryClient, snapshot }) => { // Update cache immediately },});How It Works
Section titled “How It Works”- Cancel in-flight queries
- Create snapshot (
createSnapshot) - Apply optimistic cache update
- On error: rollback via
restoreSnapshot - On settle: invalidate all
queryKeys
Available Optimistic Hooks (11)
Section titled “Available Optimistic Hooks (11)”- Complete session
- Mark no-show
- Toggle favorite
- Move items (materials)
- Reorder tags
- Reorder categories
- Submit mood
- Read notification
- Update review status
- Bulk delete materials
- Bulk tag materials
Calendar Update Helper
Section titled “Calendar Update Helper”updateCalendarEvent prefix-matches ['teacher-calendar', ...] across date ranges for optimistic calendar updates.
Helpers
Section titled “Helpers”| Helper | Purpose |
|---|---|
createSnapshot(queryClient, queryKeys) | Save current cache state |
restoreSnapshot(queryClient, snapshot) | Rollback to saved state |
updateCalendarEvent(queryClient, ...) | Update calendar cache entries |