import React, { useState } from 'react'; import { exportMaterialsToExcel } from '../../../utils/excelExport'; import api from '../../../api'; import { FilterableHeader, MaterialTable } from '../shared'; const PipeMaterialsView = ({ materials, selectedMaterials, setSelectedMaterials, userRequirements, setUserRequirements, purchasedMaterials, fileId, user, onNavigate }) => { const [sortConfig, setSortConfig] = useState({ key: null, direction: 'asc' }); const [columnFilters, setColumnFilters] = useState({}); const [showFilterDropdown, setShowFilterDropdown] = useState(null); // 파이프 구매 수량 계산 (기존 로직 복원) const calculatePipePurchase = (material) => { const pipeDetails = material.pipe_details || {}; const totalLength = pipeDetails.length || material.length || 0; const standardLength = 6; // 표준 6M const purchaseCount = Math.ceil(totalLength / standardLength); const totalPurchaseLength = purchaseCount * standardLength; const wasteLength = totalPurchaseLength - totalLength; const wastePercentage = totalLength > 0 ? (wasteLength / totalLength * 100) : 0; return { totalLength, standardLength, purchaseCount, totalPurchaseLength, wasteLength, wastePercentage }; }; // 파이프 정보 파싱 (기존 상세 로직 복원) const parsePipeInfo = (material) => { const calc = calculatePipePurchase(material); const pipeDetails = material.pipe_details || {}; return { type: 'PIPE', subtype: pipeDetails.manufacturing_method || 'SMLS', size: material.size_spec || '-', schedule: pipeDetails.schedule || material.schedule || '-', grade: material.full_material_grade || material.material_grade || '-', length: calc.totalLength, quantity: calc.purchaseCount, unit: '본', details: calc, isPipe: true }; }; // 정렬 처리 const handleSort = (key) => { let direction = 'asc'; if (sortConfig.key === key && sortConfig.direction === 'asc') { direction = 'desc'; } setSortConfig({ key, direction }); }; // 필터링된 및 정렬된 자재 목록 const getFilteredAndSortedMaterials = () => { let filtered = materials.filter(material => { return Object.entries(columnFilters).every(([key, filterValue]) => { if (!filterValue) return true; const info = parsePipeInfo(material); const value = info[key]?.toString().toLowerCase() || ''; return value.includes(filterValue.toLowerCase()); }); }); if (sortConfig.key) { filtered.sort((a, b) => { const aInfo = parsePipeInfo(a); const bInfo = parsePipeInfo(b); const aValue = aInfo[sortConfig.key] || ''; const bValue = bInfo[sortConfig.key] || ''; if (sortConfig.direction === 'asc') { return aValue > bValue ? 1 : -1; } else { return aValue < bValue ? 1 : -1; } }); } return filtered; }; // 전체 선택/해제 const handleSelectAll = () => { const filteredMaterials = getFilteredAndSortedMaterials(); if (selectedMaterials.size === filteredMaterials.length) { setSelectedMaterials(new Set()); } else { setSelectedMaterials(new Set(filteredMaterials.map(m => m.id))); } }; // 개별 선택 const handleMaterialSelect = (materialId) => { const newSelected = new Set(selectedMaterials); if (newSelected.has(materialId)) { newSelected.delete(materialId); } else { newSelected.add(materialId); } setSelectedMaterials(newSelected); }; // 엑셀 내보내기 const handleExportToExcel = async () => { const selectedMaterialsData = materials.filter(m => selectedMaterials.has(m.id)); if (selectedMaterialsData.length === 0) { alert('내보낼 자재를 선택해주세요.'); return; } const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-'); const excelFileName = `PIPE_Materials_${timestamp}.xlsx`; // 사용자 요구사항 포함 const dataWithRequirements = selectedMaterialsData.map(material => ({ ...material, user_requirement: userRequirements[material.id] || '' })); try { // 서버에 엑셀 파일 저장 요청 await api.post('/files/save-excel', { file_id: fileId, category: 'PIPE', materials: dataWithRequirements, filename: excelFileName, user_id: user?.id }); // 클라이언트에서 다운로드 exportMaterialsToExcel(dataWithRequirements, excelFileName, { category: 'PIPE', filename: excelFileName, uploadDate: new Date().toLocaleDateString() }); alert('엑셀 파일이 생성되고 서버에 저장되었습니다.'); } catch (error) { console.error('엑셀 저장 실패:', error); // 실패해도 다운로드는 진행 exportMaterialsToExcel(dataWithRequirements, excelFileName, { category: 'PIPE', filename: excelFileName, uploadDate: new Date().toLocaleDateString() }); } }; const filteredMaterials = getFilteredAndSortedMaterials(); // 필터 헤더 컴포넌트 const FilterableHeader = ({ sortKey, filterKey, children }) => (
handleSort(sortKey)} style={{ cursor: 'pointer', flex: 1 }} > {children} {sortConfig.key === sortKey && ( {sortConfig.direction === 'asc' ? '↑' : '↓'} )}
{showFilterDropdown === filterKey && (
setColumnFilters({ ...columnFilters, [filterKey]: e.target.value })} style={{ width: '100%', padding: '4px 8px', border: '1px solid #d1d5db', borderRadius: '4px', fontSize: '12px' }} autoFocus />
)}
); return (
{/* 헤더 */}

Pipe Materials

{filteredMaterials.length} items • {selectedMaterials.size} selected

{/* 테이블 */}
{/* 헤더 */}
0} onChange={handleSelectAll} style={{ cursor: 'pointer' }} />
Type Subtype Size Schedule Material Grade Length (M) Quantity
Unit
User Requirement
{/* 데이터 행들 */}
{filteredMaterials.map((material, index) => { const info = parsePipeInfo(material); const isSelected = selectedMaterials.has(material.id); const isPurchased = purchasedMaterials.has(material.id); return (
{ if (!isSelected && !isPurchased) { e.target.style.background = '#f8fafc'; } }} onMouseLeave={(e) => { if (!isSelected && !isPurchased) { e.target.style.background = 'white'; } }} >
handleMaterialSelect(material.id)} style={{ cursor: 'pointer' }} />
PIPE {isPurchased && ( PURCHASED )}
{info.subtype}
{info.size}
{info.schedule}
{info.grade}
{info.length.toFixed(2)}
{info.quantity}
{info.unit}
setUserRequirements({ ...userRequirements, [material.id]: e.target.value })} placeholder="Enter requirement..." style={{ width: '100%', padding: '6px 8px', border: '1px solid #d1d5db', borderRadius: '4px', fontSize: '12px' }} />
); })}
{filteredMaterials.length === 0 && (
🔧
No Pipe Materials Found
{Object.keys(columnFilters).some(key => columnFilters[key]) ? 'Try adjusting your filters' : 'No pipe materials available in this BOM'}
)}
); }; export default PipeMaterialsView;