import React, { useState } from 'react'; import api from '../api'; const SimpleFileUpload = ({ selectedProject, onUploadComplete }) => { const [uploading, setUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [uploadResult, setUploadResult] = useState(null); const [error, setError] = useState(''); const [dragActive, setDragActive] = useState(false); const handleDrag = (e) => { e.preventDefault(); e.stopPropagation(); if (e.type === "dragenter" || e.type === "dragover") { setDragActive(true); } else if (e.type === "dragleave") { setDragActive(false); } }; const handleDrop = (e) => { e.preventDefault(); e.stopPropagation(); setDragActive(false); if (e.dataTransfer.files && e.dataTransfer.files[0]) { handleFileUpload(e.dataTransfer.files[0]); } }; const handleFileSelect = (e) => { if (e.target.files && e.target.files[0]) { handleFileUpload(e.target.files[0]); } }; const handleFileUpload = async (file) => { if (!selectedProject) { setError('프로젝트를 먼저 선택해주세요.'); return; } // 파일 유효성 검사 const allowedTypes = ['.xlsx', '.xls', '.csv']; const fileExtension = '.' + file.name.split('.').pop().toLowerCase(); if (!allowedTypes.includes(fileExtension)) { setError(`지원하지 않는 파일 형식입니다. 허용된 확장자: ${allowedTypes.join(', ')}`); return; } if (file.size > 10 * 1024 * 1024) { setError('파일 크기는 10MB를 초과할 수 없습니다.'); return; } setUploading(true); setError(''); setUploadResult(null); setUploadProgress(0); try { const formData = new FormData(); formData.append('file', file); formData.append('job_no', selectedProject.job_no); formData.append('revision', 'Rev.0'); // 업로드 진행률 시뮬레이션 const progressInterval = setInterval(() => { setUploadProgress(prev => { if (prev >= 90) { clearInterval(progressInterval); return 90; } return prev + 10; }); }, 200); const response = await api.post('/files/upload', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); clearInterval(progressInterval); setUploadProgress(100); if (response.data.success) { setUploadResult({ success: true, message: response.data.message, file: response.data.file, job: response.data.job, sampleMaterials: response.data.sample_materials || [] }); // 업로드 완료 콜백 호출 if (onUploadComplete) { onUploadComplete(response.data); } } else { throw new Error(response.data.message || '업로드 실패'); } } catch (err) { console.error('업로드 에러:', err); setError(err.response?.data?.detail || err.message || '파일 업로드에 실패했습니다.'); setUploadProgress(0); } finally { setUploading(false); } }; return (
{/* 드래그 앤 드롭 영역 */}
document.getElementById('file-input').click()} >
{uploading ? '⏳' : '📤'}
{uploading ? '업로드 중...' : 'BOM 파일을 업로드하세요'}
파일을 드래그하거나 클릭하여 선택하세요
지원 형식: Excel (.xlsx, .xls), CSV (.csv) | 최대 크기: 10MB
{/* 업로드 진행률 */} {uploading && (
업로드 진행률 {uploadProgress}%
)} {/* 에러 메시지 */} {error && (
⚠️ {error}
)} {/* 업로드 성공 결과 */} {uploadResult && uploadResult.success && (
업로드 완료!
{uploadResult.message}
{/* 파일 정보 */}

📄 파일 정보

파일명: {uploadResult.file?.original_filename}
분석된 자재: {uploadResult.file?.parsed_count}개
저장된 자재: {uploadResult.file?.saved_count}개
프로젝트: {uploadResult.job?.job_name}
{/* 샘플 자재 미리보기 */} {uploadResult.sampleMaterials && uploadResult.sampleMaterials.length > 0 && (

🔧 자재 샘플 (처음 3개)

{uploadResult.sampleMaterials.map((material, index) => (
{material.description || material.item_code} {material.category && ( {material.category} )}
))}
)}
)}
); }; export default SimpleFileUpload;