3.4 KiB
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
- SignalR integration in KanbanBoard.tsx
- Card animations with framer-motion
- Integration tests (8+ scenarios)
Status: Not Started | Created: 2025-11-04