import React, { useState, useEffect } from 'react'; import api from '../../../api'; const BOMFilesTab = ({ selectedProject, user, bomFiles, setBomFiles, selectedBOM, onBOMSelect, refreshTrigger }) => { const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [groupedFiles, setGroupedFiles] = useState({}); // BOM 파일 목록 로드 useEffect(() => { const loadBOMFiles = async () => { if (!selectedProject) return; try { setLoading(true); setError(''); const projectCode = selectedProject.official_project_code || selectedProject.job_no; const encodedProjectCode = encodeURIComponent(projectCode); const response = await api.get(`/files/project/${encodedProjectCode}`); const files = response.data || []; setBomFiles(files); // BOM 이름별로 그룹화 const groups = groupFilesByBOM(files); setGroupedFiles(groups); } catch (err) { console.error('BOM 파일 로드 실패:', err); setError('BOM 파일을 불러오는데 실패했습니다.'); } finally { setLoading(false); } }; loadBOMFiles(); }, [selectedProject, refreshTrigger, setBomFiles]); // 파일을 BOM 이름별로 그룹화 const groupFilesByBOM = (fileList) => { const groups = {}; fileList.forEach(file => { const bomName = file.bom_name || file.original_filename; if (!groups[bomName]) { groups[bomName] = []; } groups[bomName].push(file); }); // 각 그룹 내에서 리비전 번호로 정렬 Object.keys(groups).forEach(bomName => { groups[bomName].sort((a, b) => { const revA = parseInt(a.revision?.replace('Rev.', '') || '0'); const revB = parseInt(b.revision?.replace('Rev.', '') || '0'); return revB - revA; // 최신 리비전이 위로 }); }); return groups; }; // BOM 선택 처리 const handleBOMClick = (bomFile) => { if (onBOMSelect) { onBOMSelect(bomFile); } }; // 파일 삭제 const handleDeleteFile = async (fileId, bomName) => { if (!window.confirm(`이 파일을 삭제하시겠습니까?`)) { return; } try { await api.delete(`/files/delete/${fileId}`); // 파일 목록 새로고침 const projectCode = selectedProject.official_project_code || selectedProject.job_no; const encodedProjectCode = encodeURIComponent(projectCode); const response = await api.get(`/files/project/${encodedProjectCode}`); const files = response.data || []; setBomFiles(files); setGroupedFiles(groupFilesByBOM(files)); } catch (err) { console.error('파일 삭제 실패:', err); setError('파일 삭제에 실패했습니다.'); } }; // 리비전 업로드 (향후 구현) const handleRevisionUpload = (parentFile) => { // TODO: 리비전 업로드 기능 구현 alert('리비전 업로드 기능은 향후 구현 예정입니다.'); }; // 날짜 포맷팅 const formatDate = (dateString) => { if (!dateString) return 'N/A'; try { return new Date(dateString).toLocaleDateString('ko-KR'); } catch { return dateString; } }; if (loading) { return (
Loading BOM files...
); } if (error) { return (
⚠️
{error}
); } if (bomFiles.length === 0) { return (
📄

No BOM Files Found

Upload your first BOM file using the Upload tab

); } return (

BOM Files & Revisions

Select a BOM file to manage its materials

{Object.keys(groupedFiles).length} BOM Groups • {bomFiles.length} Total Files
{/* BOM 파일 그룹 목록 */}
{Object.entries(groupedFiles).map(([bomName, files]) => { const latestFile = files[0]; // 최신 리비전 const isSelected = selectedBOM?.id === latestFile.id; return (
handleBOMClick(latestFile)} >

📋 {bomName} {isSelected && ( SELECTED )}

Latest: {latestFile.revision || 'Rev.0'}
Revisions: {Math.max(0, files.length - 1)}
Updated: {formatDate(latestFile.upload_date)}
Size: {latestFile.file_size ? `${Math.round(latestFile.file_size / 1024)} KB` : 'N/A'}
{/* 리비전 히스토리 */} {files.length > 1 && (

Revision History

{files.map((file, index) => (
{file.revision || 'Rev.0'} {index === 0 && ' (Latest)'}
))}
)} {/* 선택 안내 */} {!isSelected && (
Click to select this BOM for material management
)}
); })}
{/* 향후 기능 안내 */}

🚧 Coming Soon: Advanced Revision Features

📊
Visual Timeline
Interactive revision history
🔍
Diff Comparison
Compare changes between revisions
Rollback System
Restore previous versions
); }; export default BOMFilesTab;