연쇄 통합관리
This commit is contained in:
194
frontend/hooks/useAutoFill.ts
Normal file
194
frontend/hooks/useAutoFill.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 자동 입력 (Auto-Fill) 커스텀 훅
|
||||
* 마스터 선택 시 여러 필드를 자동으로 입력하는 기능
|
||||
*/
|
||||
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import {
|
||||
cascadingAutoFillApi,
|
||||
AutoFillGroup,
|
||||
AutoFillOption,
|
||||
} from "@/lib/api/cascadingAutoFill";
|
||||
|
||||
interface AutoFillMapping {
|
||||
targetField: string;
|
||||
targetLabel: string;
|
||||
value: any;
|
||||
isEditable: boolean;
|
||||
isRequired: boolean;
|
||||
}
|
||||
|
||||
interface UseAutoFillProps {
|
||||
/** 자동 입력 그룹 코드 */
|
||||
groupCode: string;
|
||||
/** 자동 입력 데이터가 로드되었을 때 호출되는 콜백 */
|
||||
onAutoFill?: (data: Record<string, any>, mappings: AutoFillMapping[]) => void;
|
||||
}
|
||||
|
||||
interface UseAutoFillResult {
|
||||
/** 마스터 옵션 목록 */
|
||||
masterOptions: AutoFillOption[];
|
||||
/** 현재 선택된 마스터 값 */
|
||||
selectedMasterValue: string | null;
|
||||
/** 자동 입력된 데이터 */
|
||||
autoFilledData: Record<string, any>;
|
||||
/** 매핑 정보 */
|
||||
mappings: AutoFillMapping[];
|
||||
/** 그룹 정보 */
|
||||
groupInfo: AutoFillGroup | null;
|
||||
/** 로딩 상태 */
|
||||
isLoading: boolean;
|
||||
/** 에러 메시지 */
|
||||
error: string | null;
|
||||
/** 마스터 값 선택 핸들러 */
|
||||
selectMasterValue: (value: string) => Promise<void>;
|
||||
/** 마스터 옵션 새로고침 */
|
||||
refreshOptions: () => Promise<void>;
|
||||
/** 자동 입력 데이터 초기화 */
|
||||
clearAutoFill: () => void;
|
||||
}
|
||||
|
||||
export function useAutoFill({
|
||||
groupCode,
|
||||
onAutoFill,
|
||||
}: UseAutoFillProps): UseAutoFillResult {
|
||||
// 상태
|
||||
const [masterOptions, setMasterOptions] = useState<AutoFillOption[]>([]);
|
||||
const [selectedMasterValue, setSelectedMasterValue] = useState<string | null>(null);
|
||||
const [autoFilledData, setAutoFilledData] = useState<Record<string, any>>({});
|
||||
const [mappings, setMappings] = useState<AutoFillMapping[]>([]);
|
||||
const [groupInfo, setGroupInfo] = useState<AutoFillGroup | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// 마스터 옵션 로드
|
||||
const loadMasterOptions = useCallback(async () => {
|
||||
if (!groupCode) return;
|
||||
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
// 그룹 정보 로드
|
||||
const groupResponse = await cascadingAutoFillApi.getGroupDetail(groupCode);
|
||||
if (groupResponse.success && groupResponse.data) {
|
||||
setGroupInfo(groupResponse.data);
|
||||
}
|
||||
|
||||
// 마스터 옵션 로드
|
||||
const optionsResponse = await cascadingAutoFillApi.getMasterOptions(groupCode);
|
||||
if (optionsResponse.success && optionsResponse.data) {
|
||||
setMasterOptions(optionsResponse.data);
|
||||
} else {
|
||||
setError(optionsResponse.error || "옵션 로드 실패");
|
||||
}
|
||||
} catch (err: any) {
|
||||
setError(err.message || "옵션 로드 중 오류 발생");
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [groupCode]);
|
||||
|
||||
// 마스터 값 선택 시 자동 입력 데이터 로드
|
||||
const selectMasterValue = useCallback(
|
||||
async (value: string) => {
|
||||
if (!groupCode || !value) {
|
||||
setSelectedMasterValue(null);
|
||||
setAutoFilledData({});
|
||||
setMappings([]);
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
setSelectedMasterValue(value);
|
||||
|
||||
try {
|
||||
const response = await cascadingAutoFillApi.getData(groupCode, value);
|
||||
|
||||
if (response.success) {
|
||||
const data = response.data || {};
|
||||
const mappingInfo = response.mappings || [];
|
||||
|
||||
setAutoFilledData(data);
|
||||
setMappings(mappingInfo);
|
||||
|
||||
// 콜백 호출
|
||||
if (onAutoFill) {
|
||||
onAutoFill(data, mappingInfo);
|
||||
}
|
||||
} else {
|
||||
setError(response.error || "데이터 로드 실패");
|
||||
}
|
||||
} catch (err: any) {
|
||||
setError(err.message || "데이터 로드 중 오류 발생");
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[groupCode, onAutoFill]
|
||||
);
|
||||
|
||||
// 자동 입력 데이터 초기화
|
||||
const clearAutoFill = useCallback(() => {
|
||||
setSelectedMasterValue(null);
|
||||
setAutoFilledData({});
|
||||
setMappings([]);
|
||||
}, []);
|
||||
|
||||
// 초기 로드
|
||||
useEffect(() => {
|
||||
if (groupCode) {
|
||||
loadMasterOptions();
|
||||
}
|
||||
}, [groupCode, loadMasterOptions]);
|
||||
|
||||
return {
|
||||
masterOptions,
|
||||
selectedMasterValue,
|
||||
autoFilledData,
|
||||
mappings,
|
||||
groupInfo,
|
||||
isLoading,
|
||||
error,
|
||||
selectMasterValue,
|
||||
refreshOptions: loadMasterOptions,
|
||||
clearAutoFill,
|
||||
};
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 화면관리 시스템용 자동 입력 컴포넌트 설정 타입
|
||||
// =====================================================
|
||||
|
||||
export interface AutoFillConfig {
|
||||
/** 자동 입력 활성화 여부 */
|
||||
enabled: boolean;
|
||||
/** 자동 입력 그룹 코드 */
|
||||
groupCode: string;
|
||||
/** 마스터 필드명 (이 필드 선택 시 자동 입력 트리거) */
|
||||
masterField: string;
|
||||
/** 자동 입력 후 수정 가능 여부 (전체 설정) */
|
||||
allowEdit?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 폼 데이터에 자동 입력 적용
|
||||
*/
|
||||
export function applyAutoFillToFormData(
|
||||
formData: Record<string, any>,
|
||||
autoFilledData: Record<string, any>,
|
||||
mappings: AutoFillMapping[]
|
||||
): Record<string, any> {
|
||||
const result = { ...formData };
|
||||
|
||||
for (const mapping of mappings) {
|
||||
// 수정 불가능한 필드이거나 기존 값이 없는 경우에만 자동 입력
|
||||
if (!mapping.isEditable || !result[mapping.targetField]) {
|
||||
result[mapping.targetField] = autoFilledData[mapping.targetField];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user