Files
tk-factory-services/tkeg/web/src/pages/DashboardPage.old.jsx
Hyungi Ahn 2699242d1f feat(tkeg, gateway): tkeg 대시보드 리디자인 + gateway 구매관리 네이밍 수정
- tkeg: MUI 기반 대시보드 전면 리디자인 (theme, 메트릭 카드, 프로젝트 Autocomplete, Quick Action, 관리자 섹션)
- gateway: tkpurchase 카드 "소모품 관리" → "구매관리"로 복원

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 15:36:02 +09:00

1119 lines
40 KiB
JavaScript

import React, { useState, useEffect } from 'react';
const DashboardPage = ({
user,
projects,
pendingSignupCount,
navigateToPage,
loadProjects,
createProject,
updateProjectName,
deleteProject,
editingProject,
setEditingProject,
editedProjectName,
setEditedProjectName,
showCreateProject,
setShowCreateProject,
newProjectCode,
setNewProjectCode,
newProjectName,
setNewProjectName,
newClientName,
setNewClientName,
inactiveProjects,
setInactiveProjects,
}) => {
const [selectedProject, setSelectedProject] = useState(null);
const [showProjectDropdown, setShowProjectDropdown] = useState(false);
// 프로젝트 생성 모달 닫기
const handleCloseCreateProject = () => {
setShowCreateProject(false);
setNewProjectCode('');
setNewProjectName('');
setNewClientName('');
};
// 프로젝트 선택 처리
const handleProjectSelect = (project) => {
setSelectedProject(project);
setShowProjectDropdown(false);
};
// 프로젝트 비활성화
const handleDeactivateProject = (project) => {
const projectId = project.job_no || project.official_project_code || project.id;
const projectName = project.job_name || project.project_name || projectId;
console.log('🔍 비활성화 요청:', { project, projectId, projectName });
if (window.confirm(`"${projectName}" 프로젝트를 비활성화하시겠습니까?`)) {
setInactiveProjects(prev => {
const newSet = new Set([...prev, projectId]);
console.log('📦 비활성화 프로젝트 업데이트:', { prev: Array.from(prev), new: Array.from(newSet) });
return newSet;
});
const selectedProjectId = selectedProject?.job_no || selectedProject?.official_project_code || selectedProject?.id;
if (selectedProjectId === projectId) {
setSelectedProject(null);
}
setShowProjectDropdown(false);
}
};
// 프로젝트 활성화
const handleActivateProject = (project) => {
setInactiveProjects(prev => {
const newSet = new Set(prev);
newSet.delete(project.job_no);
return newSet;
});
};
// 프로젝트 삭제 (드롭다운용)
const handleDeleteProjectFromDropdown = (project, e) => {
e.stopPropagation();
if (window.confirm(`"${project.job_name || project.job_no}" 프로젝트를 완전히 삭제하시겠습니까?`)) {
deleteProject(project.job_no);
setShowProjectDropdown(false);
}
};
// 컴포넌트 마운트 시 프로젝트 로드
useEffect(() => {
loadProjects();
}, []);
return (
<div style={{
padding: '40px',
background: 'linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%)',
minHeight: 'calc(100vh - 80px)',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
}}>
{/* 대시보드 헤더 */}
<div style={{ marginBottom: '48px' }}>
<h1 style={{
fontSize: '36px',
fontWeight: '800',
color: '#1a202c',
margin: '0 0 12px 0',
letterSpacing: '-0.025em'
}}>
Dashboard
</h1>
<p style={{
color: '#64748b',
fontSize: '18px',
margin: 0,
fontWeight: '400'
}}>
TK-MP BOM Management System v2.0 - Project Selection Interface
</p>
</div>
{/* 프로젝트 선택 섹션 */}
<div style={{
background: 'rgba(255, 255, 255, 0.95)',
backdropFilter: 'blur(10px)',
borderRadius: '20px',
padding: '32px',
boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.2)',
marginBottom: '40px',
position: 'relative',
zIndex: 1000
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '28px' }}>
<div>
<h2 style={{
fontSize: '24px',
fontWeight: '700',
color: '#0f172a',
margin: '0 0 4px 0',
letterSpacing: '-0.025em'
}}>
Project Selection
</h2>
<p style={{
fontSize: '14px',
color: '#64748b',
margin: 0,
fontWeight: '400'
}}>
Choose a project to access BOM and purchase management
</p>
</div>
<div style={{ display: 'flex', gap: '12px' }}>
<button
onClick={() => setShowCreateProject(true)}
style={{
background: 'linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%)',
color: 'white',
border: 'none',
borderRadius: '12px',
padding: '12px 20px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600',
boxShadow: '0 4px 14px 0 rgba(59, 130, 246, 0.39)',
transition: 'all 0.2s ease',
letterSpacing: '0.025em'
}}
onMouseEnter={(e) => {
e.target.style.transform = 'translateY(-2px)';
e.target.style.boxShadow = '0 8px 25px 0 rgba(59, 130, 246, 0.5)';
}}
onMouseLeave={(e) => {
e.target.style.transform = 'translateY(0)';
e.target.style.boxShadow = '0 4px 14px 0 rgba(59, 130, 246, 0.39)';
}}
>
New Project
</button>
<button
onClick={() => {
if (selectedProject) {
setEditingProject(selectedProject.job_no);
setEditedProjectName(selectedProject.job_name || selectedProject.job_no);
} else {
alert('먼저 수정할 프로젝트를 선택해주세요.');
}
}}
style={{
background: 'white',
color: '#6b7280',
border: '1px solid #d1d5db',
borderRadius: '12px',
padding: '12px 20px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600',
transition: 'all 0.2s ease',
letterSpacing: '0.025em'
}}
onMouseEnter={(e) => {
e.target.style.background = '#f9fafb';
e.target.style.borderColor = '#9ca3af';
}}
onMouseLeave={(e) => {
e.target.style.background = 'white';
e.target.style.borderColor = '#d1d5db';
}}
>
Rename
</button>
<button
onClick={() => navigateToPage('inactive-projects')}
style={{
background: 'white',
color: '#6b7280',
border: '1px solid #d1d5db',
borderRadius: '12px',
padding: '12px 20px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600',
transition: 'all 0.2s ease',
letterSpacing: '0.025em'
}}
onMouseEnter={(e) => {
e.target.style.background = '#f9fafb';
e.target.style.borderColor = '#9ca3af';
}}
onMouseLeave={(e) => {
e.target.style.background = 'white';
e.target.style.borderColor = '#d1d5db';
}}
>
Inactive Management
</button>
</div>
</div>
{/* 프로젝트 드롭다운 */}
<div style={{ position: 'relative', marginBottom: '24px', zIndex: 1001 }}>
<button
onClick={() => setShowProjectDropdown(!showProjectDropdown)}
style={{
width: '100%',
padding: '16px 20px',
background: 'white',
border: '2px solid #e2e8f0',
borderRadius: '12px',
fontSize: '16px',
fontWeight: '500',
color: selectedProject ? '#1a202c' : '#64748b',
cursor: 'pointer',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
transition: 'all 0.2s ease',
boxShadow: '0 2px 8px rgba(0,0,0,0.05)'
}}
onMouseEnter={(e) => {
e.target.style.borderColor = '#3b82f6';
e.target.style.boxShadow = '0 4px 12px rgba(59, 130, 246, 0.15)';
}}
onMouseLeave={(e) => {
e.target.style.borderColor = '#e2e8f0';
e.target.style.boxShadow = '0 2px 8px rgba(0,0,0,0.05)';
}}
>
<div style={{ textAlign: 'left', flex: 1, overflow: 'hidden' }}>
<div style={{
fontSize: '16px',
fontWeight: '600',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
{selectedProject ? (selectedProject.job_name || selectedProject.job_no) : 'Select a Project'}
</div>
{selectedProject && (
<div style={{
fontSize: '14px',
color: '#64748b',
marginTop: '4px',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
Code: {selectedProject.job_no} | Client: {selectedProject.client_name || 'N/A'}
</div>
)}
</div>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#64748b"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
style={{
transform: showProjectDropdown ? 'rotate(180deg)' : 'rotate(0deg)',
transition: 'transform 0.2s ease'
}}
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
{/* 드롭다운 메뉴 */}
{showProjectDropdown && (
<div style={{
position: 'absolute',
top: '100%',
left: 0,
right: 0,
marginTop: '8px',
background: 'white',
border: '1px solid #e2e8f0',
borderRadius: '12px',
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.15)',
zIndex: 1002,
maxHeight: '300px',
overflowY: 'auto',
width: '100%',
minWidth: '100%'
}}>
{projects.length === 0 ? (
<div style={{
padding: '20px',
textAlign: 'center',
color: '#64748b',
fontSize: '14px'
}}>
No projects available. Create a new one!
</div>
) : (
projects
.filter(project => {
const projectId = project.job_no || project.official_project_code || project.id;
return !inactiveProjects.has(projectId);
})
.map((project) => (
<div
key={project.job_no}
style={{
borderBottom: '1px solid #f1f5f9',
transition: 'background 0.15s ease',
wordWrap: 'break-word',
overflow: 'hidden',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between'
}}
>
<div
onClick={() => handleProjectSelect(project)}
style={{
padding: '16px 20px',
cursor: 'pointer',
flex: 1
}}
onMouseEnter={(e) => e.target.closest('div').style.background = '#f8fafc'}
onMouseLeave={(e) => e.target.closest('div').style.background = 'white'}
>
<div style={{
fontSize: '16px',
fontWeight: '600',
color: '#1a202c',
marginBottom: '4px',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
{project.job_name || project.job_no}
</div>
<div style={{
fontSize: '14px',
color: '#64748b',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
Code: {project.job_no} | Client: {project.client_name || 'N/A'}
</div>
</div>
{/* 프로젝트 관리 버튼들 */}
<div style={{
display: 'flex',
gap: '8px',
padding: '16px 20px 16px 0',
alignItems: 'center'
}}>
<button
onClick={(e) => {
e.stopPropagation();
handleDeactivateProject(project);
}}
style={{
background: '#fef3c7',
color: '#92400e',
border: '1px solid #fbbf24',
borderRadius: '6px',
padding: '6px 12px',
cursor: 'pointer',
fontSize: '12px',
fontWeight: '500',
transition: 'all 0.2s ease'
}}
onMouseEnter={(e) => {
e.target.style.background = '#fde68a';
e.target.style.borderColor = '#f59e0b';
}}
onMouseLeave={(e) => {
e.target.style.background = '#fef3c7';
e.target.style.borderColor = '#fbbf24';
}}
>
비활성
</button>
<button
onClick={(e) => handleDeleteProjectFromDropdown(project, e)}
style={{
background: '#fee2e2',
color: '#dc2626',
border: '1px solid #f87171',
borderRadius: '6px',
padding: '6px 12px',
cursor: 'pointer',
fontSize: '12px',
fontWeight: '500',
transition: 'all 0.2s ease'
}}
onMouseEnter={(e) => {
e.target.style.background = '#fecaca';
e.target.style.borderColor = '#ef4444';
}}
onMouseLeave={(e) => {
e.target.style.background = '#fee2e2';
e.target.style.borderColor = '#f87171';
}}
>
삭제
</button>
</div>
</div>
))
)}
</div>
)}
</div>
</div>
{/* 프로젝트가 선택된 경우 - 프로젝트 관련 메뉴 */}
{selectedProject && (
<div style={{
background: 'rgba(255, 255, 255, 0.9)',
backdropFilter: 'blur(10px)',
borderRadius: '20px',
padding: '32px',
boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.2)',
marginBottom: '40px',
position: 'relative',
zIndex: 1
}}>
<h2 style={{
fontSize: '24px',
fontWeight: '700',
color: '#0f172a',
margin: '0 0 28px 0',
letterSpacing: '-0.025em'
}}>
Project Management
</h2>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
gap: '24px'
}}>
{/* 통합 BOM 관리 */}
<div
onClick={() => navigateToPage('unified-bom', { selectedProject })}
style={{
background: 'white',
borderRadius: '16px',
padding: '32px',
boxShadow: '0 8px 20px rgba(0, 0, 0, 0.08)',
border: '1px solid #e2e8f0',
cursor: 'pointer',
transition: 'all 0.3s ease',
textAlign: 'center'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-5px)';
e.currentTarget.style.boxShadow = '0 12px 30px rgba(0, 0, 0, 0.15)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.08)';
}}
>
<div style={{
width: '64px',
height: '64px',
borderRadius: '16px',
background: 'linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 20px auto',
color: 'white',
fontSize: '24px',
fontWeight: '700'
}}>
BOM
</div>
<h3 style={{
fontSize: '20px',
fontWeight: '700',
color: '#1a202c',
margin: '0 0 12px 0'
}}>
BOM Management
</h3>
<p style={{
color: '#64748b',
fontSize: '14px',
margin: 0,
lineHeight: '1.5'
}}>
Upload, manage revisions, and classify materials in one unified workspace
</p>
{/* 기능 미리보기 */}
<div style={{
display: 'flex',
justifyContent: 'center',
gap: '12px',
marginTop: '16px'
}}>
<div style={{
background: 'rgba(59, 130, 246, 0.1)',
color: '#3b82f6',
padding: '4px 8px',
borderRadius: '6px',
fontSize: '12px',
fontWeight: '500'
}}>
📤 Upload
</div>
<div style={{
background: 'rgba(245, 158, 11, 0.1)',
color: '#f59e0b',
padding: '4px 8px',
borderRadius: '6px',
fontSize: '12px',
fontWeight: '500'
}}>
📊 Revisions
</div>
<div style={{
background: 'rgba(16, 185, 129, 0.1)',
color: '#10b981',
padding: '4px 8px',
borderRadius: '6px',
fontSize: '12px',
fontWeight: '500'
}}>
📋 Materials
</div>
</div>
</div>
{/* 구매신청 관리 */}
<div
onClick={() => navigateToPage('purchase-request', { selectedProject })}
style={{
background: 'white',
borderRadius: '16px',
padding: '32px',
boxShadow: '0 8px 20px rgba(0, 0, 0, 0.08)',
border: '1px solid #e2e8f0',
cursor: 'pointer',
transition: 'all 0.3s ease',
textAlign: 'center'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-5px)';
e.currentTarget.style.boxShadow = '0 12px 30px rgba(0, 0, 0, 0.15)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.08)';
}}
>
<div style={{
width: '64px',
height: '64px',
borderRadius: '16px',
background: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 20px auto',
color: 'white',
fontSize: '16px',
fontWeight: '700'
}}>
REQ
</div>
<h3 style={{
fontSize: '20px',
fontWeight: '700',
color: '#1a202c',
margin: '0 0 12px 0'
}}>
Purchase Request Management
</h3>
<p style={{
color: '#64748b',
fontSize: '14px',
margin: 0,
lineHeight: '1.5'
}}>
Manage purchase requests and export materials to Excel for procurement.
</p>
</div>
</div>
</div>
)}
{/* 관리자 메뉴 (Admin 이상만 표시) */}
{user?.role === 'admin' && (
<div style={{
background: 'rgba(255, 255, 255, 0.9)',
backdropFilter: 'blur(10px)',
borderRadius: '20px',
padding: '32px',
boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.2)',
marginBottom: '40px',
position: 'relative',
zIndex: 1
}}>
<h2 style={{
fontSize: '24px',
fontWeight: '700',
color: '#0f172a',
margin: '0 0 28px 0',
letterSpacing: '-0.025em'
}}>
System Administration
</h2>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
gap: '24px'
}}>
{/* 사용자 관리 */}
<div
onClick={() => navigateToPage('user-management')}
style={{
background: 'white',
borderRadius: '16px',
padding: '24px',
boxShadow: '0 8px 20px rgba(0, 0, 0, 0.08)',
border: '1px solid #e2e8f0',
cursor: 'pointer',
transition: 'all 0.3s ease',
textAlign: 'center'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-3px)';
e.currentTarget.style.boxShadow = '0 12px 25px rgba(0, 0, 0, 0.12)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.08)';
}}
>
<div style={{
width: '48px',
height: '48px',
borderRadius: '12px',
background: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 16px auto',
color: 'white',
fontSize: '14px',
fontWeight: '700'
}}>
USER
</div>
<h3 style={{
fontSize: '16px',
fontWeight: '700',
color: '#1a202c',
margin: '0 0 8px 0'
}}>
User Management
</h3>
<p style={{
color: '#64748b',
fontSize: '12px',
margin: 0,
lineHeight: '1.4'
}}>
Manage user accounts and permissions
</p>
{pendingSignupCount > 0 && (
<div style={{
marginTop: '8px',
padding: '4px 8px',
background: '#ef4444',
color: 'white',
borderRadius: '6px',
fontSize: '12px',
fontWeight: '600'
}}>
{pendingSignupCount} pending
</div>
)}
</div>
{/* 시스템 설정 */}
<div
onClick={() => navigateToPage('system-settings')}
style={{
background: 'white',
borderRadius: '16px',
padding: '24px',
boxShadow: '0 8px 20px rgba(0, 0, 0, 0.08)',
border: '1px solid #e2e8f0',
cursor: 'pointer',
transition: 'all 0.3s ease',
textAlign: 'center'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-3px)';
e.currentTarget.style.boxShadow = '0 12px 25px rgba(0, 0, 0, 0.12)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.08)';
}}
>
<div style={{
width: '48px',
height: '48px',
borderRadius: '12px',
background: 'linear-gradient(135deg, #6366f1 0%, #4f46e5 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 16px auto',
color: 'white',
fontSize: '14px',
fontWeight: '700'
}}>
SYS
</div>
<h3 style={{
fontSize: '16px',
fontWeight: '700',
color: '#1a202c',
margin: '0 0 8px 0'
}}>
System Settings
</h3>
<p style={{
color: '#64748b',
fontSize: '12px',
margin: 0,
lineHeight: '1.4'
}}>
Configure system preferences and settings
</p>
</div>
{/* 시스템 로그 */}
<div
onClick={() => navigateToPage('system-logs')}
style={{
background: 'white',
borderRadius: '16px',
padding: '24px',
boxShadow: '0 8px 20px rgba(0, 0, 0, 0.08)',
border: '1px solid #e2e8f0',
cursor: 'pointer',
transition: 'all 0.3s ease',
textAlign: 'center'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-3px)';
e.currentTarget.style.boxShadow = '0 12px 25px rgba(0, 0, 0, 0.12)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.08)';
}}
>
<div style={{
width: '48px',
height: '48px',
borderRadius: '12px',
background: 'linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 16px auto',
color: 'white',
fontSize: '14px',
fontWeight: '700'
}}>
LOG
</div>
<h3 style={{
fontSize: '16px',
fontWeight: '700',
color: '#1a202c',
margin: '0 0 8px 0'
}}>
System Logs
</h3>
<p style={{
color: '#64748b',
fontSize: '12px',
margin: 0,
lineHeight: '1.4'
}}>
View system activity and error logs
</p>
</div>
{/* 로그 모니터링 */}
<div
onClick={() => navigateToPage('log-monitoring')}
style={{
background: 'white',
borderRadius: '16px',
padding: '24px',
boxShadow: '0 8px 20px rgba(0, 0, 0, 0.08)',
border: '1px solid #e2e8f0',
cursor: 'pointer',
transition: 'all 0.3s ease',
textAlign: 'center'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-3px)';
e.currentTarget.style.boxShadow = '0 12px 25px rgba(0, 0, 0, 0.12)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.08)';
}}
>
<div style={{
width: '48px',
height: '48px',
borderRadius: '12px',
background: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: '0 auto 16px auto',
color: 'white',
fontSize: '14px',
fontWeight: '700'
}}>
MON
</div>
<h3 style={{
fontSize: '16px',
fontWeight: '700',
color: '#1a202c',
margin: '0 0 8px 0'
}}>
Log Monitoring
</h3>
<p style={{
color: '#64748b',
fontSize: '12px',
margin: 0,
lineHeight: '1.4'
}}>
Real-time system monitoring and alerts
</p>
</div>
</div>
</div>
)}
{/* 시스템 현황 섹션 */}
<div style={{
background: 'rgba(255, 255, 255, 0.9)',
backdropFilter: 'blur(10px)',
borderRadius: '20px',
padding: '32px',
boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.2)',
position: 'relative',
zIndex: 1
}}>
<h2 style={{
fontSize: '24px',
fontWeight: '700',
color: '#0f172a',
margin: '0 0 28px 0',
letterSpacing: '-0.025em'
}}>
System Overview
</h2>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
gap: '20px'
}}>
{/* 등록된 프로젝트 */}
<div style={{
background: '#f0f4f8',
borderRadius: '12px',
padding: '20px',
textAlign: 'center',
boxShadow: '0 4px 10px rgba(0,0,0,0.05)'
}}>
<div style={{ fontSize: '32px', fontWeight: '700', color: '#3b82f6', marginBottom: '8px' }}>
{projects.length || 0}
</div>
<div style={{ fontSize: '14px', color: '#475569', fontWeight: '500' }}>Registered Projects</div>
</div>
{/* 선택된 프로젝트 */}
<div style={{
background: '#f0f4f8',
borderRadius: '12px',
padding: '20px',
textAlign: 'center',
boxShadow: '0 4px 10px rgba(0,0,0,0.05)'
}}>
<div style={{ fontSize: '32px', fontWeight: '700', color: selectedProject ? '#22c55e' : '#64748b', marginBottom: '8px' }}>
{selectedProject ? '1' : '0'}
</div>
<div style={{ fontSize: '14px', color: '#475569', fontWeight: '500' }}>Selected Project</div>
</div>
{/* 현재 권한 */}
<div style={{
background: '#f0f4f8',
borderRadius: '12px',
padding: '20px',
textAlign: 'center',
boxShadow: '0 4px 10px rgba(0,0,0,0.05)'
}}>
<div style={{ fontSize: '32px', fontWeight: '700', color: '#f97316', marginBottom: '8px' }}>
{user?.role === 'admin' ? 'Admin' : 'User'}
</div>
<div style={{ fontSize: '14px', color: '#475569', fontWeight: '500' }}>Current Role</div>
</div>
{/* 시스템 상태 */}
<div style={{
background: '#f0f4f8',
borderRadius: '12px',
padding: '20px',
textAlign: 'center',
boxShadow: '0 4px 10px rgba(0,0,0,0.05)'
}}>
<div style={{ fontSize: '32px', fontWeight: '700', color: '#22c55e', marginBottom: '8px' }}>
Active
</div>
<div style={{ fontSize: '14px', color: '#475569', fontWeight: '500' }}>System Status</div>
</div>
</div>
</div>
{/* 프로젝트 생성 모달 */}
{showCreateProject && (
<div style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'rgba(0, 0, 0, 0.6)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1000
}}>
<div style={{
background: 'white',
borderRadius: '16px',
padding: '32px',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
width: '90%',
maxWidth: '500px',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
}}>
<h3 style={{
fontSize: '24px',
fontWeight: '700',
color: '#1a202c',
margin: '0 0 24px 0',
letterSpacing: '-0.025em'
}}>
Create New Project
</h3>
<div style={{ marginBottom: '20px' }}>
<label style={{ display: 'block', fontSize: '14px', color: '#475569', marginBottom: '8px', fontWeight: '500' }}>
Project Code
</label>
<input
type="text"
value={newProjectCode}
onChange={(e) => setNewProjectCode(e.target.value)}
style={{
width: '100%',
padding: '12px',
borderRadius: '8px',
border: '1px solid #cbd5e1',
fontSize: '16px',
boxSizing: 'border-box'
}}
placeholder="e.g., J24-001"
/>
</div>
<div style={{ marginBottom: '20px' }}>
<label style={{ display: 'block', fontSize: '14px', color: '#475569', marginBottom: '8px', fontWeight: '500' }}>
Project Name
</label>
<input
type="text"
value={newProjectName}
onChange={(e) => setNewProjectName(e.target.value)}
style={{
width: '100%',
padding: '12px',
borderRadius: '8px',
border: '1px solid #cbd5e1',
fontSize: '16px',
boxSizing: 'border-box'
}}
placeholder="e.g., Ulsan SK Energy Expansion"
/>
</div>
<div style={{ marginBottom: '24px' }}>
<label style={{ display: 'block', fontSize: '14px', color: '#475569', marginBottom: '8px', fontWeight: '500' }}>
Client Name (Optional)
</label>
<input
type="text"
value={newClientName}
onChange={(e) => setNewClientName(e.target.value)}
style={{
width: '100%',
padding: '12px',
borderRadius: '8px',
border: '1px solid #cbd5e1',
fontSize: '16px',
boxSizing: 'border-box'
}}
placeholder="e.g., Samsung Engineering"
/>
</div>
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '12px' }}>
<button
onClick={handleCloseCreateProject}
style={{
background: '#e2e8f0',
color: '#475569',
border: 'none',
borderRadius: '10px',
padding: '12px 24px',
cursor: 'pointer',
fontSize: '16px',
fontWeight: '600',
transition: 'background 0.2s ease'
}}
onMouseEnter={(e) => e.target.style.background = '#cbd5e1'}
onMouseLeave={(e) => e.target.style.background = '#e2e8f0'}
>
Cancel
</button>
<button
onClick={createProject}
style={{
background: 'linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%)',
color: 'white',
border: 'none',
borderRadius: '10px',
padding: '12px 24px',
cursor: 'pointer',
fontSize: '16px',
fontWeight: '600',
boxShadow: '0 4px 14px 0 rgba(59, 130, 246, 0.39)',
transition: 'all 0.2s ease'
}}
onMouseEnter={(e) => {
e.target.style.transform = 'translateY(-2px)';
e.target.style.boxShadow = '0 8px 25px 0 rgba(59, 130, 246, 0.5)';
}}
onMouseLeave={(e) => {
e.target.style.transform = 'translateY(0)';
e.target.style.boxShadow = '0 4px 14px 0 rgba(59, 130, 246, 0.39)';
}}
>
Create Project
</button>
</div>
</div>
</div>
)}
</div>
);
};
export default DashboardPage;