버튼별로 데이터 필터링기능
This commit is contained in:
@@ -1,13 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Plus, Star, Loader2 } from "lucide-react";
|
||||
import { Plus, Star, Loader2, ExternalLink } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useSplitPanelContext } from "@/contexts/SplitPanelContext";
|
||||
import { dataApi } from "@/lib/api/data";
|
||||
import type { RelatedDataButtonsConfig, ButtonItem } from "./types";
|
||||
|
||||
// 전역 상태: 현재 선택된 버튼 데이터를 외부에서 접근 가능하게
|
||||
declare global {
|
||||
interface Window {
|
||||
__relatedButtonsSelectedData?: {
|
||||
selectedItem: ButtonItem | null;
|
||||
masterData: Record<string, any> | null;
|
||||
config: RelatedDataButtonsConfig | null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface RelatedDataButtonsComponentProps {
|
||||
config: RelatedDataButtonsConfig;
|
||||
className?: string;
|
||||
@@ -21,12 +32,27 @@ export const RelatedDataButtonsComponent: React.FC<RelatedDataButtonsComponentPr
|
||||
}) => {
|
||||
const [buttons, setButtons] = useState<ButtonItem[]>([]);
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const [selectedItem, setSelectedItem] = useState<ButtonItem | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [masterData, setMasterData] = useState<Record<string, any> | null>(null);
|
||||
|
||||
// SplitPanel Context 연결
|
||||
const splitPanelContext = useSplitPanelContext();
|
||||
|
||||
// 선택된 데이터를 전역 상태에 저장 (외부 버튼에서 접근용)
|
||||
useEffect(() => {
|
||||
window.__relatedButtonsSelectedData = {
|
||||
selectedItem,
|
||||
masterData,
|
||||
config,
|
||||
};
|
||||
console.log("🔄 [RelatedDataButtons] 전역 상태 업데이트:", {
|
||||
selectedItem,
|
||||
hasConfig: !!config,
|
||||
modalLink: config?.modalLink,
|
||||
});
|
||||
}, [selectedItem, masterData, config]);
|
||||
|
||||
// 좌측 패널에서 선택된 데이터 감지
|
||||
useEffect(() => {
|
||||
if (!splitPanelContext?.selectedLeftData) {
|
||||
@@ -89,6 +115,7 @@ export const RelatedDataButtonsComponent: React.FC<RelatedDataButtonsComponentPr
|
||||
const defaultItem = items.find(item => item.isDefault);
|
||||
const targetItem = defaultItem || items[0];
|
||||
setSelectedId(targetItem.id);
|
||||
setSelectedItem(targetItem);
|
||||
emitSelection(targetItem);
|
||||
}
|
||||
}
|
||||
@@ -104,6 +131,7 @@ export const RelatedDataButtonsComponent: React.FC<RelatedDataButtonsComponentPr
|
||||
useEffect(() => {
|
||||
if (masterData) {
|
||||
setSelectedId(null); // 마스터 변경 시 선택 초기화
|
||||
setSelectedItem(null);
|
||||
loadButtons();
|
||||
}
|
||||
}, [masterData, loadButtons]);
|
||||
@@ -134,9 +162,82 @@ export const RelatedDataButtonsComponent: React.FC<RelatedDataButtonsComponentPr
|
||||
// 버튼 클릭 핸들러
|
||||
const handleButtonClick = useCallback((item: ButtonItem) => {
|
||||
setSelectedId(item.id);
|
||||
setSelectedItem(item);
|
||||
emitSelection(item);
|
||||
}, [emitSelection]);
|
||||
|
||||
// 모달 열기 (선택된 버튼 데이터 전달)
|
||||
const openModalWithSelectedData = useCallback((targetScreenId: number) => {
|
||||
if (!selectedItem) {
|
||||
console.warn("선택된 버튼이 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 데이터 매핑 적용
|
||||
const initialData: Record<string, any> = {};
|
||||
|
||||
if (config.modalLink?.dataMapping) {
|
||||
config.modalLink.dataMapping.forEach(mapping => {
|
||||
if (mapping.sourceField === "value") {
|
||||
initialData[mapping.targetField] = selectedItem.value;
|
||||
} else if (mapping.sourceField === "id") {
|
||||
initialData[mapping.targetField] = selectedItem.id;
|
||||
} else if (selectedItem.rawData[mapping.sourceField] !== undefined) {
|
||||
initialData[mapping.targetField] = selectedItem.rawData[mapping.sourceField];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 기본 매핑: id를 routing_version_id로 전달
|
||||
initialData["routing_version_id"] = selectedItem.value || selectedItem.id;
|
||||
}
|
||||
|
||||
console.log("📤 RelatedDataButtons 모달 열기:", {
|
||||
targetScreenId,
|
||||
selectedItem,
|
||||
initialData,
|
||||
});
|
||||
|
||||
window.dispatchEvent(new CustomEvent("open-screen-modal", {
|
||||
detail: {
|
||||
screenId: targetScreenId,
|
||||
initialData,
|
||||
onSuccess: () => {
|
||||
loadButtons(); // 모달 성공 후 새로고침
|
||||
},
|
||||
},
|
||||
}));
|
||||
}, [selectedItem, config.modalLink, loadButtons]);
|
||||
|
||||
// 외부 버튼에서 모달 열기 요청 수신
|
||||
useEffect(() => {
|
||||
const handleExternalModalOpen = (event: CustomEvent) => {
|
||||
const { targetScreenId, componentId } = event.detail || {};
|
||||
|
||||
// componentId가 지정되어 있고 현재 컴포넌트가 아니면 무시
|
||||
if (componentId && componentId !== config.sourceMapping?.sourceTable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetScreenId && selectedItem) {
|
||||
openModalWithSelectedData(targetScreenId);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("related-buttons-open-modal" as any, handleExternalModalOpen);
|
||||
return () => {
|
||||
window.removeEventListener("related-buttons-open-modal" as any, handleExternalModalOpen);
|
||||
};
|
||||
}, [selectedItem, config.sourceMapping, openModalWithSelectedData]);
|
||||
|
||||
// 내부 모달 링크 버튼 클릭
|
||||
const handleModalLinkClick = useCallback(() => {
|
||||
if (!config.modalLink?.targetScreenId) {
|
||||
console.warn("모달 링크 설정이 없습니다.");
|
||||
return;
|
||||
}
|
||||
openModalWithSelectedData(config.modalLink.targetScreenId);
|
||||
}, [config.modalLink, openModalWithSelectedData]);
|
||||
|
||||
// 추가 버튼 클릭
|
||||
const handleAddClick = useCallback(() => {
|
||||
if (!config.addButton?.modalScreenId) return;
|
||||
@@ -177,6 +278,7 @@ export const RelatedDataButtonsComponent: React.FC<RelatedDataButtonsComponentPr
|
||||
|
||||
const headerConfig = config.headerDisplay;
|
||||
const addButtonConfig = config.addButton;
|
||||
const modalLinkConfig = config.modalLink;
|
||||
|
||||
return (
|
||||
<div className={cn("rounded-lg border bg-card", className)} style={style}>
|
||||
@@ -198,18 +300,34 @@ export const RelatedDataButtonsComponent: React.FC<RelatedDataButtonsComponentPr
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 헤더 위치 추가 버튼 */}
|
||||
{addButtonConfig?.show && addButtonConfig?.position === "header" && (
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
onClick={handleAddClick}
|
||||
className="bg-blue-600 hover:bg-blue-700"
|
||||
>
|
||||
<Plus className="mr-1 h-4 w-4" />
|
||||
{addButtonConfig.label || "버전 추가"}
|
||||
</Button>
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* 모달 링크 버튼 (헤더 위치) */}
|
||||
{modalLinkConfig?.enabled && modalLinkConfig?.triggerType === "button" && modalLinkConfig?.buttonPosition === "header" && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleModalLinkClick}
|
||||
disabled={!selectedItem}
|
||||
title={!selectedItem ? "버튼을 먼저 선택하세요" : ""}
|
||||
>
|
||||
<ExternalLink className="mr-1 h-4 w-4" />
|
||||
{modalLinkConfig.buttonLabel || "상세 추가"}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* 헤더 위치 추가 버튼 */}
|
||||
{addButtonConfig?.show && addButtonConfig?.position === "header" && (
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
onClick={handleAddClick}
|
||||
className="bg-blue-600 hover:bg-blue-700"
|
||||
>
|
||||
<Plus className="mr-1 h-4 w-4" />
|
||||
{addButtonConfig.label || "버전 추가"}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -258,6 +376,20 @@ export const RelatedDataButtonsComponent: React.FC<RelatedDataButtonsComponentPr
|
||||
</Button>
|
||||
))}
|
||||
|
||||
{/* 모달 링크 버튼 (인라인 위치) */}
|
||||
{modalLinkConfig?.enabled && modalLinkConfig?.triggerType === "button" && modalLinkConfig?.buttonPosition !== "header" && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size={config.buttonStyle?.size || "default"}
|
||||
onClick={handleModalLinkClick}
|
||||
disabled={!selectedItem}
|
||||
title={!selectedItem ? "버튼을 먼저 선택하세요" : ""}
|
||||
>
|
||||
<ExternalLink className="mr-1 h-4 w-4" />
|
||||
{modalLinkConfig.buttonLabel || "상세 추가"}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* 인라인 추가 버튼 */}
|
||||
{addButtonConfig?.show && addButtonConfig?.position !== "header" && (
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user