"use client"; import React, { useState, useEffect } from "react"; import { Settings, Database } from "lucide-react"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Checkbox } from "@/components/ui/checkbox"; import { Separator } from "@/components/ui/separator"; import { useWebTypes } from "@/hooks/admin/useWebTypes"; import { getConfigPanelComponent } from "@/lib/utils/getConfigPanelComponent"; import { ComponentData, WidgetComponent, FileComponent, WebTypeConfig, TableInfo, LayoutComponent, } from "@/types/screen"; // 레거시 ButtonConfigPanel 제거됨 import { FileComponentConfigPanel } from "./FileComponentConfigPanel"; import { WebTypeConfigPanel } from "./WebTypeConfigPanel"; import { isFileComponent } from "@/lib/utils/componentTypeUtils"; import { BaseInputType, getBaseInputType, getDetailTypes, DetailTypeOption } from "@/types/input-type-mapping"; // 새로운 컴포넌트 설정 패널들 import import { ButtonConfigPanel as NewButtonConfigPanel } from "../config-panels/ButtonConfigPanel"; import { CardConfigPanel } from "../config-panels/CardConfigPanel"; import { DashboardConfigPanel } from "../config-panels/DashboardConfigPanel"; import { StatsCardConfigPanel } from "../config-panels/StatsCardConfigPanel"; import { ProgressBarConfigPanel } from "../config-panels/ProgressBarConfigPanel"; import { ChartConfigPanel } from "../config-panels/ChartConfigPanel"; import { AlertConfigPanel } from "../config-panels/AlertConfigPanel"; import { BadgeConfigPanel } from "../config-panels/BadgeConfigPanel"; // 동적 컴포넌트 설정 패널 import { DynamicComponentConfigPanel } from "@/lib/utils/getComponentConfigPanel"; // ComponentRegistry import (동적 ConfigPanel 가져오기용) import { ComponentRegistry } from "@/lib/registry/ComponentRegistry"; interface DetailSettingsPanelProps { selectedComponent?: ComponentData; onUpdateProperty: (componentId: string, path: string, value: any) => void; currentTable?: TableInfo; // 현재 화면의 테이블 정보 currentTableName?: string; // 현재 화면의 테이블명 tables?: TableInfo[]; // 전체 테이블 목록 currentScreenCompanyCode?: string; // 현재 편집 중인 화면의 회사 코드 } export const DetailSettingsPanel: React.FC = ({ selectedComponent, onUpdateProperty, currentTable, currentTableName, tables = [], // 기본값 빈 배열 currentScreenCompanyCode, }) => { // 데이터베이스에서 입력 가능한 웹타입들을 동적으로 가져오기 const { webTypes } = useWebTypes({ active: "Y" }); console.log(`🔍 DetailSettingsPanel props:`, { selectedComponent: selectedComponent?.id, componentType: selectedComponent?.type, currentTableName, currentTable: currentTable?.tableName, selectedComponentTableName: selectedComponent?.tableName, }); // console.log(`🔍 DetailSettingsPanel webTypes 로드됨:`, webTypes?.length, "개"); // console.log(`🔍 webTypes:`, webTypes); // console.log(`🔍 DetailSettingsPanel selectedComponent:`, selectedComponent); // console.log(`🔍 DetailSettingsPanel selectedComponent.widgetType:`, selectedComponent?.widgetType); const inputableWebTypes = webTypes.map((wt) => wt.web_type); // 새로운 컴포넌트 시스템용 로컬 상태 const [localComponentDetailType, setLocalComponentDetailType] = useState(""); // 새로운 컴포넌트 시스템의 webType 동기화 useEffect(() => { if (selectedComponent?.type === "component") { const webType = selectedComponent.componentConfig?.webType; if (webType) { setLocalComponentDetailType(webType); } } }, [selectedComponent?.type, selectedComponent?.componentConfig?.webType, selectedComponent?.id]); // 레이아웃 컴포넌트 설정 렌더링 함수 const renderLayoutConfig = (layoutComponent: LayoutComponent) => { return (
{/* 헤더 */}

레이아웃 설정

