feat: SWG 가스켓 전체 구성 정보 표시 개선
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled

- H/F/I/O SS304/GRAPHITE/CS/CS 패턴에서 4개 구성요소 모두 표시
- 기존 SS304 + GRAPHITE → SS304/GRAPHITE/CS/CS로 완전한 구성 표시
- 외부링/필러/내부링/추가구성 모든 정보 포함
- 구매수량 계산 모달에서 정확한 재질 정보 확인 가능
This commit is contained in:
Hyungi Ahn
2025-08-30 14:23:01 +09:00
parent 78d90c7a8f
commit 4f8e395f87
84 changed files with 16297 additions and 2161 deletions

View File

@@ -1,26 +1,204 @@
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import ProjectSelectionPage from './pages/ProjectSelectionPage';
import MaterialsPage from './pages/MaterialsPage';
import React, { useState, useEffect } from 'react';
import SimpleLogin from './SimpleLogin';
import NavigationMenu from './components/NavigationMenu';
import DashboardPage from './pages/DashboardPage';
import ProjectsPage from './pages/ProjectsPage';
import BOMStatusPage from './pages/BOMStatusPage';
import PurchaseConfirmationPage from './pages/PurchaseConfirmationPage';
import SimpleMaterialsPage from './pages/SimpleMaterialsPage';
import MaterialComparisonPage from './pages/MaterialComparisonPage';
import RevisionPurchasePage from './pages/RevisionPurchasePage';
import JobSelectionPage from './pages/JobSelectionPage';
import './App.css';
function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [user, setUser] = useState(null);
const [currentPage, setCurrentPage] = useState('dashboard');
const [pageParams, setPageParams] = useState({});
useEffect(() => {
// 저장된 토큰 확인
const token = localStorage.getItem('access_token');
const userData = localStorage.getItem('user_data');
if (token && userData) {
setIsAuthenticated(true);
setUser(JSON.parse(userData));
}
setIsLoading(false);
}, []);
// 로그인 성공 시 호출될 함수
const handleLoginSuccess = () => {
const userData = localStorage.getItem('user_data');
if (userData) {
setUser(JSON.parse(userData));
}
setIsAuthenticated(true);
};
// 로그아웃 함수
const handleLogout = () => {
localStorage.removeItem('access_token');
localStorage.removeItem('user_data');
setIsAuthenticated(false);
setUser(null);
setCurrentPage('dashboard');
};
// 페이지 네비게이션 함수
const navigateToPage = (page, params = {}) => {
setCurrentPage(page);
setPageParams(params);
};
// 페이지 렌더링 함수
const renderCurrentPage = () => {
switch (currentPage) {
case 'dashboard':
return <DashboardPage user={user} />;
case 'projects':
return <ProjectsPage user={user} />;
case 'bom':
return <JobSelectionPage onJobSelect={(jobNo, jobName) =>
navigateToPage('bom-status', { job_no: jobNo, job_name: jobName })
} />;
case 'bom-status':
return <BOMStatusPage
jobNo={pageParams.job_no}
jobName={pageParams.job_name}
onNavigate={navigateToPage}
/>;
case 'materials':
return <SimpleMaterialsPage
fileId={pageParams.file_id}
jobNo={pageParams.jobNo}
bomName={pageParams.bomName}
revision={pageParams.revision}
filename={pageParams.filename}
onNavigate={navigateToPage}
/>;
case 'material-comparison':
return <MaterialComparisonPage
jobNo={pageParams.job_no}
currentRevision={pageParams.current_revision}
previousRevision={pageParams.previous_revision}
filename={pageParams.filename}
onNavigate={navigateToPage}
/>;
case 'revision-purchase':
return <RevisionPurchasePage
jobNo={pageParams.job_no}
revision={pageParams.revision}
onNavigate={navigateToPage}
/>;
case 'quotes':
return <div style={{ padding: '32px' }}>💰 견적 관리 페이지 ( 구현 예정)</div>;
case 'procurement':
return <div style={{ padding: '32px' }}>🛒 구매 관리 페이지 ( 구현 예정)</div>;
case 'production':
return <div style={{ padding: '32px' }}>🏭 생산 관리 페이지 ( 구현 예정)</div>;
case 'shipment':
return <div style={{ padding: '32px' }}>🚚 출하 관리 페이지 ( 구현 예정)</div>;
case 'users':
return <div style={{ padding: '32px' }}>👥 사용자 관리 페이지 ( 구현 예정)</div>;
case 'system':
return <div style={{ padding: '32px' }}> 시스템 설정 페이지 ( 구현 예정)</div>;
default:
return <DashboardPage user={user} />;
}
};
if (isLoading) {
return (
<div style={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#f7fafc'
}}>
<div>로딩 ...</div>
</div>
);
}
if (!isAuthenticated) {
return <SimpleLogin onLoginSuccess={handleLoginSuccess} />;
}
return (
<Router>
<Routes>
<Route path="/" element={<ProjectSelectionPage />} />
{/* BOM 관리는 /bom-status로 통일 */}
<Route path="/bom-manager" element={<Navigate to="/bom-status" replace />} />
<Route path="/bom-status" element={<BOMStatusPage />} />
<Route path="/materials" element={<MaterialsPage />} />
<Route path="/purchase-confirmation" element={<PurchaseConfirmationPage />} />
<Route path="/material-comparison" element={<MaterialComparisonPage />} />
<Route path="/revision-purchase" element={<RevisionPurchasePage />} />
</Routes>
</Router>
<div style={{ display: 'flex', minHeight: '100vh' }}>
<NavigationMenu
user={user}
currentPage={currentPage}
onPageChange={(page) => navigateToPage(page, {})}
/>
{/* 메인 콘텐츠 영역 */}
<div style={{
flex: 1,
marginLeft: '280px', // 사이드바 너비만큼 여백
background: '#f7fafc'
}}>
{/* 상단 헤더 */}
<header style={{
background: 'white',
borderBottom: '1px solid #e2e8f0',
padding: '16px 32px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}>
<div>
<h2 style={{
margin: '0',
fontSize: '18px',
fontWeight: '600',
color: '#2d3748'
}}>
{currentPage === 'dashboard' && '대시보드'}
{currentPage === 'projects' && '프로젝트 관리'}
{currentPage === 'bom' && 'BOM 관리'}
{currentPage === 'materials' && '자재 관리'}
{currentPage === 'quotes' && '견적 관리'}
{currentPage === 'procurement' && '구매 관리'}
{currentPage === 'production' && '생산 관리'}
{currentPage === 'shipment' && '출하 관리'}
{currentPage === 'users' && '사용자 관리'}
{currentPage === 'system' && '시스템 설정'}
</h2>
</div>
<button
onClick={handleLogout}
style={{
padding: '8px 16px',
background: '#e53e3e',
color: 'white',
border: 'none',
borderRadius: '6px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '500',
display: 'flex',
alignItems: 'center',
gap: '6px'
}}
>
<span>🚪</span>
로그아웃
</button>
</header>
{/* 페이지 콘텐츠 */}
<main>
{renderCurrentPage()}
</main>
</div>
</div>
);
}