feat(frontend): Add SignalR Context for real-time event management
Create comprehensive SignalR Context infrastructure to support real-time updates across the application.
Changes:
- Created SignalRContext.tsx with React Context API for SignalR connection management
- Implemented useSignalREvent and useSignalREvents hooks for simplified event subscription
- Updated Kanban page to use new SignalR hooks (reduced from 150+ lines to ~50 lines)
- Updated root layout to use new SignalRProvider from SignalRContext
- Fixed login page Suspense boundary issue for Next.js 16 compatibility
- Fixed Kanban type issue: made description optional to match API response
Features:
- Auto-connect when user is authenticated
- Auto-reconnect with configurable delays (0s, 2s, 5s, 10s, 30s)
- Toast notifications for connection status changes
- Event subscription management with automatic cleanup
- Support for multiple hub connections (PROJECT, NOTIFICATION)
- TypeScript type safety with proper interfaces
Usage:
```tsx
// Subscribe to single event
useSignalREvent('TaskCreated', (task) => {
console.log('Task created:', task);
});
// Subscribe to multiple events
useSignalREvents({
'TaskCreated': (task) => handleTaskCreated(task),
'TaskUpdated': (task) => handleTaskUpdated(task),
});
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const loginSchema = z.object({
|
||||
email: z.string().email('Invalid email address'),
|
||||
@@ -18,7 +19,7 @@ const loginSchema = z.object({
|
||||
|
||||
type LoginForm = z.infer<typeof loginSchema>;
|
||||
|
||||
export default function LoginPage() {
|
||||
function LoginContent() {
|
||||
const searchParams = useSearchParams();
|
||||
const registered = searchParams.get('registered');
|
||||
|
||||
@@ -119,3 +120,18 @@ export default function LoginPage() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<Suspense fallback={
|
||||
<div className="flex min-h-screen items-center justify-center bg-gray-50">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto h-12 w-12 animate-spin rounded-full border-b-2 border-blue-600"></div>
|
||||
<p className="mt-4 text-gray-600">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
}>
|
||||
<LoginContent />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user