Skip to content

Mutations & Queries

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.

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' }),
};
const { data, isLoading } = useQuery({
queryKey: ['teacher-sessions', teacherId],
queryFn: () => api.get<Session[]>('/teacher/sessions'),
});
Key PatternData
['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
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')),
});

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
},
});
  1. Cancel in-flight queries
  2. Create snapshot (createSnapshot)
  3. Apply optimistic cache update
  4. On error: rollback via restoreSnapshot
  5. On settle: invalidate all queryKeys
  • 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

updateCalendarEvent prefix-matches ['teacher-calendar', ...] across date ranges for optimistic calendar updates.

HelperPurpose
createSnapshot(queryClient, queryKeys)Save current cache state
restoreSnapshot(queryClient, snapshot)Rollback to saved state
updateCalendarEvent(queryClient, ...)Update calendar cache entries