feat: 품목기준관리 Zustand 리팩토링 및 422 에러 팝업
- Zustand store 도입 (useItemMasterStore) - 훅 분리 및 구조 개선 (hooks/, contexts/) - 422 ValidationException 에러 AlertDialog 팝업 추가 - API 함수 분리 (src/lib/api/item-master.ts) - 타입 정의 정리 (item-master.types.ts, item-master-api.ts) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,11 @@ import type {
|
||||
LinkEntityRequest,
|
||||
LinkBomRequest,
|
||||
ReorderRelationshipsRequest,
|
||||
// 2025-12-21 추가: 재질/표면처리 타입
|
||||
MaterialOptionRequest,
|
||||
MaterialOptionResponse,
|
||||
TreatmentOptionRequest,
|
||||
TreatmentOptionResponse,
|
||||
} from '@/types/item-master-api';
|
||||
import { getAuthHeaders } from './auth-headers';
|
||||
import { handleApiError } from './error-handler';
|
||||
@@ -1893,6 +1898,36 @@ export const itemMasterApi = {
|
||||
}
|
||||
},
|
||||
|
||||
update: async (id: number, data: Partial<UnitOptionRequest>): Promise<ApiResponse<UnitOptionResponse>> => {
|
||||
const startTime = apiLogger.logRequest('PUT', `${BASE_URL}/item-master/unit-options/${id}`, data);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/unit-options/${id}`, {
|
||||
method: 'PUT',
|
||||
headers,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<UnitOptionResponse> = await response.json();
|
||||
apiLogger.logResponse('PUT', `${BASE_URL}/item-master/unit-options/${id}`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('PUT', `${BASE_URL}/item-master/unit-options/${id}`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('PUT', `${BASE_URL}/item-master/unit-options/${id}`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
delete: async (id: number): Promise<ApiResponse<void>> => {
|
||||
const startTime = apiLogger.logRequest('DELETE', `${BASE_URL}/item-master/unit-options/${id}`);
|
||||
|
||||
@@ -1922,4 +1957,276 @@ export const itemMasterApi = {
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// 재질 관리
|
||||
// ============================================
|
||||
materials: {
|
||||
list: async (): Promise<ApiResponse<any[]>> => {
|
||||
const startTime = apiLogger.logRequest('GET', `${BASE_URL}/item-master/materials`);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/materials`, {
|
||||
method: 'GET',
|
||||
headers,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<any[]> = await response.json();
|
||||
apiLogger.logResponse('GET', `${BASE_URL}/item-master/materials`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('GET', `${BASE_URL}/item-master/materials`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('GET', `${BASE_URL}/item-master/materials`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
create: async (data: {
|
||||
material_code: string;
|
||||
material_name: string;
|
||||
material_type: string;
|
||||
thickness?: string;
|
||||
description?: string;
|
||||
is_active?: boolean;
|
||||
}): Promise<ApiResponse<any>> => {
|
||||
const startTime = apiLogger.logRequest('POST', `${BASE_URL}/item-master/materials`, data);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/materials`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<any> = await response.json();
|
||||
apiLogger.logResponse('POST', `${BASE_URL}/item-master/materials`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('POST', `${BASE_URL}/item-master/materials`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('POST', `${BASE_URL}/item-master/materials`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
update: async (id: number | string, data: {
|
||||
material_code?: string;
|
||||
material_name?: string;
|
||||
material_type?: string;
|
||||
thickness?: string;
|
||||
description?: string;
|
||||
is_active?: boolean;
|
||||
}): Promise<ApiResponse<any>> => {
|
||||
const startTime = apiLogger.logRequest('PUT', `${BASE_URL}/item-master/materials/${id}`, data);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/materials/${id}`, {
|
||||
method: 'PUT',
|
||||
headers,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<any> = await response.json();
|
||||
apiLogger.logResponse('PUT', `${BASE_URL}/item-master/materials/${id}`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('PUT', `${BASE_URL}/item-master/materials/${id}`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('PUT', `${BASE_URL}/item-master/materials/${id}`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
delete: async (id: number | string): Promise<ApiResponse<void>> => {
|
||||
const startTime = apiLogger.logRequest('DELETE', `${BASE_URL}/item-master/materials/${id}`);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/materials/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<void> = await response.json();
|
||||
apiLogger.logResponse('DELETE', `${BASE_URL}/item-master/materials/${id}`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('DELETE', `${BASE_URL}/item-master/materials/${id}`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('DELETE', `${BASE_URL}/item-master/materials/${id}`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// 표면처리 관리
|
||||
// ============================================
|
||||
treatments: {
|
||||
list: async (): Promise<ApiResponse<any[]>> => {
|
||||
const startTime = apiLogger.logRequest('GET', `${BASE_URL}/item-master/surface-treatments`);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/surface-treatments`, {
|
||||
method: 'GET',
|
||||
headers,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<any[]> = await response.json();
|
||||
apiLogger.logResponse('GET', `${BASE_URL}/item-master/surface-treatments`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('GET', `${BASE_URL}/item-master/surface-treatments`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('GET', `${BASE_URL}/item-master/surface-treatments`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
create: async (data: {
|
||||
treatment_code: string;
|
||||
treatment_name: string;
|
||||
treatment_type: string;
|
||||
description?: string;
|
||||
is_active?: boolean;
|
||||
}): Promise<ApiResponse<any>> => {
|
||||
const startTime = apiLogger.logRequest('POST', `${BASE_URL}/item-master/surface-treatments`, data);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/surface-treatments`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<any> = await response.json();
|
||||
apiLogger.logResponse('POST', `${BASE_URL}/item-master/surface-treatments`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('POST', `${BASE_URL}/item-master/surface-treatments`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('POST', `${BASE_URL}/item-master/surface-treatments`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
update: async (id: number | string, data: {
|
||||
treatment_code?: string;
|
||||
treatment_name?: string;
|
||||
treatment_type?: string;
|
||||
description?: string;
|
||||
is_active?: boolean;
|
||||
}): Promise<ApiResponse<any>> => {
|
||||
const startTime = apiLogger.logRequest('PUT', `${BASE_URL}/item-master/surface-treatments/${id}`, data);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/surface-treatments/${id}`, {
|
||||
method: 'PUT',
|
||||
headers,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<any> = await response.json();
|
||||
apiLogger.logResponse('PUT', `${BASE_URL}/item-master/surface-treatments/${id}`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('PUT', `${BASE_URL}/item-master/surface-treatments/${id}`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('PUT', `${BASE_URL}/item-master/surface-treatments/${id}`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
delete: async (id: number | string): Promise<ApiResponse<void>> => {
|
||||
const startTime = apiLogger.logRequest('DELETE', `${BASE_URL}/item-master/surface-treatments/${id}`);
|
||||
|
||||
try {
|
||||
const headers = getAuthHeaders();
|
||||
const response = await fetch(`${BASE_URL}/item-master/surface-treatments/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await handleApiError(response);
|
||||
}
|
||||
|
||||
const result: ApiResponse<void> = await response.json();
|
||||
apiLogger.logResponse('DELETE', `${BASE_URL}/item-master/surface-treatments/${id}`, response.status, result, startTime);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
apiLogger.logError('DELETE', `${BASE_URL}/item-master/surface-treatments/${id}`, error, undefined, startTime);
|
||||
throw new Error('네트워크 연결을 확인해주세요. 서버에 연결할 수 없습니다.');
|
||||
}
|
||||
|
||||
apiLogger.logError('DELETE', `${BASE_URL}/item-master/surface-treatments/${id}`, error as Error, undefined, startTime);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -376,9 +376,9 @@ export const transformUnitOptionResponse = (
|
||||
): { id: string; value: string; label: string; isActive: boolean } => {
|
||||
return {
|
||||
id: response.id.toString(), // number → string 변환
|
||||
value: response.value,
|
||||
label: response.label,
|
||||
isActive: true, // API에 없으므로 기본값
|
||||
value: response.unit_code,
|
||||
label: response.unit_name,
|
||||
isActive: response.is_active,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user