feat(frontend): Implement Project Detail Page with edit and archive functionality
Add complete project detail page with real-time updates via SignalR. Changes: - Updated project detail page with edit and archive buttons - Created EditProjectDialog component for updating projects - Created ArchiveProjectDialog component for archiving projects - Integrated SignalR real-time updates (onProjectUpdated, onProjectArchived) - Added SignalR connection status indicator - Enhanced useProjectHub hook to support callback options - Improved UI layout with two-column card grid - Added toast notifications for user feedback Features: - View project details (name, description, status, timestamps) - Edit project name and description - Archive active projects - Real-time updates when project is modified by other users - Automatic redirect when project is archived 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,8 +4,21 @@ import { useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { SignalRConnectionManager } from '@/lib/signalr/ConnectionManager';
|
||||
import { SIGNALR_CONFIG } from '@/lib/signalr/config';
|
||||
import { useAuthStore } from '@/stores/authStore';
|
||||
import type { Project } from '@/types/project';
|
||||
|
||||
export function useProjectHub(projectId?: string) {
|
||||
interface UseProjectHubOptions {
|
||||
onProjectUpdated?: (project: Project) => void;
|
||||
onProjectArchived?: (data: { ProjectId: string }) => void;
|
||||
onIssueCreated?: (issue: any) => void;
|
||||
onIssueUpdated?: (issue: any) => void;
|
||||
onIssueDeleted?: (data: { IssueId: string }) => void;
|
||||
onIssueStatusChanged?: (data: any) => void;
|
||||
onUserJoinedProject?: (data: any) => void;
|
||||
onUserLeftProject?: (data: any) => void;
|
||||
onTypingIndicator?: (data: { UserId: string; IssueId: string; IsTyping: boolean }) => void;
|
||||
}
|
||||
|
||||
export function useProjectHub(projectId?: string, options?: UseProjectHubOptions) {
|
||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||
const [connectionState, setConnectionState] = useState<
|
||||
'disconnected' | 'connecting' | 'connected' | 'reconnecting'
|
||||
@@ -25,42 +38,49 @@ export function useProjectHub(projectId?: string) {
|
||||
// 监听项目事件
|
||||
manager.on('ProjectUpdated', (data: any) => {
|
||||
console.log('[ProjectHub] Project updated:', data);
|
||||
// TODO: 触发项目数据重新加载
|
||||
options?.onProjectUpdated?.(data);
|
||||
});
|
||||
|
||||
manager.on('ProjectArchived', (data: { ProjectId: string }) => {
|
||||
console.log('[ProjectHub] Project archived:', data);
|
||||
options?.onProjectArchived?.(data);
|
||||
});
|
||||
|
||||
manager.on('IssueCreated', (issue: any) => {
|
||||
console.log('[ProjectHub] Issue created:', issue);
|
||||
// TODO: 添加到看板
|
||||
options?.onIssueCreated?.(issue);
|
||||
});
|
||||
|
||||
manager.on('IssueUpdated', (issue: any) => {
|
||||
console.log('[ProjectHub] Issue updated:', issue);
|
||||
// TODO: 更新看板
|
||||
options?.onIssueUpdated?.(issue);
|
||||
});
|
||||
|
||||
manager.on('IssueDeleted', (data: { IssueId: string }) => {
|
||||
console.log('[ProjectHub] Issue deleted:', data);
|
||||
// TODO: 从看板移除
|
||||
options?.onIssueDeleted?.(data);
|
||||
});
|
||||
|
||||
manager.on('IssueStatusChanged', (data: any) => {
|
||||
console.log('[ProjectHub] Issue status changed:', data);
|
||||
// TODO: 移动看板卡片
|
||||
options?.onIssueStatusChanged?.(data);
|
||||
});
|
||||
|
||||
manager.on('UserJoinedProject', (data: any) => {
|
||||
console.log('[ProjectHub] User joined:', data);
|
||||
options?.onUserJoinedProject?.(data);
|
||||
});
|
||||
|
||||
manager.on('UserLeftProject', (data: any) => {
|
||||
console.log('[ProjectHub] User left:', data);
|
||||
options?.onUserLeftProject?.(data);
|
||||
});
|
||||
|
||||
manager.on(
|
||||
'TypingIndicator',
|
||||
(data: { UserId: string; IssueId: string; IsTyping: boolean }) => {
|
||||
console.log('[ProjectHub] Typing indicator:', data);
|
||||
// TODO: 显示正在输入提示
|
||||
options?.onTypingIndicator?.(data);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -70,7 +90,7 @@ export function useProjectHub(projectId?: string) {
|
||||
unsubscribe();
|
||||
manager.stop();
|
||||
};
|
||||
}, [isAuthenticated]);
|
||||
}, [isAuthenticated, options]);
|
||||
|
||||
// 加入项目房间
|
||||
const joinProject = useCallback(async (projectId: string) => {
|
||||
|
||||
Reference in New Issue
Block a user