import React, { useState, useEffect } from 'react'; import { api } from '../api'; const ProjectWorkspacePage = ({ project, user, onNavigate, onBackToDashboard }) => { const [projectStats, setProjectStats] = useState(null); const [recentFiles, setRecentFiles] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { if (project) { loadProjectData(); } }, [project]); const loadProjectData = async () => { try { // 실제 파일 데이터만 로드 const filesResponse = await api.get(`/files?job_no=${project.job_no}&limit=5`); if (filesResponse.data && Array.isArray(filesResponse.data)) { setRecentFiles(filesResponse.data); // 파일 데이터를 기반으로 통계 계산 const stats = { totalFiles: filesResponse.data.length, totalMaterials: filesResponse.data.reduce((sum, file) => sum + (file.parsed_count || 0), 0), classifiedMaterials: 0, // API에서 분류 정보를 가져와야 함 pendingVerification: 0, // API에서 검증 정보를 가져와야 함 }; setProjectStats(stats); } else { setRecentFiles([]); setProjectStats({ totalFiles: 0, totalMaterials: 0, classifiedMaterials: 0, pendingVerification: 0 }); } } catch (error) { console.error('프로젝트 데이터 로딩 실패:', error); setRecentFiles([]); setProjectStats({ totalFiles: 0, totalMaterials: 0, classifiedMaterials: 0, pendingVerification: 0 }); } finally { setLoading(false); } }; const getAvailableActions = () => { const userRole = user?.role || 'user'; const allActions = { // BOM 관리 (통합) 'bom-management': { title: 'BOM 관리', description: 'BOM 파일 업로드, 관리 및 리비전 추적을 수행합니다', icon: '📋', color: '#667eea', roles: ['designer', 'manager', 'admin'], path: 'bom-status' }, // 자재 관리 'material-management': { title: '자재 관리', description: '자재 분류, 검증 및 구매 관리를 수행합니다', icon: '🔧', color: '#48bb78', roles: ['designer', 'purchaser', 'manager', 'admin'], path: 'materials' } }; // 사용자 권한에 따라 필터링 return Object.entries(allActions).filter(([key, action]) => action.roles.includes(userRole) ); }; const handleActionClick = (actionPath) => { switch (actionPath) { case 'bom-management': onNavigate('bom-status', { job_no: project.job_no, job_name: project.project_name }); break; case 'material-management': onNavigate('materials', { job_no: project.job_no, job_name: project.project_name }); break; default: alert(`${actionPath} 기능은 곧 구현될 예정입니다.`); } }; if (loading) { return (
프로젝트 데이터를 불러오는 중...
); } const availableActions = getAvailableActions(); return (
{/* 헤더 */}

{project.project_name}

{project.job_no} • 진행률: {project.progress || 0}%
{/* 프로젝트 통계 */}
{[ { label: 'BOM 파일', value: projectStats.totalFiles, icon: '📄', color: '#667eea' }, { label: '전체 자재', value: projectStats.totalMaterials, icon: '📦', color: '#48bb78' }, { label: '분류 완료', value: projectStats.classifiedMaterials, icon: '✅', color: '#38b2ac' }, { label: '검증 대기', value: projectStats.pendingVerification, icon: '⏳', color: '#ed8936' } ].map((stat, index) => (
{stat.label}
{stat.value}
{stat.icon}
))}
{/* 업무 메뉴 */}

🚀 사용 가능한 업무

{availableActions.map(([key, action]) => (
handleActionClick(key)} style={{ padding: '20px', border: '1px solid #e2e8f0', borderRadius: '12px', cursor: 'pointer', transition: 'all 0.2s ease', background: 'white' }} onMouseEnter={(e) => { e.target.style.borderColor = action.color; e.target.style.boxShadow = `0 4px 12px ${action.color}20`; e.target.style.transform = 'translateY(-2px)'; }} onMouseLeave={(e) => { e.target.style.borderColor = '#e2e8f0'; e.target.style.boxShadow = 'none'; e.target.style.transform = 'translateY(0)'; }} >
{action.icon}

{action.title}

{action.description}

))}
{/* 최근 활동 (옵션) */} {recentFiles.length > 0 && (

📁 최근 BOM 파일

{recentFiles.map((file, index) => (
{file.original_filename || file.filename}
{file.revision} • {file.uploaded_by || '시스템'} • {file.parsed_count || 0}개 자재
))}
)}
); }; export default ProjectWorkspacePage;