타입: {layoutComponent.layoutType}
ID: {layoutComponent.id}
{/* 레이아웃 설정 영역 */}
{/* 기본 정보 */}
onUpdateProperty(layoutComponent.id, "label", e.target.value)} className="border-input bg-background focus-visible:ring-ring h-8 w-full rounded-md border px-3 text-xs focus-visible:ring-1 focus-visible:outline-none" placeholder="레이아웃 이름을 입력하세요" />
{/* 그리드 레이아웃 설정 */} {layoutComponent.layoutType === "grid" && (

그리드 설정

{ const newRows = parseInt(e.target.value); const newCols = layoutComponent.layoutConfig?.grid?.columns || 2; // 그리드 설정 업데이트 onUpdateProperty(layoutComponent.id, "layoutConfig.grid.rows", newRows); // 존 개수 자동 업데이트 (행 × 열) const totalZones = newRows * newCols; const currentZones = layoutComponent.zones || []; if (totalZones !== currentZones.length) { const newZones = []; for (let row = 0; row < newRows; row++) { for (let col = 0; col < newCols; col++) { const zoneIndex = row * newCols + col; newZones.push({ id: `zone${zoneIndex + 1}`, name: `존 ${zoneIndex + 1}`, position: { row, column: col }, size: { width: "100%", height: "100%" }, }); } } onUpdateProperty(layoutComponent.id, "zones", newZones); } }} className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
{ const newCols = parseInt(e.target.value); const newRows = layoutComponent.layoutConfig?.grid?.rows || 2; // 그리드 설정 업데이트 onUpdateProperty(layoutComponent.id, "layoutConfig.grid.columns", newCols); // 존 개수 자동 업데이트 (행 × 열) const totalZones = newRows * newCols; const currentZones = layoutComponent.zones || []; if (totalZones !== currentZones.length) { const newZones = []; for (let row = 0; row < newRows; row++) { for (let col = 0; col < newCols; col++) { const zoneIndex = row * newCols + col; newZones.push({ id: `zone${zoneIndex + 1}`, name: `존 ${zoneIndex + 1}`, position: { row, column: col }, size: { width: "100%", height: "100%" }, }); } } onUpdateProperty(layoutComponent.id, "zones", newZones); } }} className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
onUpdateProperty(layoutComponent.id, "layoutConfig.grid.gap", parseInt(e.target.value)) } className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
)} {/* 플렉스박스 레이아웃 설정 */} {layoutComponent.layoutType === "flexbox" && (

플렉스박스 설정

{ const newZoneCount = parseInt(e.target.value); const currentZones = layoutComponent.zones || []; const direction = layoutComponent.layoutConfig?.flexbox?.direction || "row"; if (newZoneCount > currentZones.length) { // 존 추가 const newZones = [...currentZones]; for (let i = currentZones.length; i < newZoneCount; i++) { newZones.push({ id: `zone${i + 1}`, name: `존 ${i + 1}`, position: {}, size: { width: direction === "row" ? `${100 / newZoneCount}%` : "100%", height: direction === "column" ? `${100 / newZoneCount}%` : "100%", }, }); } // 기존 존들의 크기도 조정 newZones.forEach((zone, index) => { if (direction === "row") { zone.size.width = `${100 / newZoneCount}%`; } else { zone.size.height = `${100 / newZoneCount}%`; } }); onUpdateProperty(layoutComponent.id, "zones", newZones); } else if (newZoneCount < currentZones.length) { // 존 제거 const newZones = currentZones.slice(0, newZoneCount); // 남은 존들의 크기 재조정 newZones.forEach((zone, index) => { if (direction === "row") { zone.size.width = `${100 / newZoneCount}%`; } else { zone.size.height = `${100 / newZoneCount}%`; } }); onUpdateProperty(layoutComponent.id, "zones", newZones); } }} className="w-20 rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
onUpdateProperty(layoutComponent.id, "layoutConfig.flexbox.gap", parseInt(e.target.value)) } className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
)} {/* 분할 레이아웃 설정 */} {layoutComponent.layoutType === "split" && (

분할 설정

)} {/* 카드 레이아웃 설정 */} {layoutComponent.layoutType === "card-layout" && (

카드 설정

{/* 테이블 컬럼 매핑 */}
테이블 컬럼 매핑
{currentTable && ( 테이블: {currentTable.table_name} )}
{/* 테이블이 선택되지 않은 경우 안내 */} {!currentTable && (

테이블을 먼저 선택해주세요

화면 설정에서 테이블을 선택하면 컬럼 목록이 표시됩니다

)} {/* 테이블이 선택된 경우 컬럼 드롭다운 */} {currentTable && ( <>
{/* 동적 표시 컬럼 추가 */}
{(layoutComponent.layoutConfig?.card?.columnMapping?.displayColumns || []).map( (column, index) => (
), )} {(!layoutComponent.layoutConfig?.card?.columnMapping?.displayColumns || layoutComponent.layoutConfig.card.columnMapping.displayColumns.length === 0) && (
"컬럼 추가" 버튼을 클릭하여 표시할 컬럼을 추가하세요
)}
)}
{/* 카드 스타일 설정 */}
카드 스타일
onUpdateProperty(layoutComponent.id, "layoutConfig.card.cardsPerRow", parseInt(e.target.value)) } className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
onUpdateProperty(layoutComponent.id, "layoutConfig.card.cardSpacing", parseInt(e.target.value)) } className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
onUpdateProperty(layoutComponent.id, "layoutConfig.card.cardStyle.showTitle", e.target.checked) } className="rounded border-gray-300" />
onUpdateProperty( layoutComponent.id, "layoutConfig.card.cardStyle.showSubtitle", e.target.checked, ) } className="rounded border-gray-300" />
onUpdateProperty( layoutComponent.id, "layoutConfig.card.cardStyle.showDescription", e.target.checked, ) } className="rounded border-gray-300" />
onUpdateProperty(layoutComponent.id, "layoutConfig.card.cardStyle.showImage", e.target.checked) } className="rounded border-gray-300" />
onUpdateProperty( layoutComponent.id, "layoutConfig.card.cardStyle.maxDescriptionLength", parseInt(e.target.value), ) } className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} />
)} {/* 존 목록 - 카드 레이아웃은 데이터 기반이므로 존 관리 불필요 */} {layoutComponent.layoutType !== "card-layout" && (

존 목록

{layoutComponent.zones?.map((zone, index) => (
{zone.name} ID: {zone.id}
onUpdateProperty(layoutComponent.id, `zones.${index}.size.width`, e.target.value) } className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} placeholder="100%" />
onUpdateProperty(layoutComponent.id, `zones.${index}.size.height`, e.target.value) } className="w-full rounded border border-gray-300 px-2 py-1 text-xs" style={{ fontSize: "12px" }} placeholder="auto" />
))}
)}
); }; // 웹타입별 상세 설정 렌더링 함수 - useCallback 제거하여 항상 최신 widget 사용 const renderWebTypeConfig = (widget: WidgetComponent) => { const currentConfig = widget.webTypeConfig || {}; // console.log("🎨 DetailSettingsPanel renderWebTypeConfig 호출:", { // componentId: widget.id, // widgetType: widget.widgetType, // currentConfig, // configExists: !!currentConfig, // configKeys: Object.keys(currentConfig), // configStringified: JSON.stringify(currentConfig), // widgetWebTypeConfig: widget.webTypeConfig, // widgetWebTypeConfigExists: !!widget.webTypeConfig, // timestamp: new Date().toISOString(), // }); // console.log("🎨 selectedComponent 전체:", selectedComponent); const handleConfigChange = (newConfig: WebTypeConfig) => { // 강제 새 객체 생성으로 React 변경 감지 보장 const freshConfig = { ...newConfig }; onUpdateProperty(widget.id, "webTypeConfig", freshConfig); // TextTypeConfig의 자동입력 설정을 autoGeneration으로도 매핑 const textConfig = newConfig as any; if (textConfig.autoInput && textConfig.autoValueType === "numbering_rule" && textConfig.numberingRuleId) { onUpdateProperty(widget.id, "autoGeneration", { type: "numbering_rule", enabled: true, options: { numberingRuleId: textConfig.numberingRuleId, }, }); } else if (textConfig.autoInput === false) { // 자동입력이 비활성화되면 autoGeneration도 비활성화 onUpdateProperty(widget.id, "autoGeneration", { type: "none", enabled: false, }); } }; // 1순위: DB에서 지정된 설정 패널 사용 const dbWebType = webTypes.find((wt) => wt.web_type === widget.widgetType); // console.log(`🎨 웹타입 "${widget.widgetType}" DB 조회 결과:`, dbWebType); if (dbWebType?.config_panel) { // console.log(`🎨 웹타입 "${widget.widgetType}" → DB 지정 설정 패널 "${dbWebType.config_panel}" 사용`); const ConfigPanelComponent = getConfigPanelComponent(dbWebType.config_panel); // console.log(`🎨 getConfigPanelComponent 결과:`, ConfigPanelComponent); if (ConfigPanelComponent) { // console.log(`🎨 ✅ ConfigPanelComponent 렌더링 시작`); return ( ); } else { // console.log(`🎨 ❌ ConfigPanelComponent가 null - WebTypeConfigPanel 사용`); return ( ); } } else { // console.log(`🎨 config_panel이 없음 - WebTypeConfigPanel 사용`); return ( ); } }; if (!selectedComponent) { return (
{/* 헤더 */}

