Files
sam-react-prod/src/components/items/DynamicItemForm/hooks/useFieldDetection.ts
byeongcheolryu 25f9d4e55f refactor: DynamicItemForm 훅/컴포넌트 분리 리팩토링
대규모 코드 구조 개선:
- useFieldDetection: 필드 감지 로직 분리
- useFileHandling: 파일 업로드 로직 분리
- useItemCodeGeneration: 품목코드 자동생성 로직 분리
- usePartTypeHandling: 파트타입 처리 로직 분리
- FormHeader, ValidationAlert, FileUploadFields 컴포넌트 분리
- DuplicateCodeDialog 컴포넌트 분리
- index.tsx 1300줄+ 감소로 가독성 및 유지보수성 향상
- BOM 검색 최적화 (검색어 입력 시에만 API 호출)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-16 17:40:55 +09:00

175 lines
6.0 KiB
TypeScript

'use client';
import { useMemo } from 'react';
import { DynamicFormData, ItemType, StructuredFieldConfig } from '../types';
import { ItemFieldResponse } from '@/types/item';
/**
* 부품 유형 탐지 결과
*/
export interface PartTypeDetectionResult {
/** 부품 유형 필드 키 (예: 'part_type') */
partTypeFieldKey: string;
/** 현재 선택된 부품 유형 값 (예: '절곡 부품') */
selectedPartType: string;
/** 절곡 부품 여부 */
isBendingPart: boolean;
/** 조립 부품 여부 */
isAssemblyPart: boolean;
/** 구매 부품 여부 */
isPurchasedPart: boolean;
}
/**
* useFieldDetection 훅 입력 파라미터
*/
export interface UseFieldDetectionParams {
/** 폼 구조 정보 */
structure: StructuredFieldConfig | null;
/** 현재 선택된 품목 유형 (FG, PT, SM, RM, CS) */
selectedItemType: ItemType;
/** 현재 폼 데이터 */
formData: DynamicFormData;
}
/**
* useFieldDetection 훅 반환 타입
*/
export interface FieldDetectionResult extends PartTypeDetectionResult {
/** BOM 필요 체크박스 필드 키 */
bomRequiredFieldKey: string;
}
/**
* 필드 탐지 커스텀 훅
*
* 폼 구조에서 특정 필드들을 탐지합니다:
* 1. PT 품목의 부품 유형 필드 (절곡/조립/구매 부품 판별)
* 2. BOM 필요 체크박스 필드
*
* @param params - 훅 입력 파라미터
* @returns 필드 탐지 결과
*/
export function useFieldDetection({
structure,
selectedItemType,
formData,
}: UseFieldDetectionParams): FieldDetectionResult {
// 부품 유형 필드 탐지 (PT 품목에서 절곡/조립/구매 부품 판별용)
const { partTypeFieldKey, selectedPartType, isBendingPart, isAssemblyPart, isPurchasedPart } = useMemo(() => {
if (!structure || selectedItemType !== 'PT') {
return {
partTypeFieldKey: '',
selectedPartType: '',
isBendingPart: false,
isAssemblyPart: false,
isPurchasedPart: false,
};
}
let foundPartTypeKey = '';
// 모든 필드에서 부품 유형 필드 찾기
const checkField = (fieldKey: string, field: ItemFieldResponse) => {
const fieldName = field.field_name || '';
// part_type, 부품유형, 부품 유형 등 탐지
const isPartType =
fieldKey.includes('part_type') ||
fieldName.includes('부품유형') ||
fieldName.includes('부품 유형');
if (isPartType && !foundPartTypeKey) {
foundPartTypeKey = fieldKey;
}
};
structure.sections.forEach((section) => {
section.fields.forEach((f) => {
const key = f.field.field_key || `field_${f.field.id}`;
checkField(key, f.field);
});
});
structure.directFields.forEach((f) => {
const key = f.field.field_key || `field_${f.field.id}`;
checkField(key, f.field);
});
const currentPartType = (formData[foundPartTypeKey] as string) || '';
// "절곡 부품", "BENDING", "절곡부품" 등 다양한 형태 지원
const isBending = currentPartType.includes('절곡') || currentPartType.toUpperCase() === 'BENDING';
// "조립 부품", "ASSEMBLY", "조립부품" 등 다양한 형태 지원
const isAssembly = currentPartType.includes('조립') || currentPartType.toUpperCase() === 'ASSEMBLY';
// "구매 부품", "PURCHASED", "구매부품" 등 다양한 형태 지원
const isPurchased = currentPartType.includes('구매') || currentPartType.toUpperCase() === 'PURCHASED';
// console.log('[useFieldDetection] 부품 유형 감지:', { partTypeFieldKey: foundPartTypeKey, currentPartType, isBending, isAssembly, isPurchased });
return {
partTypeFieldKey: foundPartTypeKey,
selectedPartType: currentPartType,
isBendingPart: isBending,
isAssemblyPart: isAssembly,
isPurchasedPart: isPurchased,
};
}, [structure, selectedItemType, formData]);
// BOM 필요 체크박스 필드 키 탐지 (structure에서 직접 검색)
const bomRequiredFieldKey = useMemo(() => {
if (!structure) return '';
// 모든 섹션의 필드에서 BOM 관련 체크박스 필드 찾기
for (const section of structure.sections) {
for (const f of section.fields) {
const field = f.field;
const fieldKey = field.field_key || '';
const fieldName = field.field_name || '';
const fieldType = field.field_type || '';
// 체크박스 타입이고 BOM 관련 필드인지 확인
const isCheckbox = fieldType.toLowerCase() === 'checkbox' || fieldType.toLowerCase() === 'boolean';
const isBomRelated =
fieldKey.toLowerCase().includes('bom') ||
fieldName.toLowerCase().includes('bom') ||
fieldName.includes('부품구성') ||
fieldKey.includes('부품구성');
if (isCheckbox && isBomRelated) {
// console.log('[useFieldDetection] BOM 체크박스 필드 발견:', { fieldKey, fieldName });
return field.field_key || `field_${field.id}`;
}
}
}
// 직접 필드에서도 찾기
for (const f of structure.directFields) {
const field = f.field;
const fieldKey = field.field_key || '';
const fieldName = field.field_name || '';
const fieldType = field.field_type || '';
const isCheckbox = fieldType.toLowerCase() === 'checkbox' || fieldType.toLowerCase() === 'boolean';
const isBomRelated =
fieldKey.toLowerCase().includes('bom') ||
fieldName.toLowerCase().includes('bom') ||
fieldName.includes('부품구성') ||
fieldKey.includes('부품구성');
if (isCheckbox && isBomRelated) {
// console.log('[useFieldDetection] BOM 체크박스 필드 발견 (직접필드):', { fieldKey, fieldName });
return field.field_key || `field_${field.id}`;
}
}
// console.log('[useFieldDetection] BOM 체크박스 필드를 찾지 못함');
return '';
}, [structure]);
return {
partTypeFieldKey,
selectedPartType,
isBendingPart,
isAssemblyPart,
isPurchasedPart,
bomRequiredFieldKey,
};
}