import React, { useState, useEffect } from 'react'; import api from '../api'; import { exportMaterialsToExcel } from '../utils/excelExport'; import './PurchaseRequestPage.css'; const PurchaseRequestPage = ({ onNavigate, fileId, jobNo, selectedProject }) => { const [requests, setRequests] = useState([]); const [selectedRequest, setSelectedRequest] = useState(null); const [requestMaterials, setRequestMaterials] = useState([]); const [isLoading, setIsLoading] = useState(false); useEffect(() => { loadRequests(); }, [fileId, jobNo]); const loadRequests = async () => { setIsLoading(true); try { const params = {}; if (fileId) params.file_id = fileId; if (jobNo) params.job_no = jobNo; const response = await api.get('/purchase-request/list', { params }); setRequests(response.data.requests || []); } catch (error) { console.error('Failed to load requests:', error); } finally { setIsLoading(false); } }; const loadRequestMaterials = async (requestId) => { setIsLoading(true); try { const response = await api.get(`/purchase-request/${requestId}/materials`); // 그룹화된 자재가 있으면 우선 표시, 없으면 개별 자재 표시 if (response.data.grouped_materials && response.data.grouped_materials.length > 0) { setRequestMaterials(response.data.grouped_materials); } else { setRequestMaterials(response.data.materials || []); } } catch (error) { console.error('Failed to load materials:', error); } finally { setIsLoading(false); } }; const handleRequestSelect = (request) => { setSelectedRequest(request); loadRequestMaterials(request.request_id); }; const handleDownloadExcel = async (requestId, requestNo) => { try { console.log('📥 엑셀 다운로드 시작:', requestId, requestNo); // 서버에서 생성된 엑셀 파일 직접 다운로드 (BOM 페이지와 동일한 파일) const response = await api.get(`/purchase-request/${requestId}/download-excel`, { responseType: 'blob' // 파일 다운로드용 }); // 파일 다운로드 처리 const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `${requestNo}_재다운로드.xlsx`; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); console.log('✅ 엑셀 파일 다운로드 완료'); } catch (error) { console.error('❌ 엑셀 다운로드 실패:', error); alert('엑셀 다운로드 실패: ' + error.message); } }; return (

구매신청 관리

구매신청한 자재들을 그룹별로 관리합니다

{/* 구매신청 목록 */}

구매신청 목록 ({requests.length})

{isLoading ? (
로딩중...
) : requests.length === 0 ? (
구매신청이 없습니다
) : ( requests.map(request => (
handleRequestSelect(request)} >
{request.request_no} {new Date(request.requested_at).toLocaleDateString()}
{request.job_no} - {request.job_name}
{request.category || '전체'} | {request.material_count}개 자재
{request.requested_by}
)) )}
{/* 선택된 구매신청 상세 */}
{selectedRequest ? ( <>

{selectedRequest.request_no}

{/* 업로드 당시 분류된 정보를 그대로 표시 */} {requestMaterials.length === 0 ? (
자재 정보가 없습니다
) : (
{/* 카테고리별로 그룹화하여 표시 */} {(() => { // 카테고리별로 자재 그룹화 const groupedByCategory = requestMaterials.reduce((acc, material) => { const category = material.category || material.classified_category || 'UNKNOWN'; if (!acc[category]) acc[category] = []; acc[category].push(material); return acc; }, {}); return Object.entries(groupedByCategory).map(([category, materials]) => (

{category} ({materials.length}개)

{materials.map((material, idx) => ( ))}
No 카테고리 자재 설명 크기 스케줄 재질 수량 사용자요구
{idx + 1} {material.category || material.classified_category} {material.description || material.original_description} {material.size || material.size_spec || '-'} {material.schedule || '-'} {material.material_grade || material.full_material_grade || '-'} {Math.round(material.quantity || material.requested_quantity || 0)} {material.unit || material.requested_unit || '개'} {material.user_requirement || '-'}
)); })()}
)}
) : (
📦
구매신청을 선택하세요
)}
); }; export default PurchaseRequestPage;