상세 설정

컴포넌트를 선택하여 상세 설정을 편집하세요

{/* 빈 상태 */}

컴포넌트를 선택하세요

위젯 컴포넌트를 선택하면 상세 설정을 편집할 수 있습니다.

); } // 컴포넌트 타입별 설정 패널 렌더링 const renderComponentConfigPanel = () => { // console.log("🔍 renderComponentConfigPanel - selectedComponent:", selectedComponent); if (!selectedComponent) { // console.error("❌ selectedComponent가 undefined입니다!"); return (

오류

선택된 컴포넌트가 없습니다.

); } const componentType = selectedComponent.componentConfig?.type || selectedComponent.type; const handleUpdateProperty = (path: string, value: any) => { onUpdateProperty(selectedComponent.id, path, value); }; const handleConfigChange = (newConfig: any) => { onUpdateProperty(selectedComponent.id, "componentConfig.config", newConfig); }; // 🆕 ComponentRegistry에서 ConfigPanel 가져오기 const componentId = selectedComponent.componentConfig?.type || selectedComponent.componentConfig?.id; if (componentId) { const definition = ComponentRegistry.getComponent(componentId); if (definition?.configPanel) { const ConfigPanelComponent = definition.configPanel; const currentConfig = selectedComponent.componentConfig || {}; console.log("✅ ConfigPanel 표시:", { componentId, definitionName: definition.name, hasConfigPanel: !!definition.configPanel, currentConfig, }); // 래퍼 컴포넌트: 새 ConfigPanel 인터페이스를 기존 패턴에 맞춤 const ConfigPanelWrapper = () => { // Section Card, Section Paper 등 신규 컴포넌트는 componentConfig 바로 아래에 설정 저장 const config = currentConfig || definition.defaultProps?.componentConfig || {}; const handleConfigChange = (newConfig: any) => { // componentConfig 전체를 업데이트 onUpdateProperty(selectedComponent.id, "componentConfig", newConfig); }; return (

