ERP-node/frontend/components/screen/panels/DetailSettingsPanel.tsx

213 lines
8.6 KiB
TypeScript
Raw Normal View History

2025-09-03 11:32:09 +09:00
"use client";
import React from "react";
import { Settings } from "lucide-react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
2025-09-09 14:29:04 +09:00
import { useWebTypes } from "@/hooks/admin/useWebTypes";
2025-09-09 15:42:04 +09:00
import { getConfigPanelComponent } from "@/lib/utils/getConfigPanelComponent";
import { ComponentData, WidgetComponent, FileComponent, WebTypeConfig, TableInfo } from "@/types/screen";
import { ButtonConfigPanel } from "./ButtonConfigPanel";
2025-09-05 21:52:19 +09:00
import { FileComponentConfigPanel } from "./FileComponentConfigPanel";
2025-09-03 11:32:09 +09:00
interface DetailSettingsPanelProps {
selectedComponent?: ComponentData;
onUpdateProperty: (componentId: string, path: string, value: any) => void;
currentTable?: TableInfo; // 현재 화면의 테이블 정보
currentTableName?: string; // 현재 화면의 테이블명
2025-09-03 11:32:09 +09:00
}
export const DetailSettingsPanel: React.FC<DetailSettingsPanelProps> = ({
selectedComponent,
onUpdateProperty,
currentTable,
currentTableName,
}) => {
2025-09-09 14:29:04 +09:00
// 데이터베이스에서 입력 가능한 웹타입들을 동적으로 가져오기
const { webTypes } = useWebTypes({ active: "Y" });
2025-09-09 15:42:04 +09:00
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);
2025-09-03 11:32:09 +09:00
2025-09-09 15:42:04 +09:00
// 웹타입별 상세 설정 렌더링 함수 - 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) => {
console.log("🔧 WebTypeConfig 업데이트:", {
2025-09-03 11:32:09 +09:00
widgetType: widget.widgetType,
2025-09-09 15:42:04 +09:00
oldConfig: currentConfig,
newConfig,
componentId: widget.id,
isEqual: JSON.stringify(currentConfig) === JSON.stringify(newConfig),
2025-09-03 11:32:09 +09:00
});
2025-09-09 15:42:04 +09:00
// 강제 새 객체 생성으로 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);
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 <ConfigPanelComponent config={currentConfig} onConfigChange={handleConfigChange} />;
} else {
console.log(`🎨 ❌ ConfigPanelComponent가 null - 기본 설정 표시`);
return (
<div className="py-8 text-center text-gray-500">
<br />
"{widget.widgetType}" .
</div>
);
2025-09-03 11:32:09 +09:00
}
2025-09-09 15:42:04 +09:00
} else {
console.log(`🎨 config_panel이 없음 - 기본 설정 표시`);
return (
<div className="py-8 text-center text-gray-500">
<br />
"{widget.widgetType}" .
</div>
);
}
};
2025-09-03 11:32:09 +09:00
if (!selectedComponent) {
return (
<div className="flex h-full flex-col items-center justify-center p-6 text-center">
<Settings className="mb-4 h-12 w-12 text-gray-400" />
<h3 className="mb-2 text-lg font-medium text-gray-900"> </h3>
<p className="text-sm text-gray-500"> .</p>
</div>
);
}
2025-09-09 17:42:23 +09:00
if (selectedComponent.type !== "widget" && selectedComponent.type !== "file" && selectedComponent.type !== "button") {
2025-09-03 11:32:09 +09:00
return (
<div className="flex h-full flex-col items-center justify-center p-6 text-center">
<Settings className="mb-4 h-12 w-12 text-gray-400" />
2025-09-05 21:52:19 +09:00
<h3 className="mb-2 text-lg font-medium text-gray-900"> </h3>
2025-09-03 11:32:09 +09:00
<p className="text-sm text-gray-500">
2025-09-09 17:42:23 +09:00
, , .
2025-09-03 11:32:09 +09:00
<br />
: {selectedComponent.type}
</p>
</div>
);
}
2025-09-05 21:52:19 +09:00
// 파일 컴포넌트인 경우 FileComponentConfigPanel 렌더링
if (selectedComponent.type === "file") {
const fileComponent = selectedComponent as FileComponent;
return (
<div className="flex h-full flex-col">
{/* 헤더 */}
<div className="border-b border-gray-200 p-4">
<div className="flex items-center space-x-2">
<Settings className="h-4 w-4 text-gray-600" />
<h3 className="font-medium text-gray-900"> </h3>
</div>
<div className="mt-2 flex items-center space-x-2">
<span className="text-sm text-gray-600">:</span>
<span className="rounded bg-purple-100 px-2 py-1 text-xs font-medium text-purple-800"> </span>
</div>
<div className="mt-1 text-xs text-gray-500"> : {fileComponent.fileConfig.docTypeName}</div>
</div>
{/* 파일 컴포넌트 설정 영역 */}
<div className="flex-1 overflow-y-auto p-4">
<FileComponentConfigPanel
component={fileComponent}
onUpdateProperty={onUpdateProperty}
currentTable={currentTable}
currentTableName={currentTableName}
/>
2025-09-05 21:52:19 +09:00
</div>
</div>
);
}
2025-09-09 17:42:23 +09:00
// 버튼 컴포넌트인 경우 ButtonConfigPanel 렌더링
if (selectedComponent.type === "button") {
const buttonWidget = selectedComponent as WidgetComponent;
return (
<div className="flex h-full flex-col">
{/* 헤더 */}
<div className="border-b border-gray-200 p-4">
<div className="flex items-center space-x-2">
<Settings className="h-4 w-4 text-gray-600" />
<h3 className="font-medium text-gray-900"> </h3>
</div>
<div className="mt-2 flex items-center space-x-2">
<span className="text-sm text-gray-600">:</span>
<span className="rounded bg-green-100 px-2 py-1 text-xs font-medium text-green-800"></span>
</div>
<div className="mt-1 text-xs text-gray-500">: {buttonWidget.label || "버튼"}</div>
</div>
{/* 버튼 설정 영역 */}
<div className="flex-1 overflow-y-auto p-4">
<ButtonConfigPanel
component={buttonWidget}
onUpdateComponent={(updates) => {
Object.entries(updates).forEach(([key, value]) => {
onUpdateProperty(buttonWidget.id, key, value);
});
}}
/>
</div>
</div>
);
}
2025-09-03 11:32:09 +09:00
const widget = selectedComponent as WidgetComponent;
return (
<div className="flex h-full flex-col">
{/* 헤더 */}
<div className="border-b border-gray-200 p-4">
<div className="flex items-center space-x-2">
<Settings className="h-4 w-4 text-gray-600" />
<h3 className="font-medium text-gray-900"> </h3>
</div>
<div className="mt-2 flex items-center space-x-2">
<span className="text-sm text-gray-600">:</span>
<span className="rounded bg-blue-100 px-2 py-1 text-xs font-medium text-blue-800">{widget.widgetType}</span>
</div>
<div className="mt-1 text-xs text-gray-500">: {widget.columnName}</div>
</div>
{/* 상세 설정 영역 */}
<div className="flex-1 overflow-y-auto p-4">{renderWebTypeConfig(widget)}</div>
</div>
);
};
export default DetailSettingsPanel;