ERP-node/frontend/components/dataflow/CustomEdge.tsx

163 lines
4.1 KiB
TypeScript
Raw Normal View History

2025-09-05 11:30:27 +09:00
"use client";
import React from "react";
import { EdgeProps, getBezierPath, EdgeLabelRenderer, BaseEdge } from "@xyflow/react";
interface CustomEdgeData {
relationshipType: string;
connectionType: string;
label?: string;
}
export const CustomEdge: React.FC<EdgeProps<CustomEdgeData>> = ({
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
data,
markerEnd,
selected,
}) => {
const [edgePath, labelX, labelY] = getBezierPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition,
});
// 연결 타입에 따른 색상 반환
const getEdgeColor = (connectionType: string) => {
switch (connectionType) {
case "simple-key":
return "#3B82F6"; // 파란색 - 단순 키값 연결
case "data-save":
return "#10B981"; // 초록색 - 데이터 저장
case "external-call":
return "#F59E0B"; // 주황색 - 외부 호출
default:
return "#6B7280"; // 회색 - 기본
}
};
// 연결 타입에 따른 스타일 반환
const getEdgeStyle = (connectionType: string) => {
switch (connectionType) {
case "simple-key":
return {
strokeWidth: 2,
strokeDasharray: "5,5",
opacity: selected ? 1 : 0.8,
};
case "data-save":
return {
strokeWidth: 3,
opacity: selected ? 1 : 0.8,
};
case "external-call":
return {
strokeWidth: 2,
strokeDasharray: "10,5",
opacity: selected ? 1 : 0.8,
};
default:
return {
strokeWidth: 2,
opacity: selected ? 1 : 0.6,
};
}
};
// 관계 타입에 따른 아이콘 반환
const getRelationshipIcon = (relationshipType: string) => {
switch (relationshipType) {
case "one-to-one":
return "1:1";
case "one-to-many":
return "1:N";
case "many-to-one":
return "N:1";
case "many-to-many":
return "N:N";
default:
return "1:1";
}
};
// 연결 타입에 따른 설명 반환
const getConnectionTypeDescription = (connectionType: string) => {
switch (connectionType) {
case "simple-key":
return "단순 키값";
case "data-save":
return "데이터 저장";
case "external-call":
return "외부 호출";
default:
return "연결";
}
};
const edgeColor = getEdgeColor(data?.connectionType || "");
const edgeStyle = getEdgeStyle(data?.connectionType || "");
return (
<>
<BaseEdge
id={id}
path={edgePath}
markerEnd={markerEnd}
style={{
stroke: edgeColor,
...edgeStyle,
}}
/>
<EdgeLabelRenderer>
<div
style={{
position: "absolute",
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
background: "white",
padding: "8px 12px",
borderRadius: "8px",
fontSize: "12px",
fontWeight: 600,
border: `2px solid ${edgeColor}`,
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
color: edgeColor,
minWidth: "80px",
textAlign: "center",
}}
className={`nodrag nopan transition-all duration-200 ${selected ? "scale-110" : "hover:scale-105"}`}
>
<div className="flex flex-col items-center">
<div className="text-sm font-bold">
{data?.label || getRelationshipIcon(data?.relationshipType || "one-to-one")}
</div>
<div className="mt-1 text-xs opacity-75">
{getConnectionTypeDescription(data?.connectionType || "simple-key")}
</div>
</div>
</div>
</EdgeLabelRenderer>
{/* 선택된 상태일 때 추가 시각적 효과 */}
{selected && (
<BaseEdge
id={`${id}-glow`}
path={edgePath}
style={{
stroke: edgeColor,
strokeWidth: 6,
opacity: 0.3,
}}
/>
)}
</>
);
};