"use client"; import React, { useState, useEffect } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Database, Search, Info } from "lucide-react"; import { WebTypeConfigPanelProps } from "@/lib/registry/types"; import { WidgetComponent, EntityTypeConfig } from "@/types/screen"; import { tableTypeApi } from "@/lib/api/screen"; export const EntityConfigPanel: React.FC = ({ component, onUpdateComponent, onUpdateProperty, }) => { const widget = component as WidgetComponent; const config = (widget.webTypeConfig as EntityTypeConfig) || {}; // 테이블 타입 관리에서 설정된 참조 테이블 정보 const [referenceInfo, setReferenceInfo] = useState<{ referenceTable: string; referenceColumn: string; displayColumn: string; isLoading: boolean; error: string | null; }>({ referenceTable: "", referenceColumn: "", displayColumn: "", isLoading: true, error: null, }); // 로컬 상태 (UI 관련 설정만) const [localConfig, setLocalConfig] = useState({ entityType: config.entityType || "", displayFields: config.displayFields || [], searchFields: config.searchFields || [], valueField: config.valueField || "", labelField: config.labelField || "", multiple: config.multiple || false, searchable: config.searchable !== false, placeholder: config.placeholder || "항목을 선택하세요", emptyMessage: config.emptyMessage || "검색 결과가 없습니다", pageSize: config.pageSize || 20, minSearchLength: config.minSearchLength || 1, defaultValue: config.defaultValue || "", required: config.required || false, readonly: config.readonly || false, apiEndpoint: config.apiEndpoint || "", filters: config.filters || {}, }); // 테이블 타입 관리에서 설정된 참조 테이블 정보 로드 useEffect(() => { const loadReferenceInfo = async () => { // 컴포넌트의 테이블명과 컬럼명이 있는 경우에만 조회 const tableName = widget.tableName; const columnName = widget.columnName; if (!tableName || !columnName) { setReferenceInfo({ referenceTable: "", referenceColumn: "", displayColumn: "", isLoading: false, error: "테이블 또는 컬럼 정보가 없습니다.", }); return; } try { // 테이블 타입 관리에서 컬럼 정보 조회 const columns = await tableTypeApi.getColumns(tableName); const columnInfo = columns.find((col: any) => (col.columnName || col.column_name) === columnName ); if (columnInfo) { const refTable = columnInfo.referenceTable || columnInfo.reference_table || ""; const refColumn = columnInfo.referenceColumn || columnInfo.reference_column || ""; const dispColumn = columnInfo.displayColumn || columnInfo.display_column || ""; // detailSettings에서도 정보 확인 (JSON 파싱) let detailSettings: any = {}; if (columnInfo.detailSettings) { try { if (typeof columnInfo.detailSettings === 'string') { detailSettings = JSON.parse(columnInfo.detailSettings); } else { detailSettings = columnInfo.detailSettings; } } catch { // JSON 파싱 실패 시 무시 } } const finalRefTable = refTable || detailSettings.referenceTable || ""; const finalRefColumn = refColumn || detailSettings.referenceColumn || ""; const finalDispColumn = dispColumn || detailSettings.displayColumn || ""; setReferenceInfo({ referenceTable: finalRefTable, referenceColumn: finalRefColumn, displayColumn: finalDispColumn, isLoading: false, error: null, }); // webTypeConfig에 참조 테이블 정보 자동 설정 if (finalRefTable) { const newConfig = { ...localConfig, valueField: finalRefColumn || "id", labelField: finalDispColumn || "name", }; setLocalConfig(newConfig); onUpdateProperty("webTypeConfig", newConfig); } } else { setReferenceInfo({ referenceTable: "", referenceColumn: "", displayColumn: "", isLoading: false, error: "컬럼 정보를 찾을 수 없습니다.", }); } } catch (error) { console.error("참조 테이블 정보 로드 실패:", error); setReferenceInfo({ referenceTable: "", referenceColumn: "", displayColumn: "", isLoading: false, error: "참조 테이블 정보 로드 실패", }); } }; loadReferenceInfo(); }, [widget.tableName, widget.columnName]); // 컴포넌트 변경 시 로컬 상태 동기화 useEffect(() => { const currentConfig = (widget.webTypeConfig as EntityTypeConfig) || {}; setLocalConfig({ entityType: currentConfig.entityType || "", displayFields: currentConfig.displayFields || [], searchFields: currentConfig.searchFields || [], valueField: currentConfig.valueField || referenceInfo.referenceColumn || "", labelField: currentConfig.labelField || referenceInfo.displayColumn || "", multiple: currentConfig.multiple || false, searchable: currentConfig.searchable !== false, placeholder: currentConfig.placeholder || "항목을 선택하세요", emptyMessage: currentConfig.emptyMessage || "검색 결과가 없습니다", pageSize: currentConfig.pageSize || 20, minSearchLength: currentConfig.minSearchLength || 1, defaultValue: currentConfig.defaultValue || "", required: currentConfig.required || false, readonly: currentConfig.readonly || false, apiEndpoint: currentConfig.apiEndpoint || "", filters: currentConfig.filters || {}, }); }, [widget.webTypeConfig, referenceInfo.referenceColumn, referenceInfo.displayColumn]); // 설정 업데이트 핸들러 (즉시 부모에게 전달 - 드롭다운, 체크박스 등) const updateConfig = (field: keyof EntityTypeConfig, value: any) => { const newConfig = { ...localConfig, [field]: value }; setLocalConfig(newConfig); onUpdateProperty("webTypeConfig", newConfig); }; // 입력 필드용 업데이트 (로컬 상태만) const updateConfigLocal = (field: keyof EntityTypeConfig, value: any) => { setLocalConfig({ ...localConfig, [field]: value }); }; // 입력 완료 시 부모에게 전달 const handleInputBlur = () => { onUpdateProperty("webTypeConfig", localConfig); }; return ( 엔티티 설정 데이터베이스 엔티티 선택 필드의 설정을 관리합니다. {/* 참조 테이블 정보 (테이블 타입 관리에서 설정된 값 - 읽기 전용) */}

참조 테이블 정보 테이블 타입 관리에서 설정

{referenceInfo.isLoading ? (

참조 테이블 정보 로딩 중...

) : referenceInfo.error ? (

{referenceInfo.error}

테이블 타입 관리에서 이 컬럼의 참조 테이블을 먼저 설정해주세요.

) : !referenceInfo.referenceTable ? (

참조 테이블이 설정되지 않았습니다.

테이블 타입 관리에서 이 컬럼의 참조 테이블을 먼저 설정해주세요.

) : (
참조 테이블:
{referenceInfo.referenceTable}
참조 컬럼:
{referenceInfo.referenceColumn || "-"}
표시 컬럼:
{referenceInfo.displayColumn || "-"}

이 정보는 테이블 타입 관리에서 변경할 수 있습니다.

)}
{/* UI 모드 설정 */}

UI 설정

{/* UI 모드 선택 */}

{(localConfig as any).uiMode === "select" && "검색 가능한 드롭다운 형태로 표시됩니다."} {(localConfig as any).uiMode === "modal" && "모달 팝업에서 데이터를 검색하고 선택합니다."} {((localConfig as any).uiMode === "combo" || !(localConfig as any).uiMode) && "입력 필드와 검색 버튼이 함께 표시됩니다."} {(localConfig as any).uiMode === "autocomplete" && "입력하면서 자동완성 목록이 표시됩니다."}

updateConfigLocal("placeholder", e.target.value)} onBlur={handleInputBlur} placeholder="항목을 선택하세요" className="text-xs" />
updateConfigLocal("emptyMessage", e.target.value)} onBlur={handleInputBlur} placeholder="검색 결과가 없습니다" className="text-xs" />
{/* 검색 설정 */}

검색 설정

updateConfig("minSearchLength", parseInt(e.target.value))} min={0} max={10} className="text-xs" />
updateConfig("pageSize", parseInt(e.target.value))} min={5} max={100} className="text-xs" />

항목을 검색할 수 있습니다.

updateConfig("searchable", checked)} />

여러 항목을 선택할 수 있습니다.

updateConfig("multiple", checked)} />
{/* 상태 설정 */}

상태 설정

반드시 항목을 선택해야 합니다.

updateConfig("required", checked)} />

값을 변경할 수 없습니다.

updateConfig("readonly", checked)} />
{/* 미리보기 */}

미리보기

{localConfig.placeholder || "항목을 선택하세요"} {localConfig.searchable && }
테이블: {referenceInfo.referenceTable || "미설정"}
값 필드: {localConfig.valueField || referenceInfo.referenceColumn || "-"}
표시 필드: {localConfig.labelField || referenceInfo.displayColumn || "-"}
{localConfig.multiple && / 다중선택} {localConfig.required && / 필수}
); }; EntityConfigPanel.displayName = "EntityConfigPanel";