Files
ColaFlow/docs/plans/sprint_1_story_3_task_3.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

3.4 KiB

Task 11: Integrate SignalR Real-time Updates

Task ID: TASK-011 | Story: STORY-003 | Sprint: Sprint 1 Estimated Hours: 3h | Assignee: Frontend Developer 1 | Priority: P1 | Status: Not Started

Task Description

Connect Kanban board to SignalR event handlers for real-time updates when Epic/Story/Task changes occur.

Implementation

Update KanbanBoard.tsx (2h)

import { useEffect } from 'react';
import { useSignalRContext } from '../services/signalr/SignalRContext';
import { useQueryClient } from '@tanstack/react-query';

export const KanbanBoard: React.FC = () => {
  const { projectId } = useParams();
  const queryClient = useQueryClient();
  const { service, isConnected } = useSignalRContext();

  // Subscribe to real-time events
  useEffect(() => {
    if (!isConnected || !service) return;

    const handlers = service.getEventHandlers();
    if (!handlers) return;

    // Epic events
    const unsubEpicCreated = handlers.subscribe('epic:created', (event) => {
      queryClient.invalidateQueries(['epics', projectId]);
    });

    const unsubEpicUpdated = handlers.subscribe('epic:updated', (event) => {
      queryClient.setQueryData(['epics', projectId], (old: Epic[]) => {
        return old.map(e => e.id === event.epicId ? { ...e, ...event } : e);
      });
    });

    const unsubEpicDeleted = handlers.subscribe('epic:deleted', (event) => {
      queryClient.setQueryData(['epics', projectId], (old: Epic[]) => {
        return old.filter(e => e.id !== event.epicId);
      });
    });

    // Story events (similar)
    const unsubStoryCreated = handlers.subscribe('story:created', (event) => {
      queryClient.invalidateQueries(['stories', projectId]);
    });

    // Task events (similar)
    const unsubTaskCreated = handlers.subscribe('task:created', (event) => {
      queryClient.invalidateQueries(['tasks', projectId]);
    });

    const unsubTaskStatusChanged = handlers.subscribe('task:statusChanged', (event) => {
      // Animate card movement between columns
      queryClient.setQueryData(['tasks', projectId], (old: Task[]) => {
        return old.map(t => t.id === event.taskId ? { ...t, status: event.newStatus } : t);
      });
    });

    // Cleanup subscriptions
    return () => {
      unsubEpicCreated();
      unsubEpicUpdated();
      unsubEpicDeleted();
      unsubStoryCreated();
      unsubTaskCreated();
      unsubTaskStatusChanged();
    };
  }, [isConnected, service, projectId, queryClient]);

  // ... rest of component
};

Add Card Animation (1h)

// Use framer-motion for smooth animations
import { motion } from 'framer-motion';

export const KanbanCard: React.FC<{ item: any }> = ({ item }) => {
  return (
    <motion.div
      layout
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -20 }}
      transition={{ duration: 0.3 }}
      className="kanban-card"
    >
      {/* Card content */}
    </motion.div>
  );
};

Acceptance Criteria

  • Kanban updates automatically on SignalR events
  • All 13 event types handled
  • Card animations smooth (60 FPS)
  • No duplicate cards after updates
  • Optimistic updates working

Deliverables

  1. SignalR integration in KanbanBoard.tsx
  2. Card animations with framer-motion
  3. Integration tests (8+ scenarios)

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