feat: Enhance SplitPanelLayout with modal support for add and edit buttons

- Implemented modal configuration for add and edit buttons in the SplitPanelLayoutComponent, allowing for custom modal screens based on user interactions.
- Added settings for button visibility and modes (auto or modal) in the SplitPanelLayoutConfigPanel, improving flexibility in UI configuration.
- Enhanced data handling by storing selected left panel items in modalDataStore for use in modal screens, ensuring seamless data flow.
- Updated types to include new properties for add and edit button configurations, facilitating better type safety and clarity in component usage.
This commit is contained in:
kjs
2026-02-12 14:54:14 +09:00
parent 5d391f0cee
commit fb02e5b389
4 changed files with 496 additions and 35 deletions

View File

@@ -1993,6 +1993,88 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
// 추가 버튼 핸들러
const handleAddClick = useCallback(
(panel: "left" | "right") => {
// 좌측 패널 추가 시, addButton 모달 모드 확인
if (panel === "left") {
const addButtonConfig = componentConfig.leftPanel?.addButton;
if (addButtonConfig?.mode === "modal" && addButtonConfig?.modalScreenId) {
const leftTableName = componentConfig.leftPanel?.tableName || "";
// ScreenModal 열기 이벤트 발생
window.dispatchEvent(
new CustomEvent("openScreenModal", {
detail: {
screenId: addButtonConfig.modalScreenId,
urlParams: {
mode: "add",
tableName: leftTableName,
},
},
}),
);
console.log("✅ [SplitPanel] 좌측 추가 모달 화면 열기:", {
screenId: addButtonConfig.modalScreenId,
tableName: leftTableName,
});
return;
}
}
// 우측 패널 추가 시, addButton 모달 모드 확인
if (panel === "right") {
const addButtonConfig =
activeTabIndex === 0
? componentConfig.rightPanel?.addButton
: (componentConfig.rightPanel?.additionalTabs?.[activeTabIndex - 1] as any)?.addButton;
if (addButtonConfig?.mode === "modal" && addButtonConfig?.modalScreenId) {
// 커스텀 모달 화면 열기
const currentTableName =
activeTabIndex === 0
? componentConfig.rightPanel?.tableName || ""
: (componentConfig.rightPanel?.additionalTabs?.[activeTabIndex - 1] as any)?.tableName || "";
// 좌측 선택 데이터를 modalDataStore에 저장 (추가 화면에서 참조 가능)
if (selectedLeftItem && componentConfig.leftPanel?.tableName) {
import("@/stores/modalDataStore").then(({ useModalDataStore }) => {
useModalDataStore.getState().setData(componentConfig.leftPanel!.tableName!, [selectedLeftItem]);
});
}
// ScreenModal 열기 이벤트 발생
window.dispatchEvent(
new CustomEvent("openScreenModal", {
detail: {
screenId: addButtonConfig.modalScreenId,
urlParams: {
mode: "add",
tableName: currentTableName,
// 좌측 선택 항목의 연결 키 값 전달
...(selectedLeftItem && (() => {
const relation = activeTabIndex === 0
? componentConfig.rightPanel?.relation
: (componentConfig.rightPanel?.additionalTabs?.[activeTabIndex - 1] as any)?.relation;
const leftColumn = relation?.keys?.[0]?.leftColumn || relation?.leftColumn;
const rightColumn = relation?.keys?.[0]?.rightColumn || relation?.foreignKey;
if (leftColumn && rightColumn && selectedLeftItem[leftColumn] !== undefined) {
return { [rightColumn]: selectedLeftItem[leftColumn] };
}
return {};
})()),
},
},
}),
);
console.log("✅ [SplitPanel] 추가 모달 화면 열기:", {
screenId: addButtonConfig.modalScreenId,
tableName: currentTableName,
});
return;
}
}
// 기존 내장 추가 모달 로직
setAddModalPanel(panel);
// 우측 패널 추가 시, 좌측에서 선택된 항목의 조인 컬럼 값을 자동으로 채움
@@ -2012,12 +2094,66 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
setShowAddModal(true);
},
[selectedLeftItem, componentConfig],
[selectedLeftItem, componentConfig, activeTabIndex],
);
// 수정 버튼 핸들러
const handleEditClick = useCallback(
(panel: "left" | "right", item: any) => {
// 좌측 패널 수정 버튼 설정 확인 (모달 모드)
if (panel === "left") {
const editButtonConfig = componentConfig.leftPanel?.editButton;
if (editButtonConfig?.mode === "modal" && editButtonConfig?.modalScreenId) {
const leftTableName = componentConfig.leftPanel?.tableName || "";
const sourceColumn = componentConfig.leftPanel?.itemAddConfig?.sourceColumn || "id";
// Primary Key 찾기
let primaryKeyName = sourceColumn;
let primaryKeyValue = item[sourceColumn];
if (primaryKeyValue === undefined || primaryKeyValue === null) {
if (item.id !== undefined && item.id !== null) {
primaryKeyName = "id";
primaryKeyValue = item.id;
} else if (item.ID !== undefined && item.ID !== null) {
primaryKeyName = "ID";
primaryKeyValue = item.ID;
} else {
const firstKey = Object.keys(item)[0];
primaryKeyName = firstKey;
primaryKeyValue = item[firstKey];
}
}
// modalDataStore에 저장
import("@/stores/modalDataStore").then(({ useModalDataStore }) => {
useModalDataStore.getState().setData(leftTableName, [item]);
});
// ScreenModal 열기 이벤트 발생
window.dispatchEvent(
new CustomEvent("openScreenModal", {
detail: {
screenId: editButtonConfig.modalScreenId,
urlParams: {
mode: "edit",
editId: primaryKeyValue,
tableName: leftTableName,
},
},
}),
);
console.log("✅ [SplitPanel] 좌측 수정 모달 화면 열기:", {
screenId: editButtonConfig.modalScreenId,
tableName: leftTableName,
primaryKeyName,
primaryKeyValue,
});
return;
}
}
// 우측 패널 수정 버튼 설정 확인 (탭별 설정 지원)
if (panel === "right") {
const editButtonConfig =
@@ -3339,29 +3475,33 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
{/* 항목별 버튼들 */}
{!isDesignMode && (
<div className="flex flex-shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100">
{/* 수정 버튼 */}
<button
onClick={(e) => {
e.stopPropagation();
handleEditClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-gray-200"
title="수정"
>
<Pencil className="h-4 w-4 text-gray-600" />
</button>
{/* 수정 버튼 (showEdit 활성화 시에만 표시) */}
{(componentConfig.leftPanel?.showEdit !== false) && (
<button
onClick={(e) => {
e.stopPropagation();
handleEditClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-gray-200"
title="수정"
>
<Pencil className="h-4 w-4 text-gray-600" />
</button>
)}
{/* 삭제 버튼 */}
<button
onClick={(e) => {
e.stopPropagation();
handleDeleteClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-red-100"
title="삭제"
>
<Trash2 className="h-4 w-4 text-red-600" />
</button>
{/* 삭제 버튼 (showDelete 활성화 시에만 표시) */}
{(componentConfig.leftPanel?.showDelete !== false) && (
<button
onClick={(e) => {
e.stopPropagation();
handleDeleteClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-red-100"
title="삭제"
>
<Trash2 className="h-4 w-4 text-red-600" />
</button>
)}
{/* 항목별 추가 버튼 */}
{componentConfig.leftPanel?.showItemAddButton && (