웹 타입 설정패널 분리
This commit is contained in:
@@ -3063,6 +3063,7 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
||||
autoHeight={true}
|
||||
>
|
||||
<DetailSettingsPanel
|
||||
key={`detail-settings-${selectedComponent?.id}-${selectedComponent?.type === "widget" ? (selectedComponent as any).widgetType : "non-widget"}`}
|
||||
selectedComponent={selectedComponent || undefined}
|
||||
onUpdateProperty={(componentId: string, path: string, value: any) => {
|
||||
updateComponentProperty(componentId, path, value);
|
||||
|
||||
@@ -4,35 +4,8 @@ import React from "react";
|
||||
import { Settings } from "lucide-react";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { useWebTypes } from "@/hooks/admin/useWebTypes";
|
||||
import {
|
||||
ComponentData,
|
||||
WidgetComponent,
|
||||
FileComponent,
|
||||
WebTypeConfig,
|
||||
DateTypeConfig,
|
||||
NumberTypeConfig,
|
||||
SelectTypeConfig,
|
||||
TextTypeConfig,
|
||||
TextareaTypeConfig,
|
||||
CheckboxTypeConfig,
|
||||
RadioTypeConfig,
|
||||
FileTypeConfig,
|
||||
CodeTypeConfig,
|
||||
EntityTypeConfig,
|
||||
ButtonTypeConfig,
|
||||
TableInfo,
|
||||
} from "@/types/screen";
|
||||
import { DateTypeConfigPanel } from "./webtype-configs/DateTypeConfigPanel";
|
||||
import { NumberTypeConfigPanel } from "./webtype-configs/NumberTypeConfigPanel";
|
||||
import { SelectTypeConfigPanel } from "./webtype-configs/SelectTypeConfigPanel";
|
||||
import { TextTypeConfigPanel } from "./webtype-configs/TextTypeConfigPanel";
|
||||
import { TextareaTypeConfigPanel } from "./webtype-configs/TextareaTypeConfigPanel";
|
||||
import { CheckboxTypeConfigPanel } from "./webtype-configs/CheckboxTypeConfigPanel";
|
||||
import { RadioTypeConfigPanel } from "./webtype-configs/RadioTypeConfigPanel";
|
||||
import { FileTypeConfigPanel } from "./webtype-configs/FileTypeConfigPanel";
|
||||
import { CodeTypeConfigPanel } from "./webtype-configs/CodeTypeConfigPanel";
|
||||
import { RatingTypeConfigPanel, RatingTypeConfig } from "./webtype-configs/RatingTypeConfigPanel";
|
||||
import { EntityTypeConfigPanel } from "./webtype-configs/EntityTypeConfigPanel";
|
||||
import { getConfigPanelComponent } from "@/lib/utils/getConfigPanelComponent";
|
||||
import { ComponentData, WidgetComponent, FileComponent, WebTypeConfig, TableInfo } from "@/types/screen";
|
||||
import { ButtonConfigPanel } from "./ButtonConfigPanel";
|
||||
import { FileComponentConfigPanel } from "./FileComponentConfigPanel";
|
||||
|
||||
@@ -51,166 +24,77 @@ export const DetailSettingsPanel: React.FC<DetailSettingsPanelProps> = ({
|
||||
}) => {
|
||||
// 데이터베이스에서 입력 가능한 웹타입들을 동적으로 가져오기
|
||||
const { webTypes } = useWebTypes({ active: "Y" });
|
||||
|
||||
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 renderWebTypeConfig = React.useCallback(
|
||||
(widget: WidgetComponent) => {
|
||||
const currentConfig = widget.webTypeConfig || {};
|
||||
// 웹타입별 상세 설정 렌더링 함수 - useCallback 제거하여 항상 최신 widget 사용
|
||||
const renderWebTypeConfig = (widget: WidgetComponent) => {
|
||||
const currentConfig = widget.webTypeConfig || {};
|
||||
|
||||
console.log("🎨 DetailSettingsPanel renderWebTypeConfig 호출:", {
|
||||
componentId: widget.id,
|
||||
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) => {
|
||||
console.log("🔧 WebTypeConfig 업데이트:", {
|
||||
widgetType: widget.widgetType,
|
||||
currentConfig,
|
||||
configExists: !!currentConfig,
|
||||
configKeys: Object.keys(currentConfig),
|
||||
configStringified: JSON.stringify(currentConfig),
|
||||
widgetWebTypeConfig: widget.webTypeConfig,
|
||||
widgetWebTypeConfigExists: !!widget.webTypeConfig,
|
||||
timestamp: new Date().toISOString(),
|
||||
oldConfig: currentConfig,
|
||||
newConfig,
|
||||
componentId: widget.id,
|
||||
isEqual: JSON.stringify(currentConfig) === JSON.stringify(newConfig),
|
||||
});
|
||||
|
||||
const handleConfigChange = (newConfig: WebTypeConfig) => {
|
||||
console.log("🔧 WebTypeConfig 업데이트:", {
|
||||
widgetType: widget.widgetType,
|
||||
oldConfig: currentConfig,
|
||||
newConfig,
|
||||
componentId: widget.id,
|
||||
isEqual: JSON.stringify(currentConfig) === JSON.stringify(newConfig),
|
||||
});
|
||||
// 강제 새 객체 생성으로 React 변경 감지 보장
|
||||
const freshConfig = { ...newConfig };
|
||||
onUpdateProperty(widget.id, "webTypeConfig", freshConfig);
|
||||
};
|
||||
|
||||
// 강제 새 객체 생성으로 React 변경 감지 보장
|
||||
const freshConfig = { ...newConfig };
|
||||
onUpdateProperty(widget.id, "webTypeConfig", freshConfig);
|
||||
};
|
||||
// 1순위: DB에서 지정된 설정 패널 사용
|
||||
const dbWebType = webTypes.find((wt) => wt.web_type === widget.widgetType);
|
||||
console.log(`🎨 웹타입 "${widget.widgetType}" DB 조회 결과:`, dbWebType);
|
||||
|
||||
switch (widget.widgetType) {
|
||||
case "date":
|
||||
case "datetime":
|
||||
return (
|
||||
<DateTypeConfigPanel
|
||||
key={`date-config-${widget.id}`}
|
||||
config={currentConfig as DateTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
if (dbWebType?.config_panel) {
|
||||
console.log(`🎨 웹타입 "${widget.widgetType}" → DB 지정 설정 패널 "${dbWebType.config_panel}" 사용`);
|
||||
const ConfigPanelComponent = getConfigPanelComponent(dbWebType.config_panel);
|
||||
console.log(`🎨 getConfigPanelComponent 결과:`, ConfigPanelComponent);
|
||||
|
||||
case "number":
|
||||
case "decimal":
|
||||
return (
|
||||
<NumberTypeConfigPanel
|
||||
key={`${widget.id}-number`}
|
||||
config={currentConfig as NumberTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "select":
|
||||
case "dropdown":
|
||||
return (
|
||||
<SelectTypeConfigPanel
|
||||
key={`${widget.id}-select`}
|
||||
config={currentConfig as SelectTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "text":
|
||||
case "email":
|
||||
case "tel":
|
||||
return (
|
||||
<TextTypeConfigPanel
|
||||
key={`${widget.id}-text`}
|
||||
config={currentConfig as TextTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "textarea":
|
||||
return (
|
||||
<TextareaTypeConfigPanel
|
||||
key={`${widget.id}-textarea`}
|
||||
config={currentConfig as TextareaTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "checkbox":
|
||||
case "boolean":
|
||||
return (
|
||||
<CheckboxTypeConfigPanel
|
||||
key={`${widget.id}-checkbox`}
|
||||
config={currentConfig as CheckboxTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "radio":
|
||||
return (
|
||||
<RadioTypeConfigPanel
|
||||
key={`${widget.id}-radio`}
|
||||
config={currentConfig as RadioTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "file":
|
||||
return (
|
||||
<FileTypeConfigPanel
|
||||
key={`${widget.id}-file`}
|
||||
config={currentConfig as FileTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "code":
|
||||
return (
|
||||
<CodeTypeConfigPanel
|
||||
key={`${widget.id}-code`}
|
||||
config={currentConfig as CodeTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "rating":
|
||||
case "star":
|
||||
case "score":
|
||||
return (
|
||||
<RatingTypeConfigPanel
|
||||
key={`${widget.id}-rating`}
|
||||
config={currentConfig as RatingTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "entity":
|
||||
return (
|
||||
<EntityTypeConfigPanel
|
||||
key={`${widget.id}-entity`}
|
||||
config={currentConfig as EntityTypeConfig}
|
||||
onConfigChange={handleConfigChange}
|
||||
/>
|
||||
);
|
||||
|
||||
case "button":
|
||||
return (
|
||||
<ButtonConfigPanel
|
||||
key={`${widget.id}-button`}
|
||||
component={widget}
|
||||
onUpdateComponent={(updates) => {
|
||||
Object.entries(updates).forEach(([key, value]) => {
|
||||
onUpdateProperty(widget.id, key, value);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
return <div className="text-sm text-gray-500 italic">해당 웹타입의 상세 설정이 지원되지 않습니다.</div>;
|
||||
if (ConfigPanelComponent) {
|
||||
console.log(`🎨 ✅ ConfigPanelComponent 렌더링 시작`);
|
||||
return <ConfigPanelComponent config={currentConfig} onConfigChange={handleConfigChange} />;
|
||||
} else {
|
||||
console.log(`🎨 ❌ ConfigPanelComponent가 null - 기본 설정 표시`);
|
||||
return (
|
||||
<div className="py-8 text-center text-gray-500">
|
||||
⚙️ 기본 설정
|
||||
<br />
|
||||
웹타입 "{widget.widgetType}"은 추가 설정이 없습니다.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
[onUpdateProperty],
|
||||
);
|
||||
} else {
|
||||
console.log(`🎨 config_panel이 없음 - 기본 설정 표시`);
|
||||
return (
|
||||
<div className="py-8 text-center text-gray-500">
|
||||
⚙️ 기본 설정
|
||||
<br />
|
||||
웹타입 "{widget.widgetType}"은 추가 설정이 없습니다.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if (!selectedComponent) {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect, useRef, useMemo } from "react";
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
TableInfo,
|
||||
} from "@/types/screen";
|
||||
import DataTableConfigPanel from "./DataTableConfigPanel";
|
||||
import { DynamicConfigPanel } from "@/lib/registry";
|
||||
import { useWebTypes } from "@/hooks/admin/useWebTypes";
|
||||
|
||||
// DataTableConfigPanel을 위한 안정화된 래퍼 컴포넌트
|
||||
@@ -351,39 +350,6 @@ const PropertiesPanelComponent: React.FC<PropertiesPanelProps> = ({
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* 동적 웹타입 설정 패널 */}
|
||||
{selectedComponent.widgetType && (
|
||||
<div className="space-y-3">
|
||||
<Separator />
|
||||
<div>
|
||||
<Label className="text-sm font-medium">웹타입 세부 설정</Label>
|
||||
<div className="mt-2">
|
||||
<DynamicConfigPanel
|
||||
webType={selectedComponent.widgetType}
|
||||
component={selectedComponent}
|
||||
onUpdateComponent={(updatedComponent) => {
|
||||
// 컴포넌트 전체 업데이트
|
||||
Object.keys(updatedComponent).forEach((key) => {
|
||||
if (key !== "id") {
|
||||
onUpdateProperty(key, updatedComponent[key]);
|
||||
}
|
||||
});
|
||||
}}
|
||||
onUpdateProperty={(property, value) => {
|
||||
// 웹타입 설정 업데이트
|
||||
if (property === "webTypeConfig") {
|
||||
onUpdateProperty("webTypeConfig", value);
|
||||
} else {
|
||||
onUpdateProperty(property, value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Separator />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<Label htmlFor="placeholder" className="text-sm font-medium">
|
||||
플레이스홀더
|
||||
|
||||
Reference in New Issue
Block a user