refactor(WEB): 코드 품질 개선 및 불필요 코드 제거
- 미사용 import/변수/console.log 대량 정리 (100+개 파일) - ItemMasterContext 간소화 (미사용 로직 제거) - IntegratedListTemplateV2 / UniversalListPage 개선 - 결재 컴포넌트(ApprovalBox, DraftBox, ReferenceBox) 정리 - HR 컴포넌트(급여/휴가/부서) 코드 간소화 - globals.css 스타일 정리 및 개선 - AuthenticatedLayout 개선 - middleware CSP 정리 - proxy route 불필요 로깅 제거 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -101,8 +101,7 @@ export function useFieldDetection({
|
||||
// "구매 부품", "PURCHASED", "구매부품" 등 다양한 형태 지원
|
||||
const isPurchased = currentPartType.includes('구매') || currentPartType.toUpperCase() === 'PURCHASED';
|
||||
|
||||
// console.log('[useFieldDetection] 부품 유형 감지:', { partTypeFieldKey: foundPartTypeKey, currentPartType, isBending, isAssembly, isPurchased });
|
||||
|
||||
//
|
||||
return {
|
||||
partTypeFieldKey: foundPartTypeKey,
|
||||
selectedPartType: currentPartType,
|
||||
@@ -133,8 +132,7 @@ export function useFieldDetection({
|
||||
fieldKey.includes('부품구성');
|
||||
|
||||
if (isCheckbox && isBomRelated) {
|
||||
// console.log('[useFieldDetection] BOM 체크박스 필드 발견:', { fieldKey, fieldName });
|
||||
return field.field_key || `field_${field.id}`;
|
||||
// return field.field_key || `field_${field.id}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,12 +152,10 @@ export function useFieldDetection({
|
||||
fieldKey.includes('부품구성');
|
||||
|
||||
if (isCheckbox && isBomRelated) {
|
||||
// console.log('[useFieldDetection] BOM 체크박스 필드 발견 (직접필드):', { fieldKey, fieldName });
|
||||
return field.field_key || `field_${field.id}`;
|
||||
// return field.field_key || `field_${field.id}`;
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('[useFieldDetection] BOM 체크박스 필드를 찾지 못함');
|
||||
return '';
|
||||
}, [structure]);
|
||||
|
||||
|
||||
@@ -115,7 +115,6 @@ export function useFileHandling({
|
||||
if (typeof filesRaw === 'string') {
|
||||
try {
|
||||
filesRaw = JSON.parse(filesRaw);
|
||||
console.log('[useFileHandling] files JSON 문자열 파싱 완료');
|
||||
} catch (e) {
|
||||
console.error('[useFileHandling] files JSON 파싱 실패:', e);
|
||||
filesRaw = undefined;
|
||||
@@ -125,12 +124,6 @@ export function useFileHandling({
|
||||
const files = filesRaw as FilesObject | undefined;
|
||||
|
||||
// 2025-12-15: 파일 로드 디버깅
|
||||
console.log('[useFileHandling] 파일 로드 시작');
|
||||
console.log('[useFileHandling] initialData.files (raw):', initialData.files);
|
||||
console.log('[useFileHandling] filesRaw 타입:', typeof filesRaw);
|
||||
console.log('[useFileHandling] files 변수:', files);
|
||||
console.log('[useFileHandling] specification_file:', files?.specification_file);
|
||||
console.log('[useFileHandling] certification_file:', files?.certification_file);
|
||||
|
||||
// 전개도 파일 (배열의 마지막 파일 = 최신 파일을 가져옴)
|
||||
const bendingFileArr = files?.bending_diagram;
|
||||
@@ -138,12 +131,9 @@ export function useFileHandling({
|
||||
? bendingFileArr[bendingFileArr.length - 1]
|
||||
: undefined;
|
||||
if (bendingFile) {
|
||||
console.log('[useFileHandling] bendingFile 전체 객체:', bendingFile);
|
||||
console.log('[useFileHandling] bendingFile 키 목록:', Object.keys(bendingFile));
|
||||
setExistingBendingDiagram(bendingFile.file_path);
|
||||
// API에서 id 또는 file_id로 올 수 있음
|
||||
const bendingFileId = bendingFile.id || bendingFile.file_id;
|
||||
console.log('[useFileHandling] bendingFile ID 추출:', { id: bendingFile.id, file_id: bendingFile.file_id, final: bendingFileId });
|
||||
setExistingBendingDiagramFileId(bendingFileId as number);
|
||||
} else if (initialData.bending_diagram) {
|
||||
setExistingBendingDiagram(initialData.bending_diagram as string);
|
||||
@@ -154,14 +144,11 @@ export function useFileHandling({
|
||||
const specFile = specFileArr && specFileArr.length > 0
|
||||
? specFileArr[specFileArr.length - 1]
|
||||
: undefined;
|
||||
console.log('[useFileHandling] specFile 전체 객체:', specFile);
|
||||
console.log('[useFileHandling] specFile 키 목록:', specFile ? Object.keys(specFile) : 'undefined');
|
||||
if (specFile?.file_path) {
|
||||
setExistingSpecificationFile(specFile.file_path);
|
||||
setExistingSpecificationFileName(specFile.file_name || '시방서');
|
||||
// API에서 id 또는 file_id로 올 수 있음
|
||||
const specFileId = specFile.id || specFile.file_id;
|
||||
console.log('[useFileHandling] specFile ID 추출:', { id: specFile.id, file_id: specFile.file_id, final: specFileId });
|
||||
setExistingSpecificationFileId(specFileId as number || null);
|
||||
} else {
|
||||
// 파일이 없으면 상태 초기화 (이전 값 제거)
|
||||
@@ -175,14 +162,11 @@ export function useFileHandling({
|
||||
const certFile = certFileArr && certFileArr.length > 0
|
||||
? certFileArr[certFileArr.length - 1]
|
||||
: undefined;
|
||||
console.log('[useFileHandling] certFile 전체 객체:', certFile);
|
||||
console.log('[useFileHandling] certFile 키 목록:', certFile ? Object.keys(certFile) : 'undefined');
|
||||
if (certFile?.file_path) {
|
||||
setExistingCertificationFile(certFile.file_path);
|
||||
setExistingCertificationFileName(certFile.file_name || '인정서');
|
||||
// API에서 id 또는 file_id로 올 수 있음
|
||||
const certFileId = certFile.id || certFile.file_id;
|
||||
console.log('[useFileHandling] certFile ID 추출:', { id: certFile.id, file_id: certFile.file_id, final: certFileId });
|
||||
setExistingCertificationFileId(certFileId as number || null);
|
||||
} else {
|
||||
// 파일이 없으면 상태 초기화 (이전 값 제거)
|
||||
@@ -244,13 +228,6 @@ export function useFileHandling({
|
||||
onBendingDiagramDeleted?: () => void;
|
||||
}
|
||||
) => {
|
||||
console.log('[useFileHandling] handleDeleteFile 호출:', {
|
||||
fileType,
|
||||
propItemId,
|
||||
existingBendingDiagramFileId,
|
||||
existingSpecificationFileId,
|
||||
existingCertificationFileId,
|
||||
});
|
||||
|
||||
if (!propItemId) {
|
||||
console.error('[useFileHandling] propItemId가 없습니다');
|
||||
@@ -267,7 +244,6 @@ export function useFileHandling({
|
||||
fileId = existingCertificationFileId;
|
||||
}
|
||||
|
||||
console.log('[useFileHandling] 삭제할 파일 ID:', fileId);
|
||||
|
||||
if (!fileId) {
|
||||
console.error('[useFileHandling] 파일 ID를 찾을 수 없습니다:', fileType);
|
||||
|
||||
@@ -34,12 +34,10 @@ export function useFormStructure(
|
||||
const initData = await itemMasterApi.init();
|
||||
|
||||
// 단위 옵션 저장 (SimpleUnitOption 형식으로 변환)
|
||||
console.log('[useFormStructure] API initData.unitOptions:', initData.unitOptions);
|
||||
const simpleUnitOptions: SimpleUnitOption[] = (initData.unitOptions || []).map((u) => ({
|
||||
label: u.unit_name,
|
||||
value: u.unit_code,
|
||||
}));
|
||||
console.log('[useFormStructure] Processed unitOptions:', simpleUnitOptions.length, 'items');
|
||||
setUnitOptions(simpleUnitOptions);
|
||||
|
||||
// 2. 품목 유형에 해당하는 페이지 찾기
|
||||
|
||||
@@ -74,8 +74,7 @@ export function usePartTypeHandling({
|
||||
|
||||
// 이전 값이 있고, 현재 값과 다른 경우에만 초기화
|
||||
if (prevPartType && prevPartType !== currentPartType) {
|
||||
// console.log('[usePartTypeHandling] 부품 유형 변경 감지:', prevPartType, '→', currentPartType);
|
||||
|
||||
//
|
||||
// setTimeout으로 다음 틱에서 초기화 실행
|
||||
// → 부품 유형 Select 값 변경이 먼저 완료된 후 초기화
|
||||
setTimeout(() => {
|
||||
@@ -121,8 +120,7 @@ export function usePartTypeHandling({
|
||||
|
||||
// 중복 제거 후 초기화
|
||||
const uniqueFields = [...new Set(fieldsToReset)];
|
||||
// console.log('[usePartTypeHandling] 초기화할 필드:', uniqueFields);
|
||||
|
||||
//
|
||||
uniqueFields.forEach((fieldKey) => {
|
||||
setFieldValue(fieldKey, '');
|
||||
});
|
||||
@@ -152,11 +150,6 @@ export function usePartTypeHandling({
|
||||
}, 0);
|
||||
|
||||
const sumString = totalSum.toString();
|
||||
console.log('[usePartTypeHandling] bendingDetails 폭 합계 → formData 동기화:', {
|
||||
widthSumKey: bendingFieldKeys.widthSum,
|
||||
totalSum,
|
||||
bendingDetailsCount: bendingDetails.length,
|
||||
});
|
||||
|
||||
setFieldValue(bendingFieldKeys.widthSum, sumString);
|
||||
bendingWidthSumSyncedRef.current = true;
|
||||
@@ -175,14 +168,12 @@ export function usePartTypeHandling({
|
||||
|
||||
// 품목명이 변경되었고, 이전 값이 있었을 때만 종류 필드 초기화
|
||||
if (prevItemNameValue && prevItemNameValue !== currentItemNameValue) {
|
||||
// console.log('[usePartTypeHandling] 품목명 변경 감지:', prevItemNameValue, '→', currentItemNameValue);
|
||||
|
||||
//
|
||||
// 모든 종류 필드 값 초기화
|
||||
allCategoryKeysWithIds.forEach(({ key }) => {
|
||||
const currentVal = (formData[key] as string) || '';
|
||||
if (currentVal) {
|
||||
// console.log('[usePartTypeHandling] 종류 필드 초기화:', key);
|
||||
setFieldValue(key, '');
|
||||
// setFieldValue(key, '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -129,7 +129,6 @@ export default function DynamicItemForm({
|
||||
useEffect(() => {
|
||||
if (mode === 'edit' && initialBomLines && initialBomLines.length > 0) {
|
||||
setBomLines(initialBomLines);
|
||||
console.log('[DynamicItemForm] initialBomLines로 BOM 데이터 로드:', initialBomLines.length, '건');
|
||||
}
|
||||
}, [mode, initialBomLines]);
|
||||
|
||||
@@ -159,7 +158,6 @@ export default function DynamicItemForm({
|
||||
.map((item: { code?: string; item_code?: string }) => item.code || item.item_code || '')
|
||||
.filter((code: string) => code);
|
||||
setExistingItemCodes(codes);
|
||||
// console.log('[DynamicItemForm] PT 기존 품목코드 로드:', codes.length, '개');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[DynamicItemForm] PT 품목코드 조회 실패:', err);
|
||||
@@ -213,18 +211,9 @@ export default function DynamicItemForm({
|
||||
const [isEditDataMapped, setIsEditDataMapped] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('[DynamicItemForm] Edit useEffect 체크:', {
|
||||
mode,
|
||||
hasStructure: !!structure,
|
||||
hasInitialData: !!initialData,
|
||||
isEditDataMapped,
|
||||
structureSections: structure?.sections?.length,
|
||||
});
|
||||
|
||||
if (mode !== 'edit' || !structure || !initialData || isEditDataMapped) return;
|
||||
|
||||
console.log('[DynamicItemForm] Edit mode: initialData 직접 로드 (field_key 통일됨)');
|
||||
console.log('[DynamicItemForm] initialData:', initialData);
|
||||
|
||||
// structure의 field_key들 확인
|
||||
const fieldKeys: string[] = [];
|
||||
@@ -233,8 +222,6 @@ export default function DynamicItemForm({
|
||||
fieldKeys.push(f.field.field_key || `field_${f.field.id}`);
|
||||
});
|
||||
});
|
||||
console.log('[DynamicItemForm] structure field_keys:', fieldKeys);
|
||||
console.log('[DynamicItemForm] initialData keys:', Object.keys(initialData));
|
||||
|
||||
// field_key가 통일되었으므로 initialData를 그대로 사용
|
||||
// 기존 레거시 데이터(98_unit 형식)도 그대로 동작
|
||||
@@ -348,7 +335,6 @@ export default function DynamicItemForm({
|
||||
// PT (절곡/조립) 전개도 이미지 업로드
|
||||
if (selectedItemType === 'PT' && (isBendingPart || isAssemblyPart) && bendingDiagramFile) {
|
||||
try {
|
||||
console.log('[DynamicItemForm] 전개도 파일 업로드 시작:', bendingDiagramFile.name);
|
||||
await uploadItemFile(itemId, bendingDiagramFile, 'bending_diagram', {
|
||||
fieldKey: 'bending_diagram',
|
||||
// 수정 모드: 기존 파일 ID가 있으면 덮어쓰기, 없으면 새 파일 등록
|
||||
@@ -359,7 +345,6 @@ export default function DynamicItemForm({
|
||||
type: d.shaded ? 'shaded' : 'normal',
|
||||
})) : undefined,
|
||||
});
|
||||
console.log('[DynamicItemForm] 전개도 파일 업로드 성공');
|
||||
} catch (error) {
|
||||
if (isNextRedirectError(error)) throw error;
|
||||
console.error('[DynamicItemForm] 전개도 파일 업로드 실패:', error);
|
||||
@@ -370,13 +355,11 @@ export default function DynamicItemForm({
|
||||
// FG (제품) 시방서 업로드
|
||||
if (selectedItemType === 'FG' && specificationFile) {
|
||||
try {
|
||||
console.log('[DynamicItemForm] 시방서 파일 업로드 시작:', specificationFile.name);
|
||||
await uploadItemFile(itemId, specificationFile, 'specification', {
|
||||
fieldKey: 'specification_file',
|
||||
// 수정 모드: 기존 파일 ID가 있으면 덮어쓰기, 없으면 새 파일 등록
|
||||
fileId: existingSpecificationFileId ?? undefined,
|
||||
});
|
||||
console.log('[DynamicItemForm] 시방서 파일 업로드 성공');
|
||||
} catch (error) {
|
||||
if (isNextRedirectError(error)) throw error;
|
||||
console.error('[DynamicItemForm] 시방서 파일 업로드 실패:', error);
|
||||
@@ -387,7 +370,6 @@ export default function DynamicItemForm({
|
||||
// FG (제품) 인정서 업로드
|
||||
if (selectedItemType === 'FG' && certificationFile) {
|
||||
try {
|
||||
console.log('[DynamicItemForm] 인정서 파일 업로드 시작:', certificationFile.name);
|
||||
// formData에서 인정서 관련 필드 추출
|
||||
const certNumber = Object.entries(formData).find(([key]) =>
|
||||
key.includes('certification_number') || key.includes('인정번호')
|
||||
@@ -407,7 +389,6 @@ export default function DynamicItemForm({
|
||||
certificationStartDate: certStartDate,
|
||||
certificationEndDate: certEndDate,
|
||||
});
|
||||
console.log('[DynamicItemForm] 인정서 파일 업로드 성공');
|
||||
} catch (error) {
|
||||
if (isNextRedirectError(error)) throw error;
|
||||
console.error('[DynamicItemForm] 인정서 파일 업로드 실패:', error);
|
||||
@@ -457,7 +438,6 @@ export default function DynamicItemForm({
|
||||
|
||||
// 2025-12-09: field_key 통일로 변환 로직 제거
|
||||
// formData의 field_key가 백엔드 필드명과 일치하므로 직접 사용
|
||||
console.log('[DynamicItemForm] 저장 시 formData:', formData);
|
||||
|
||||
// is_active 필드만 boolean 변환 (드롭다운 값 → boolean)
|
||||
const convertedData: Record<string, any> = {};
|
||||
@@ -509,8 +489,7 @@ export default function DynamicItemForm({
|
||||
finalSpec = convertedData.spec;
|
||||
}
|
||||
|
||||
// console.log('[DynamicItemForm] 품목명/규격 결정:', { finalName, finalSpec });
|
||||
|
||||
//
|
||||
// 품목코드 결정
|
||||
// 2025-12-11: 수정 모드에서는 기존 코드 유지 (자동생성으로 코드가 변경되는 버그 수정)
|
||||
// 생성 모드에서만 자동생성 코드 사용
|
||||
@@ -569,20 +548,17 @@ export default function DynamicItemForm({
|
||||
} : {}),
|
||||
} as DynamicFormData;
|
||||
|
||||
// console.log('[DynamicItemForm] 제출 데이터:', submitData);
|
||||
|
||||
//
|
||||
// 2025-12-11: 품목코드 중복 체크 (조립/절곡 부품만 해당)
|
||||
// PT-조립부품, PT-절곡부품은 품목코드가 자동생성되므로 중복 체크 필요
|
||||
const needsDuplicateCheck = selectedItemType === 'PT' && (isAssemblyPart || isBendingPart) && finalCode;
|
||||
|
||||
if (needsDuplicateCheck) {
|
||||
console.log('[DynamicItemForm] 품목코드 중복 체크:', finalCode);
|
||||
|
||||
// 수정 모드에서는 자기 자신 제외 (propItemId)
|
||||
const excludeId = mode === 'edit' ? propItemId : undefined;
|
||||
const duplicateResult = await checkItemCodeDuplicate(finalCode, excludeId);
|
||||
|
||||
console.log('[DynamicItemForm] 중복 체크 결과:', duplicateResult);
|
||||
|
||||
if (duplicateResult.isDuplicate) {
|
||||
// 중복 발견 → 다이얼로그 표시
|
||||
@@ -983,8 +959,7 @@ export default function DynamicItemForm({
|
||||
const isBomRequired = bomValue === true || bomValue === 'true' || bomValue === '1' || bomValue === 1;
|
||||
|
||||
// 디버깅 로그
|
||||
// console.log('[DynamicItemForm] BOM 체크 디버깅:', { bomRequiredFieldKey, bomValue, isBomRequired });
|
||||
|
||||
//
|
||||
if (!isBomRequired) return null;
|
||||
|
||||
return (
|
||||
@@ -1021,7 +996,6 @@ export default function DynamicItemForm({
|
||||
const blob = new Blob([uint8Array], { type: mimeType });
|
||||
const file = new File([blob], `bending_diagram_${Date.now()}.png`, { type: mimeType });
|
||||
setBendingDiagramFile(file);
|
||||
console.log('[DynamicItemForm] 드로잉 캔버스 → File 변환 성공:', file.name);
|
||||
} catch (error) {
|
||||
if (isNextRedirectError(error)) throw error;
|
||||
console.error('[DynamicItemForm] 드로잉 캔버스 → File 변환 실패:', error);
|
||||
|
||||
Reference in New Issue
Block a user