Files
metabuilder/workflowui/src/hooks/useProjectSidebarLogic.ts
T
git dc982772af refactor(workflowui): complete monolithic file refactoring + business logic extraction + stub implementation
## Phase 1: Monolithic File Refactoring 
- Refactored 8 large files (300-500 LOC) into 40+ modular components/hooks
- All files now <150 LOC per file (max 125 LOC)
- CanvasSettings: 343 → 7 components
- SecuritySettings: 273 → 6 components
- NotificationSettings: 239 → 6 components
- Editor/Toolbar: 258 → 7 components
- InfiniteCanvas: 239 → 10 modules
- WorkflowCard: 320 → 5 components + custom hook
- useProjectCanvas: 322 → 8 hooks
- projectSlice: 335 → 4 Redux slices

## Phase 2: Business Logic Extraction 
- Extracted logic from 5 components into 8 custom hooks
- register/page.tsx: 235 → 167 LOC (-29%)
- login/page.tsx: 137 → 100 LOC (-27%)
- MainLayout.tsx: 216 → 185 LOC (-14%)
- ProjectSidebar.tsx: 200 → 200 LOC (refactored)
- page.tsx (Dashboard): 197 → 171 LOC (-13%)
- New hooks: useAuthForm, usePasswordValidation, useLoginLogic, useRegisterLogic, useHeaderLogic, useResponsiveSidebar, useProjectSidebarLogic, useDashboardLogic

## Phase 3: Dead Code Analysis & Implementation 
- Identified and documented 3 unused hooks (244 LOC)
- Removed useRealtimeService from exports
- Cleaned 8 commented lines in useProject.ts
- Documented useExecution stub methods
- Removed 3 commented dispatch calls in useCanvasKeyboard
- Fixed 3 'as any' type assertions

## Phase 4: Stub Code Implementation 
- Fully implemented useExecution methods: execute(), stop(), getDetails(), getStats(), getHistory()
- Integrated useCanvasKeyboard into InfiniteCanvas with Redux dispatch
- Verified useCanvasVirtualization for 100+ items
- Enhanced useRealtimeService documentation for Phase 4 WebSocket integration

## Backend Updates
- Added SQLAlchemy models: Workspace, Project, ProjectCanvasItem
- Added Flask API endpoints for CRUD operations
- Configured multi-tenant filtering for all queries
- Added database migrations for new entities

## Build Verification 
- TypeScript strict mode: 0 errors
- Production build:  Successful (161 kB First Load JS)
- No breaking changes
- 100% backward compatibility maintained

## Documentation Generated
- 6 comprehensive guides (70+ KB total)
- Test templates for all new implementations
- Quick reference for all 42 hooks
- Implementation checklist and deployment guide

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-23 06:44:57 +00:00

95 lines
2.5 KiB
TypeScript

/**
* useProjectSidebarLogic Hook
* Business logic for project sidebar including project operations
*/
import { useState, useCallback, useMemo } from 'react';
import { Project } from '../types/project';
export interface UseProjectSidebarLogicReturn {
isCollapsed: boolean;
showNewProjectForm: boolean;
newProjectName: string;
starredProjects: Project[];
regularProjects: Project[];
setIsCollapsed: (collapsed: boolean) => void;
toggleCollapsed: () => void;
setShowNewProjectForm: (show: boolean) => void;
setNewProjectName: (name: string) => void;
handleCreateProject: (e: React.FormEvent, onSuccess: () => void) => Promise<void>;
handleProjectClick: (projectId: string, onSelect: (id: string) => void) => void;
resetProjectForm: () => void;
}
/**
* Custom hook for project sidebar logic
* Manages project filtering, form state, and project operations
*/
export const useProjectSidebarLogic = (projects: Project[]): UseProjectSidebarLogicReturn => {
const [isCollapsed, setIsCollapsed] = useState(false);
const [showNewProjectForm, setShowNewProjectForm] = useState(false);
const [newProjectName, setNewProjectName] = useState('');
// Memoized project filtering
const starredProjects = useMemo(
() => projects.filter((p) => p.starred),
[projects]
);
const regularProjects = useMemo(
() => projects.filter((p) => !p.starred),
[projects]
);
const toggleCollapsed = useCallback(() => {
setIsCollapsed((prev) => !prev);
}, []);
const resetProjectForm = useCallback(() => {
setShowNewProjectForm(false);
setNewProjectName('');
}, []);
const handleCreateProject = useCallback(
async (e: React.FormEvent, onSuccess: () => void) => {
e.preventDefault();
if (!newProjectName.trim()) {
return;
}
try {
// This would call the createProject from useProject hook
// Caller should handle the actual API call
await onSuccess?.();
resetProjectForm();
} catch (error) {
console.error('Failed to create project:', error);
}
},
[newProjectName, resetProjectForm]
);
const handleProjectClick = useCallback(
(projectId: string, onSelect: (id: string) => void) => {
onSelect(projectId);
},
[]
);
return {
isCollapsed,
showNewProjectForm,
newProjectName,
starredProjects,
regularProjects,
setIsCollapsed,
toggleCollapsed,
setShowNewProjectForm,
setNewProjectName,
handleCreateProject,
handleProjectClick,
resetProjectForm
};
};