feat: 자재 분류 시스템 개선 및 상세 테이블 추가

- 모든 자재 카테고리별 상세 테이블 생성 (fitting, valve, flange, bolt, gasket, instrument)
- PIPE, FITTING, VALVE 분류 결과를 각 상세 테이블에 저장하는 로직 구현
- 프론트엔드 라우팅 정리 및 BOM 현황 페이지 기능 개선
- 자재확인 페이지 에러 처리 개선

TODO: FLANGE, BOLT, GASKET, INSTRUMENT 저장 로직 추가 필요
This commit is contained in:
Hyungi Ahn
2025-07-17 10:44:19 +09:00
parent ea111433e4
commit 5f7a6f0b3a
30 changed files with 3963 additions and 923 deletions

View File

@@ -17,7 +17,7 @@ const BOMStatusPage = () => {
setLoading(true);
setError('');
try {
let url = '/files';
let url = 'http://localhost:8000/files';
if (jobNo) {
url += `?job_no=${jobNo}`;
}
@@ -28,6 +28,7 @@ const BOMStatusPage = () => {
else setFiles([]);
} catch (e) {
setError('파일 목록을 불러오지 못했습니다.');
console.error('파일 목록 로드 에러:', e);
} finally {
setLoading(false);
}
@@ -45,10 +46,10 @@ const BOMStatusPage = () => {
setUploading(true);
setError('');
try {
const formData = new FormData();
const formData = new FormData();
formData.append('file', file);
formData.append('project_id', 1); // 예시: 실제 프로젝트 ID로 대체 필요
const res = await fetch('/files/upload', {
const res = await fetch('http://localhost:8000/upload', {
method: 'POST',
body: formData
});
@@ -74,49 +75,62 @@ const BOMStatusPage = () => {
accept=".csv,.xlsx,.xls"
onChange={e => setFile(e.target.files[0])}
disabled={uploading}
/>
/>
<Button type="submit" variant="contained" disabled={!file || uploading} sx={{ ml: 2 }}>
업로드
</Button>
</Button>
</form>
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
{loading && <CircularProgress sx={{ mt: 4 }} />}
<TableContainer component={Paper} sx={{ mt: 2 }}>
<Table size="small">
<TableHead>
<TableHead>
<TableRow>
<TableCell>파일명</TableCell>
<TableCell>리비전</TableCell>
<TableCell>세부내역</TableCell>
<TableCell>리비전</TableCell>
<TableCell>삭제</TableCell>
</TableRow>
</TableHead>
<TableBody>
</TableRow>
</TableHead>
<TableBody>
{files.map(file => (
<TableRow key={file.id}>
<TableCell>{file.original_filename || file.filename}</TableCell>
<TableCell>{file.revision}</TableCell>
<TableCell>
<Button size="small" variant="outlined" onClick={() => alert(`자재확인: ${file.original_filename}`)}>
<TableCell>
<Button size="small" variant="outlined" onClick={() => navigate(`/materials?fileId=${file.id}`)}>
자재확인
</Button>
</TableCell>
<TableCell>
</TableCell>
<TableCell>
<Button size="small" variant="outlined" color="info" onClick={() => alert(`리비전 관리: ${file.original_filename}`)}>
리비전
</Button>
</TableCell>
<TableCell>
<Button size="small" variant="outlined" color="error" onClick={() => alert(`삭제: ${file.original_filename}`)}>
</TableCell>
<TableCell>
<Button size="small" variant="outlined" color="error" onClick={async () => {
if (window.confirm(`정말로 ${file.original_filename}을 삭제하시겠습니까?`)) {
try {
const res = await fetch(`http://localhost:8000/files/${file.id}`, { method: 'DELETE' });
if (res.ok) {
fetchFiles();
} else {
alert('삭제에 실패했습니다.');
}
} catch (e) {
alert('삭제 중 오류가 발생했습니다.');
}
}
}}>
삭제
</Button>
</TableCell>
</TableRow>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</TableBody>
</Table>
</TableContainer>
</Box>
);
};