{definition.name} 설정

); }; return ; } else { console.warn("⚠️ ConfigPanel 없음:", { componentId, definitionName: definition?.name, hasDefinition: !!definition, }); } } // 기존 하드코딩된 설정 패널들 (레거시) switch (componentType) { case "button": case "button-primary": case "button-secondary": // 🔧 component.id만 key로 사용 (unmount 방지) return ( ); case "card": return ; case "dashboard": return ; case "stats": case "stats-card": return ; case "progress": case "progress-bar": return ; case "chart": case "chart-basic": return ; case "alert": case "alert-info": return ; case "badge": case "badge-status": return ; default: return (

⚠️ 설정 패널 없음

컴포넌트 "{componentId || componentType}"에 대한 설정 패널이 없습니다.

); } }; // 새로운 컴포넌트 타입들에 대한 설정 패널 확인 const componentType = selectedComponent?.componentConfig?.type || selectedComponent?.type; // console.log("🔍 DetailSettingsPanel componentType 확인:", { // selectedComponentType: selectedComponent?.type, // componentConfigType: selectedComponent?.componentConfig?.type, // finalComponentType: componentType, // }); const hasNewConfigPanel = componentType && [ "button", "button-primary", "button-secondary", "card", "dashboard", "stats", "stats-card", "progress", "progress-bar", "chart", "chart-basic", "alert", "alert-info", "badge", "badge-status", ].includes(componentType); // console.log("🔍 hasNewConfigPanel:", hasNewConfigPanel); if (hasNewConfigPanel) { return (
{/* 헤더 */}

