"use client"; import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Plus } from "lucide-react"; import { ItemSelectionModal } from "./ItemSelectionModal"; import { RepeaterTable } from "./RepeaterTable"; import { ModalRepeaterTableProps, RepeaterColumnConfig } from "./types"; import { useCalculation } from "./useCalculation"; import { cn } from "@/lib/utils"; interface ModalRepeaterTableComponentProps extends Partial { config?: ModalRepeaterTableProps; } export function ModalRepeaterTableComponent({ config, sourceTable: propSourceTable, sourceColumns: propSourceColumns, sourceSearchFields: propSourceSearchFields, modalTitle: propModalTitle, modalButtonText: propModalButtonText, multiSelect: propMultiSelect, columns: propColumns, calculationRules: propCalculationRules, value: propValue, onChange: propOnChange, uniqueField: propUniqueField, filterCondition: propFilterCondition, companyCode: propCompanyCode, className, }: ModalRepeaterTableComponentProps) { // config prop 우선, 없으면 개별 prop 사용 const sourceTable = config?.sourceTable || propSourceTable || ""; // sourceColumns에서 빈 문자열 필터링 const rawSourceColumns = config?.sourceColumns || propSourceColumns || []; const sourceColumns = rawSourceColumns.filter((col) => col && col.trim() !== ""); const sourceSearchFields = config?.sourceSearchFields || propSourceSearchFields || []; const modalTitle = config?.modalTitle || propModalTitle || "항목 검색"; const modalButtonText = config?.modalButtonText || propModalButtonText || "품목 검색"; const multiSelect = config?.multiSelect ?? propMultiSelect ?? true; const calculationRules = config?.calculationRules || propCalculationRules || []; const value = config?.value || propValue || []; const onChange = config?.onChange || propOnChange || (() => {}); // uniqueField 자동 보정: order_no는 item_info 테이블에 없으므로 item_number로 변경 const rawUniqueField = config?.uniqueField || propUniqueField; const uniqueField = rawUniqueField === "order_no" && sourceTable === "item_info" ? "item_number" : rawUniqueField; const filterCondition = config?.filterCondition || propFilterCondition || {}; const companyCode = config?.companyCode || propCompanyCode; const [modalOpen, setModalOpen] = useState(false); // columns가 비어있으면 sourceColumns로부터 자동 생성 const columns = React.useMemo((): RepeaterColumnConfig[] => { const configuredColumns = config?.columns || propColumns || []; if (configuredColumns.length > 0) { console.log("✅ 설정된 columns 사용:", configuredColumns); return configuredColumns; } // columns가 비어있으면 sourceColumns로부터 자동 생성 if (sourceColumns.length > 0) { console.log("🔄 sourceColumns로부터 자동 생성:", sourceColumns); const autoColumns: RepeaterColumnConfig[] = sourceColumns.map((field) => ({ field: field, label: field, // 필드명을 라벨로 사용 (나중에 설정에서 변경 가능) editable: false, // 기본적으로 읽기 전용 type: "text" as const, width: "150px", })); console.log("📋 자동 생성된 columns:", autoColumns); return autoColumns; } console.warn("⚠️ columns와 sourceColumns 모두 비어있음!"); return []; }, [config?.columns, propColumns, sourceColumns]); // 초기 props 로깅 useEffect(() => { if (rawSourceColumns.length !== sourceColumns.length) { console.warn(`⚠️ sourceColumns 필터링: ${rawSourceColumns.length}개 → ${sourceColumns.length}개 (빈 문자열 제거)`); } if (rawUniqueField !== uniqueField) { console.warn(`⚠️ uniqueField 자동 보정: "${rawUniqueField}" → "${uniqueField}"`); } console.log("🎬 ModalRepeaterTableComponent 마운트:", { columnsLength: columns.length, sourceTable, sourceColumns, uniqueField, }); if (columns.length === 0) { console.error("❌ columns가 비어있습니다! sourceColumns:", sourceColumns); } else { console.log("✅ columns 설정 완료:", columns.map(c => c.label || c.field).join(", ")); } }, []); // value 변경 감지 useEffect(() => { console.log("📦 ModalRepeaterTableComponent value 변경:", { valueLength: value.length, }); }, [value]); const { calculateRow, calculateAll } = useCalculation(calculationRules); // 초기 데이터에 계산 필드 적용 useEffect(() => { if (value.length > 0 && calculationRules.length > 0) { const calculated = calculateAll(value); // 값이 실제로 변경된 경우만 업데이트 if (JSON.stringify(calculated) !== JSON.stringify(value)) { onChange(calculated); } } }, []); const handleAddItems = (items: any[]) => { console.log("➕ handleAddItems 호출:", items.length, "개 항목"); console.log("📋 소스 데이터:", items); // 매핑 규칙에 따라 데이터 변환 const mappedItems = items.map((sourceItem) => { const newItem: any = {}; columns.forEach((col) => { console.log(`🔄 컬럼 "${col.field}" 매핑 처리:`, col.mapping); // 1. 매핑 규칙이 있는 경우 if (col.mapping) { if (col.mapping.type === "source") { // 소스 테이블 컬럼에서 복사 const sourceField = col.mapping.sourceField; if (sourceField && sourceItem[sourceField] !== undefined) { newItem[col.field] = sourceItem[sourceField]; console.log(` ✅ 소스 복사: ${sourceField} → ${col.field}:`, newItem[col.field]); } else { console.warn(` ⚠️ 소스 필드 "${sourceField}" 값이 없음`); } } else if (col.mapping.type === "reference") { // 외부 테이블 참조 (TODO: API 호출 필요) console.log(` ⏳ 참조 조회 필요: ${col.mapping.referenceTable}.${col.mapping.referenceField}`); // 현재는 빈 값으로 설정 (나중에 API 호출로 구현) newItem[col.field] = undefined; } else if (col.mapping.type === "manual") { // 사용자 입력 (빈 값) newItem[col.field] = undefined; console.log(` ✏️ 수동 입력 필드`); } } // 2. 매핑 규칙이 없는 경우 - 소스 데이터에서 같은 필드명으로 복사 else if (sourceItem[col.field] !== undefined) { newItem[col.field] = sourceItem[col.field]; console.log(` 📝 직접 복사: ${col.field}:`, newItem[col.field]); } // 3. 기본값 적용 if (col.defaultValue !== undefined && newItem[col.field] === undefined) { newItem[col.field] = col.defaultValue; console.log(` 🎯 기본값 적용: ${col.field}:`, col.defaultValue); } }); console.log("📦 변환된 항목:", newItem); return newItem; }); // 계산 필드 업데이트 const calculatedItems = calculateAll(mappedItems); // 기존 데이터에 추가 const newData = [...value, ...calculatedItems]; console.log("✅ 최종 데이터:", newData.length, "개 항목"); onChange(newData); }; const handleRowChange = (index: number, newRow: any) => { // 계산 필드 업데이트 const calculatedRow = calculateRow(newRow); // 데이터 업데이트 const newData = [...value]; newData[index] = calculatedRow; onChange(newData); }; const handleRowDelete = (index: number) => { const newData = value.filter((_, i) => i !== index); onChange(newData); }; // 컬럼명 -> 라벨명 매핑 생성 const columnLabels = columns.reduce((acc, col) => { acc[col.field] = col.label; return acc; }, {} as Record); return (
{/* 추가 버튼 */}
{value.length > 0 && `${value.length}개 항목`}
{/* Repeater 테이블 */} {/* 항목 선택 모달 */}
); }