Files
TK-BOM-Project/frontend/src/api.js
Hyungi Ahn 5f7a6f0b3a feat: 자재 분류 시스템 개선 및 상세 테이블 추가
- 모든 자재 카테고리별 상세 테이블 생성 (fitting, valve, flange, bolt, gasket, instrument)
- PIPE, FITTING, VALVE 분류 결과를 각 상세 테이블에 저장하는 로직 구현
- 프론트엔드 라우팅 정리 및 BOM 현황 페이지 기능 개선
- 자재확인 페이지 에러 처리 개선

TODO: FLANGE, BOLT, GASKET, INSTRUMENT 저장 로직 추가 필요
2025-07-17 10:44:19 +09:00

134 lines
3.4 KiB
JavaScript

import axios from 'axios';
// 환경변수에서 API URL을 읽음 (Vite 기준)
const API_BASE_URL = import.meta.env.VITE_API_URL ||
(import.meta.env.DEV ? 'http://localhost:8000' : 'http://localhost:8000');
console.log('API Base URL:', API_BASE_URL);
console.log('Environment:', import.meta.env.MODE);
// axios 인스턴스 생성
export const api = axios.create({
baseURL: API_BASE_URL,
timeout: 30000, // 30초로 증가
headers: {
'Content-Type': 'application/json',
},
});
// 재시도 로직을 위한 설정
const MAX_RETRIES = 3;
const RETRY_DELAY = 1000; // 1초
// 재시도 함수
const retryRequest = async (config, retries = MAX_RETRIES) => {
try {
return await api(config);
} catch (error) {
if (retries > 0 && (error.code === 'ECONNABORTED' || error.response?.status >= 500)) {
console.log(`API 재시도 중... (${MAX_RETRIES - retries + 1}/${MAX_RETRIES})`);
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
return retryRequest(config, retries - 1);
}
throw error;
}
};
// 공통 에러 핸들링 (예시)
api.interceptors.response.use(
response => response,
error => {
console.error('API Error:', {
url: error.config?.url,
method: error.config?.method,
status: error.response?.status,
data: error.response?.data,
message: error.message
});
// 필요시 에러 로깅/알림 등 추가
return Promise.reject(error);
}
);
// 예시: 파일 업로드 (multipart/form-data)
export function uploadFile(formData, options = {}) {
const config = {
method: 'post',
url: '/upload',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
...options,
};
return retryRequest(config);
}
// 예시: 자재 목록 조회
export function fetchMaterials(params) {
return api.get('/files/materials', { params });
}
// 예시: 자재 요약 통계
export function fetchMaterialsSummary(params) {
return api.get('/files/materials/summary', { params });
}
// 파일 목록 조회
export function fetchFiles(params) {
return api.get('/files', { params });
}
// 파일 삭제
export function deleteFile(fileId) {
return api.delete(`/files/${fileId}`);
}
// 예시: Job 목록 조회
export function fetchJobs(params) {
return api.get('/jobs', { params });
}
// 예시: Job 생성
export function createJob(data) {
return api.post('/jobs', data);
}
// 리비전 비교
export function compareRevisions(jobNo, filename, oldRevision, newRevision) {
return api.get('/files/materials/compare-revisions', {
params: {
job_no: jobNo,
filename: filename,
old_revision: oldRevision,
new_revision: newRevision
}
});
}
// 프로젝트 수정
export function updateProject(projectId, data) {
return api.put(`/projects/${projectId}`, data);
}
// 프로젝트 삭제
export function deleteProject(projectId) {
return api.delete(`/projects/${projectId}`);
}
// 스풀 관련 API
export function fetchProjectSpools(projectId) {
return api.get(`/spools/project/${projectId}/spools`);
}
export function validateSpoolIdentifier(identifier) {
return api.post('/spools/validate-identifier', { spool_identifier: identifier });
}
export function generateSpoolIdentifier(dwgName, areaNumber, spoolNumber) {
return api.post('/spools/generate-identifier', {
dwg_name: dwgName,
area_number: areaNumber,
spool_number: spoolNumber
});
}