컴포넌트 설정

타입: {componentType}
{/* 설정 패널 영역 */}
{renderComponentConfigPanel()}
); } // 레이아웃 컴포넌트 처리 if (selectedComponent.type === "layout") { return renderLayoutConfig(selectedComponent as LayoutComponent); } if ( selectedComponent.type !== "widget" && selectedComponent.type !== "file" && selectedComponent.type !== "button" && selectedComponent.type !== "component" ) { return (

설정할 수 없는 컴포넌트입니다

상세 설정은 위젯, 파일, 버튼, 컴포넌트, 레이아웃에서만 사용할 수 있습니다.
현재 선택된 컴포넌트: {selectedComponent.type}

); } // 파일 컴포넌트인 경우 FileComponentConfigPanel 렌더링 if (isFileComponent(selectedComponent)) { const fileComponent = selectedComponent as FileComponent; return (
{/* 헤더 */}

파일 컴포넌트 설정

타입: 파일 업로드
{selectedComponent.type === "widget" ? `위젯타입: ${selectedComponent.widgetType}` : `문서 타입: ${fileComponent.fileConfig?.docTypeName || "일반 문서"}`}
{/* 파일 컴포넌트 설정 영역 */}
); } // 레거시 버튼을 새로운 컴포넌트 시스템으로 강제 변환 if (selectedComponent.type === "button") { // console.log("🔄 레거시 버튼을 새로운 컴포넌트 시스템으로 변환:", selectedComponent); // 레거시 버튼을 새로운 시스템으로 변환 const convertedComponent = { ...selectedComponent, type: "component" as const, componentConfig: { type: "button-primary", webType: "button", ...selectedComponent.componentConfig, }, }; // 변환된 컴포넌트로 DB 업데이트 onUpdateProperty(selectedComponent.id, "type", "component"); onUpdateProperty(selectedComponent.id, "componentConfig", convertedComponent.componentConfig); // 변환된 컴포넌트로 처리 계속 selectedComponent = convertedComponent; } // 새로운 컴포넌트 시스템 처리 (type: "component") if (selectedComponent.type === "component") { const componentId = (selectedComponent as any).componentType || selectedComponent.componentConfig?.type; const webType = selectedComponent.componentConfig?.webType; // console.log("🔧 새로운 컴포넌트 시스템 설정 패널:", { componentId, webType }); if (!componentId) { return (

컴포넌트 ID가 없습니다

componentConfig.type이 설정되지 않았습니다.

); } // 현재 웹타입의 기본 입력 타입 추출 const currentBaseInputType = webType ? getBaseInputType(webType as any) : null; // 선택 가능한 세부 타입 목록 const availableDetailTypes = currentBaseInputType ? getDetailTypes(currentBaseInputType) : []; // 세부 타입 변경 핸들러 const handleDetailTypeChange = (newDetailType: string) => { setLocalComponentDetailType(newDetailType); onUpdateProperty(selectedComponent.id, "componentConfig.webType", newDetailType); }; return (
{/* 헤더 */}

상세 설정

선택한 컴포넌트의 속성을 편집하세요

