import React, { useState } from 'react'; import { exportMaterialsToExcel } from '../../../utils/excelExport'; import api from '../../../api'; import { FilterableHeader } from '../shared'; const ValveMaterialsView = ({ materials, selectedMaterials, setSelectedMaterials, userRequirements, setUserRequirements, purchasedMaterials, fileId, user }) => { const [sortConfig, setSortConfig] = useState({ key: null, direction: 'asc' }); const [columnFilters, setColumnFilters] = useState({}); const [showFilterDropdown, setShowFilterDropdown] = useState(null); const parseValveInfo = (material) => { const valveDetails = material.valve_details || {}; const description = material.original_description || ''; // 밸브 타입 파싱 (GATE, BALL, CHECK, GLOBE 등) - 기존 NewMaterialsPage와 동일 let valveType = valveDetails.valve_type || ''; if (!valveType && description) { if (description.includes('GATE')) valveType = 'GATE'; else if (description.includes('BALL')) valveType = 'BALL'; else if (description.includes('CHECK')) valveType = 'CHECK'; else if (description.includes('GLOBE')) valveType = 'GLOBE'; else if (description.includes('BUTTERFLY')) valveType = 'BUTTERFLY'; else if (description.includes('NEEDLE')) valveType = 'NEEDLE'; else if (description.includes('RELIEF')) valveType = 'RELIEF'; } // 연결 방식 파싱 (FLG, SW, THRD 등) - 기존 NewMaterialsPage와 동일 let connectionType = ''; if (description.includes('FLG')) { connectionType = 'FLG'; } else if (description.includes('SW X THRD')) { connectionType = 'SW×THRD'; } else if (description.includes('SW')) { connectionType = 'SW'; } else if (description.includes('THRD')) { connectionType = 'THRD'; } else if (description.includes('BW')) { connectionType = 'BW'; } // 압력 등급 파싱 let pressure = '-'; const pressureMatch = description.match(/(\d+)LB/i); if (pressureMatch) { pressure = `${pressureMatch[1]}LB`; } // 스케줄은 밸브에는 일반적으로 없음 (기본값) let schedule = '-'; return { type: 'VALVE', subtype: `${valveType} ${connectionType}`.trim() || 'VALVE', // 타입과 연결방식 결합 valveType: valveType, connectionType: connectionType, size: material.size_spec || '-', pressure: pressure, schedule: schedule, grade: material.material_grade || '-', quantity: Math.round(material.quantity || 0), unit: '개', isValve: 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 = parseValveInfo(material); const value = info[key]?.toString().toLowerCase() || ''; return value.includes(filterValue.toLowerCase()); }); }); if (sortConfig.key) { filtered.sort((a, b) => { const aInfo = parseValveInfo(a); const bInfo = parseValveInfo(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(); const selectableMaterials = filteredMaterials.filter(m => !purchasedMaterials.has(m.id)); if (selectedMaterials.size === selectableMaterials.length) { setSelectedMaterials(new Set()); } else { setSelectedMaterials(new Set(selectableMaterials.map(m => m.id))); } }; // 개별 선택 (구매신청된 자재는 선택 불가) const handleMaterialSelect = (materialId) => { if (purchasedMaterials.has(materialId)) { return; // 구매신청된 자재는 선택 불가 } 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 = `VALVE_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: 'VALVE', materials: dataWithRequirements, filename: excelFileName, user_id: user?.id }); exportMaterialsToExcel(dataWithRequirements, excelFileName, { category: 'VALVE', filename: excelFileName, uploadDate: new Date().toLocaleDateString() }); alert('엑셀 파일이 생성되고 서버에 저장되었습니다.'); } catch (error) { console.error('엑셀 저장 실패:', error); exportMaterialsToExcel(dataWithRequirements, excelFileName, { category: 'VALVE', filename: excelFileName, uploadDate: new Date().toLocaleDateString() }); } }; const filteredMaterials = getFilteredAndSortedMaterials(); return (
{filteredMaterials.length} items • {selectedMaterials.size} selected