import React, { useState, useEffect } from 'react'; import { fetchMaterials } from '../api'; import api from '../api'; import { PipeMaterialsView, FittingMaterialsView, FlangeMaterialsView, ValveMaterialsView, GasketMaterialsView, BoltMaterialsView, SupportMaterialsView } from '../components/bom'; import './BOMManagementPage.css'; const BOMManagementPage = ({ onNavigate, selectedProject, fileId, jobNo, bomName, revision, filename, user }) => { const [materials, setMaterials] = useState([]); const [loading, setLoading] = useState(true); const [selectedCategory, setSelectedCategory] = useState('PIPE'); const [selectedMaterials, setSelectedMaterials] = useState(new Set()); const [exportHistory, setExportHistory] = useState([]); const [availableRevisions, setAvailableRevisions] = useState([]); const [currentRevision, setCurrentRevision] = useState(revision || 'Rev.0'); const [userRequirements, setUserRequirements] = useState({}); const [purchasedMaterials, setPurchasedMaterials] = useState(new Set()); const [error, setError] = useState(null); // 카테고리 정의 const categories = [ { key: 'PIPE', label: 'Pipes', color: '#3b82f6' }, { key: 'FITTING', label: 'Fittings', color: '#10b981' }, { key: 'FLANGE', label: 'Flanges', color: '#f59e0b' }, { key: 'VALVE', label: 'Valves', color: '#ef4444' }, { key: 'GASKET', label: 'Gaskets', color: '#8b5cf6' }, { key: 'BOLT', label: 'Bolts', color: '#6b7280' }, { key: 'SUPPORT', label: 'Supports', color: '#f97316' } ]; // 자료 로드 함수들 const loadMaterials = async (id) => { try { setLoading(true); console.log('🔍 자재 데이터 로딩 중...', { file_id: id, selectedProject: selectedProject?.job_no || selectedProject?.official_project_code, jobNo }); // 구매신청된 자재 먼저 확인 const projectJobNo = selectedProject?.job_no || selectedProject?.official_project_code || jobNo; await loadPurchasedMaterials(projectJobNo); const response = await fetchMaterials({ file_id: parseInt(id), limit: 10000, exclude_requested: false, job_no: projectJobNo }); if (response.data?.materials) { const materialsData = response.data.materials; console.log(`✅ ${materialsData.length}개 원본 자재 로드 완료`); setMaterials(materialsData); setError(null); } else { console.warn('⚠️ 자재 데이터가 없습니다:', response.data); setMaterials([]); } } catch (error) { console.error('자재 로드 실패:', error); setError('자재 로드에 실패했습니다.'); } finally { setLoading(false); } }; const loadAvailableRevisions = async () => { try { const response = await api.get('/files/', { params: { job_no: jobNo } }); const allFiles = Array.isArray(response.data) ? response.data : response.data?.files || []; const sameBomFiles = allFiles.filter(file => (file.bom_name || file.original_filename) === bomName ); sameBomFiles.sort((a, b) => { const revA = parseInt(a.revision?.replace('Rev.', '') || '0'); const revB = parseInt(b.revision?.replace('Rev.', '') || '0'); return revB - revA; }); setAvailableRevisions(sameBomFiles); } catch (error) { console.error('리비전 목록 조회 실패:', error); } }; const loadPurchasedMaterials = async (jobNo) => { try { // 새로운 API로 구매신청된 자재 ID 목록 조회 const response = await api.get('/purchase-request/requested-materials', { params: { job_no: jobNo, file_id: fileId } }); if (response.data?.requested_material_ids) { const purchasedIds = new Set(response.data.requested_material_ids); setPurchasedMaterials(purchasedIds); console.log(`✅ ${purchasedIds.size}개 구매신청된 자재 ID 로드 완료`); } } catch (error) { console.error('구매신청 자재 조회 실패:', error); } }; const loadUserRequirements = async (fileId) => { try { const response = await api.get(`/files/${fileId}/user-requirements`); if (response.data?.requirements) { const reqMap = {}; response.data.requirements.forEach(req => { reqMap[req.material_id] = req.requirement; }); setUserRequirements(reqMap); } } catch (error) { console.error('사용자 요구사항 로드 실패:', error); } }; // 초기 로드 useEffect(() => { if (fileId) { loadMaterials(fileId); loadAvailableRevisions(); loadUserRequirements(fileId); } }, [fileId]); // 카테고리별 자재 필터링 const getCategoryMaterials = (category) => { return materials.filter(material => material.classified_category === category || material.category === category ); }; // 카테고리별 컴포넌트 렌더링 const renderCategoryView = () => { const categoryMaterials = getCategoryMaterials(selectedCategory); const commonProps = { materials: categoryMaterials, selectedMaterials, setSelectedMaterials, userRequirements, setUserRequirements, purchasedMaterials, onPurchasedMaterialsUpdate: (materialIds) => { setPurchasedMaterials(prev => { const newSet = new Set(prev); materialIds.forEach(id => newSet.add(id)); console.log(`📦 구매신청 자재 추가: 기존 ${prev.size}개 → 신규 ${newSet.size}개`); return newSet; }); }, fileId, jobNo, user, onNavigate }; switch (selectedCategory) { case 'PIPE': return ; case 'FITTING': return ; case 'FLANGE': return ; case 'VALVE': return ; case 'GASKET': return ; case 'BOLT': return ; case 'SUPPORT': return ; default: return
카테고리를 선택해주세요.
; } }; if (loading) { return (
Loading Materials...
); } return (
{/* 헤더 섹션 */}

BOM Materials Management

{bomName} - {currentRevision} | Project: {selectedProject?.job_name || jobNo}

{/* 통계 정보 */}
{materials.length}
Total Materials
{getCategoryMaterials(selectedCategory).length}
{selectedCategory} Items
{selectedMaterials.size}
Selected
{purchasedMaterials.size}
Purchased
{/* 카테고리 탭 */}
{categories.map((category) => { const isActive = selectedCategory === category.key; const count = getCategoryMaterials(category.key).length; return ( ); })}
{/* 카테고리별 컨텐츠 */}
{error ? (
⚠️
Error Loading Materials
{error}
) : ( renderCategoryView() )}
); }; export default BOMManagementPage;