{/* 컴포넌트 정보 */}
컴포넌트: {componentId}
{webType && currentBaseInputType && (
입력 타입: {currentBaseInputType}
)} {selectedComponent.columnName && (
컬럼: {selectedComponent.columnName}
)}
{/* 컴포넌트 설정 패널 */}
{/* DynamicComponentConfigPanel */} { const config = selectedComponent.componentConfig || {}; // console.log("🔍 DetailSettingsPanel에서 전달하는 config:", config); // console.log("🔍 selectedComponent 전체:", selectedComponent); return config; })()} screenTableName={selectedComponent.tableName || currentTable?.tableName || currentTableName} tableColumns={(() => { // console.log("🔍 DetailSettingsPanel tableColumns 전달:", { // currentTable, // columns: currentTable?.columns, // columnsLength: currentTable?.columns?.length, // sampleColumn: currentTable?.columns?.[0], // deptCodeColumn: currentTable?.columns?.find((col) => col.columnName === "dept_code"), // }); return currentTable?.columns || []; })()} tables={tables} // 전체 테이블 목록 전달 onChange={(newConfig) => { // console.log("🔧 컴포넌트 설정 변경:", newConfig); // 개별 속성별로 업데이트하여 다른 속성과의 충돌 방지 Object.entries(newConfig).forEach(([key, value]) => { onUpdateProperty(selectedComponent.id, `componentConfig.${key}`, value); }); }} /> {/* 🆕 테이블 데이터 자동 입력 섹션 (component 타입용) */}

테이블 데이터 자동 입력

{ onUpdateProperty(selectedComponent.id, "autoFill", { enabled: checked as boolean, sourceTable: selectedComponent.autoFill?.sourceTable || "", filterColumn: selectedComponent.autoFill?.filterColumn || "company_code", userField: selectedComponent.autoFill?.userField || "companyCode", displayColumn: selectedComponent.autoFill?.displayColumn || "", }); }} />
{selectedComponent.autoFill?.enabled && (

데이터를 조회할 테이블

{ onUpdateProperty(selectedComponent.id, "autoFill", { ...selectedComponent.autoFill!, filterColumn: e.target.value, }); }} placeholder="company_code" className="text-xs" />

예: company_code, dept_code, user_id

로그인한 사용자의 정보를 필터로 사용

{ onUpdateProperty(selectedComponent.id, "autoFill", { ...selectedComponent.autoFill!, displayColumn: e.target.value, }); }} placeholder="company_name" className="text-xs" />

조회된 레코드에서 표시할 컬럼 (예: company_name)

)}
); } // 기존 위젯 시스템 처리 (type: "widget") const widget = selectedComponent as WidgetComponent; // 현재 웹타입의 기본 입력 타입 추출 const currentBaseInputType = getBaseInputType(widget.widgetType); // 선택 가능한 세부 타입 목록 const availableDetailTypes = getDetailTypes(currentBaseInputType); // 로컬 상태: 세부 타입 선택 const [localDetailType, setLocalDetailType] = useState(widget.widgetType); // 컴포넌트 변경 시 로컬 상태 동기화 useEffect(() => { setLocalDetailType(widget.widgetType); }, [widget.widgetType, widget.id]); // 세부 타입 변경 핸들러 const handleDetailTypeChange = (newDetailType: string) => { setLocalDetailType(newDetailType); onUpdateProperty(widget.id, "widgetType", newDetailType); // 웹타입 변경 시 기존 설정 초기화 (선택적) // onUpdateProperty(widget.id, "webTypeConfig", {}); }; return (
{/* 헤더 */}

상세 설정

입력 타입: {currentBaseInputType}
컬럼: {widget.columnName}
{/* 세부 타입 선택 영역 */}

입력 타입 "{currentBaseInputType}"에 사용할 구체적인 형태를 선택하세요

{/* 상세 설정 영역 */}
{console.log("🔍 [DetailSettingsPanel] widget 타입:", selectedComponent?.type, "autoFill:", widget.autoFill)} {/* 🆕 자동 입력 섹션 */}

🔥 테이블 데이터 자동 입력 (테스트)

{ onUpdateProperty(widget.id, "autoFill", { enabled: checked as boolean, sourceTable: widget.autoFill?.sourceTable || '', filterColumn: widget.autoFill?.filterColumn || 'company_code', userField: widget.autoFill?.userField || 'companyCode', displayColumn: widget.autoFill?.displayColumn || '', }); }} />
{widget.autoFill?.enabled && (

데이터를 조회할 테이블

{ onUpdateProperty(widget.id, "autoFill", { ...widget.autoFill!, filterColumn: e.target.value, }); }} placeholder="company_code" className="text-xs" />

예: company_code, dept_code, user_id

로그인한 사용자 정보에서 가져올 필드

{ onUpdateProperty(widget.id, "autoFill", { ...widget.autoFill!, displayColumn: e.target.value, }); }} placeholder="company_name" className="text-xs" />

Input에 표시할 컬럼명 (예: company_name, dept_name)

)}
{/* 웹타입 설정 */} {renderWebTypeConfig(widget)}
); }; export default DetailSettingsPanel;