Files
ColaFlow/docs/plans/sprint_1_story_2_task_2.md
Yaojia Wang 08b317e789
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Add trace files.
2025-11-04 23:28:56 +01:00

2.3 KiB

Task 6: Build React Query Hooks

Task ID: TASK-006 | Story: STORY-002 | Sprint: Sprint 1 Estimated Hours: 3h | Assignee: Frontend Developer 2 | Priority: P0 | Status: Not Started

Task Description

Create React Query hooks for Epic/Story/Task with query caching, mutations, and optimistic updates.

Implementation

File: src/hooks/useEpics.ts

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { epicApiClient } from '../api/clients/EpicApiClient';

export const useEpics = (projectId: string) => {
  return useQuery({
    queryKey: ['epics', projectId],
    queryFn: () => epicApiClient.getAll(projectId),
    staleTime: 60000 // 1 minute
  });
};

export const useCreateEpic = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: epicApiClient.create,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['epics'] });
    }
  });
};

export const useUpdateEpic = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, dto }) => epicApiClient.update(id, dto),
    onMutate: async ({ id, dto }) => {
      // Optimistic update
      await queryClient.cancelQueries({ queryKey: ['epics', id] });
      const previous = queryClient.getQueryData(['epics', id]);
      queryClient.setQueryData(['epics', id], dto);
      return { previous };
    },
    onError: (err, vars, context) => {
      queryClient.setQueryData(['epics', vars.id], context.previous);
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['epics'] });
    }
  });
};

export const useDeleteEpic = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: epicApiClient.delete,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['epics'] });
    }
  });
};

Acceptance Criteria

  • useEpics/Stories/Tasks query hooks
  • useCreate/Update/Delete mutation hooks
  • Query cache invalidation working
  • Optimistic updates for better UX
  • Loading and error states handled

Deliverables

  1. useEpics.ts with 4 hooks
  2. useStories.ts with 4 hooks
  3. useTasks.ts with 4 hooks
  4. Unit tests (12+ tests)

Status: Not Started | Created: 2025-11-04