
+
+ Add a journey point
+
+ )
+ },
+ position: { x: 250, y: 220 }
}
];
@@ -78,11 +88,17 @@ const nodeContents = {
`
};
+const connectEdges = [
+ {
+ id: 'e1-2',
+ source: '1',
+ target: '2'
+ }
+];
+
const NoteFlow = () => {
const [nodes, setNodes] = useState(initialNodes);
- const [edges, setEdges] = useState([
- { id: 'e1-2', source: '1', target: '2' } // Kết nối node "Add Note" với node mặc định ban đầu
- ]);
+ const [edges, setEdges] = useState(connectEdges);
const [showTabBar, setShowTabBar] = useState(false);
const [lastNodeId, setLastNodeId] = useState('1');
const [nodeToDelete, setNodeToDelete] = useState(null);
@@ -99,13 +115,14 @@ const NoteFlow = () => {
});
};
const closeTabbar = () => {
- console.log('aaa');
setIsTabbarVisible(false); // Ẩn tabbar khi click close
};
const onNodeClick = (event, node) => {
- if (node.id === '2') {
- // Check if the clicked node is "Add Note"
+ console.log(node);
+ if (node.key === 'add-node') {
+ console.log(node);
+ // Check if the clicked node is "Add Node"
setShowTabBar(true);
setIsTabbarVisible(true);
} else {
@@ -165,14 +182,13 @@ const NoteFlow = () => {
const addNode = (option) => {
const newNodeId = nanoid(8); // Generate a unique ID for the new node
- const addNoteNode = nodes.find((node) => node.id === '2');
- const initialX = addNoteNode.position.x;
- console.log(initialX);
+ const addNoteNode = nodes.find((node) => node.key === 'add-node');
+ const initialX = addNoteNode?.position.x;
const nextY =
nodes.length > 2
- ? getNextYPosition(initialX, 130)
- : addNoteNode.position.y;
+ ? getNextYPosition(initialX, 120)
+ : addNoteNode?.position.y;
// Remove existing edges from addNoteNode
setEdges((eds) =>
@@ -270,14 +286,12 @@ const NoteFlow = () => {
setLastNodeId(noNode.id);
} else {
- console.log(option);
-
// Add new node logic
if (addNoteNode) {
const initialX = addNoteNode.position.x;
setNodes((nds) =>
nds.map((node) =>
- node.id === '2'
+ node.key === 'add-node'
? {
...node,
position: {
@@ -303,6 +317,10 @@ const NoteFlow = () => {
id: nanoid(8),
source: lastNodeId,
target: newNodeId
+ // data: {
+ // label:
+
,
+ // onClick: handleAddNoteClick
+ // }
};
setNodes((nds) => [...nds, newNode]);
@@ -315,15 +333,17 @@ const NoteFlow = () => {
// setEdges((eds) => [
// ...eds,
// {
- // id: uuidv4(),
+ // id: nanoid(8),
// source: lastNodeId,
// data: {
// label:
Add Note
, // Use HTML or React component
// onClick: handleAddNoteClick
// },
// target: newNodeId
- // }
+ // },
+ // { id: nanoid(8), source: newNodeId, target: addNoteNode.id }
// ]);
+
// Cuộn tới node mới thêm
setLastNodeId(newNodeId);
}
@@ -340,21 +360,361 @@ const NoteFlow = () => {
setSelectedNodeContent(content); // Cập nhật nội dung được chọn
};
+ const onDrop = (event) => {
+ event.preventDefault();
+
+ const type = JSON.parse(
+ event.dataTransfer.getData('application/reactflow')
+ );
+ const reactFlowBounds = event.target.getBoundingClientRect();
+ const position = {
+ x: event.clientX - reactFlowBounds.left - 100,
+ y: event.clientY - reactFlowBounds.top + 5
+ };
+
+ const newNodeId = nanoid(8);
+ // Xử lý add-node với id '2'
+ const addNodeId = '2';
+ const addNode = nodes.find((node) => node.id === addNodeId);
+
+ // Tìm các edge nối với node có id '2'
+ const targetEdge = edges.find(
+ (edge) => edge?.source === '2' || edge?.target === '2'
+ );
+ const targetNodeId =
+ targetEdge?.source === '2' ? targetEdge?.target : targetEdge?.source;
+
+ const targetNode = nodes.find((node) => node.id === targetNodeId);
+
+ // Cập nhật vị trí của node mới để cách node đang kết nối 200 đơn vị
+ const newNodePosition = {
+ x: targetNode?.position.x,
+ y: targetNode?.position.y + 110
+ };
+
+ // Tạo node mới
+ const newNode = {
+ id: newNodeId,
+ key: type.key,
+ type: type.type || 'default',
+ data: {
+ label: (
+
+
+

+
+
{type.label}
+
+ )
+ },
+ position: newNodePosition
+ };
+
+ // Loại bỏ các edge liên quan đến node '2'
+ setEdges((eds) =>
+ eds.filter((edge) => edge.source !== '2' && edge.target !== '2')
+ );
+
+ // Kiểm tra điều kiện node là 'ifelse'
+ if (type.key === 'ifelse') {
+ setNodes((nds) => nds.filter((node) => node.id !== addNodeId));
+ const yesNodeId = nanoid(8);
+ const noNodeId = nanoid(8);
+
+ // Tạo node Yes
+ const yesNode = {
+ id: yesNodeId,
+ key: 'add-node',
+ brand: 'yes',
+ data: {
+ label: (
+
+ + Add a journey point
+
+ )
+ },
+ position: {
+ x: newNode.position.x - 200, // Điều chỉnh vị trí của nhánh Yes
+ y: newNode.position.y + 150 // Điều chỉnh vị trí của nhánh Yes
+ }
+ };
+
+ // Tạo node No
+ const noNode = {
+ id: noNodeId,
+ key: 'add-node',
+ brand: 'no',
+ data: {
+ label: (
+
+ + Add a journey point
+
+ )
+ },
+ position: {
+ x: newNode?.position.x + 200, // Điều chỉnh vị trí của nhánh No
+ y: newNode?.position.y + 150 // Điều chỉnh vị trí của nhánh No
+ }
+ };
+
+ // Tạo các edge nối từ node ifelse đến Yes và No
+ const ifelseEdges = [
+ {
+ id: nanoid(8),
+ source: targetNodeId,
+ target: newNodeId
+ },
+ {
+ id: nanoid(8),
+ source: newNodeId,
+ target: yesNodeId,
+ type: 'custom',
+ data: {
+ label: 'Yes'
+ }
+ },
+ {
+ id: nanoid(8),
+ source: newNodeId,
+ target: noNodeId,
+ type: 'custom',
+ data: {
+ label: 'No'
+ }
+ }
+ ];
+
+ // Thêm node yes, no và edge vào danh sách node và edges
+ setNodes((nds) => [...nds, newNode, yesNode, noNode]);
+ setEdges((eds) => [...eds, ...ifelseEdges]);
+ } else {
+ // Nếu không phải 'ifelse', kiểm tra các điều kiện của node bình thường
+
+ if (targetNode) {
+ setNodes((nds) => [...nds, newNode]);
+ setEdges((eds) => [
+ ...eds,
+ {
+ id: nanoid(8),
+ source: targetNodeId,
+ target: newNodeId
+ },
+ {
+ id: nanoid(8),
+ source: newNodeId,
+ target: '2'
+ }
+ ]);
+
+ if (addNode) {
+ const addNodePosition = {
+ x: addNode.position.x,
+ y: addNode.position.y + 110
+ };
+
+ setNodes((nds) =>
+ nds.map((node) =>
+ node.id === addNodeId
+ ? { ...node, position: addNodePosition }
+ : node
+ )
+ );
+
+ setEdges((eds) =>
+ eds.filter(
+ (edge) => edge.source !== addNodeId && edge.target !== addNodeId
+ )
+ );
+
+ // Thêm edge mới nối add-node và node mới
+ setEdges((eds) => [
+ ...eds,
+ {
+ id: nanoid(8),
+ source: newNodeId,
+ target: addNodeId
+ }
+ ]);
+
+ // Kiểm tra nếu node mới là 'contact-exists', ẩn add-node
+ if (type.key === 'contact-exists') {
+ setNodes((nds) => nds.filter((node) => node.id !== addNodeId));
+ }
+ }
+ } else {
+ const newNodeNew = {
+ id: newNodeId,
+ key: type.key,
+ type: type.type || 'default',
+ data: {
+ label: (
+
+
+

+
+
{type.label}
+
+ )
+ },
+ position: position
+ };
+
+ setNodes((nds) => [...nds, newNodeNew]);
+ }
+ }
+ };
+
+ const onDragOver = useCallback((event) => {
+ event.preventDefault();
+ event.dataTransfer.dropEffect = 'move';
+ }, []);
+
+ const onNodesChange = useCallback(
+ (changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
+ [setNodes]
+ );
+ const onEdgesChange = useCallback(
+ (changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
+ [setEdges]
+ );
+
+ const defaultEdgeOptions = {
+ style: { strokeWidth: 1.5, stroke: 'black' },
+ type: 'floating',
+ markerEnd: {
+ type: MarkerType.ArrowClosed,
+ color: 'black'
+ }
+ };
+
+ const onConnect = useCallback(
+ (params) => setEdges((eds) => addEdge(params, eds)),
+ [setEdges]
+ );
+
+ // Hàm tính khoảng cách giữa hai node
+ const getDistance = (pos1, pos2) => {
+ return Math.sqrt(
+ Math.pow(pos1.x - pos2.x, 2) + Math.pow(pos1.y - pos2.y, 2)
+ );
+ };
+
+ // Hàm xử lý khi dừng kéo node
+ const onNodeDragStop = useCallback(
+ (event, node) => {
+ const threshold = 50; // khoảng cách cho phép để node bị "đè"
+ let closestNode = null;
+ let closestDistance = Infinity;
+
+ nodes.forEach((item) => {
+ if (item.id !== node.id) {
+ const distance = getDistance(node.position, item.position);
+ if (distance < closestDistance && distance <= threshold) {
+ closestNode = item;
+ closestDistance = distance;
+ }
+ }
+ });
+
+ if (closestNode) {
+ // Thay thế node cũ bằng node mới
+ const updatedEdges = edges.map((edge) => {
+ if (edge.source === closestNode.id) {
+ return { ...edge, source: node.id }; // Nối node mới làm source
+ }
+ if (edge.target === closestNode.id) {
+ return { ...edge, target: node.id }; // Nối node mới làm target
+ }
+ return edge;
+ });
+ if (node.type != 'output') {
+ // Tạo một node mới với nội dung "Add a journey point" ngay dưới node thay thế
+ const newNode = {
+ id: nanoid(8),
+ key: 'add-node',
+ brand: node.brand,
+ position: {
+ x: node.position.x, // Giữ nguyên vị trí x
+ y: node.position.y + 100 // Đặt node mới xuống dưới 150 đơn vị y
+ },
+ data: {
+ label: (
+
+ + Add a journey point
+
+ )
+ }
+ };
+
+ // Thay thế node cũ bằng node mới
+ setNodes((nds) => [
+ ...nds.map((n) =>
+ n.id === closestNode.id
+ ? { ...closestNode, ...node, position: node.position }
+ : n
+ ),
+ newNode // Thêm node mới
+ ]);
+
+ // Cập nhật edges
+ setEdges([
+ ...updatedEdges,
+ {
+ id: nanoid(8), // ID của edge mới
+ source: node.id, // Nối từ node vừa thay thế
+ target: newNode.id // Đến node "Add a journey point"
+ }
+ ]);
+ } else {
+ // Thay thế node cũ bằng node mới
+ setNodes((nds) => [
+ ...nds.map((n) =>
+ n.id === closestNode.id
+ ? { ...closestNode, ...node, position: node.position }
+ : n
+ )
+ ]);
+
+ // Cập nhật edges
+ setEdges(updatedEdges);
+ }
+ } else {
+ // Không có node gần, cập nhật node vào vị trí mới
+ setNodes((nds) =>
+ nds.map((n) =>
+ n.id === node.id ? { ...n, position: node.position } : n
+ )
+ );
+ }
+ },
+ [nodes, edges, setNodes, setEdges]
+ );
+
return (
-
-
-
-
-
+
+
{isTabbarVisible && (
diff --git a/src/nodes/ShowPopup.tsx b/src/nodes/ShowPopup.tsx
index beee81e..0cddbb0 100644
--- a/src/nodes/ShowPopup.tsx
+++ b/src/nodes/ShowPopup.tsx
@@ -18,14 +18,27 @@ const ShowPopup = ({ selectedNodeContent, hidePopup }) => {
<>
+
+
+
+
+
>
);
diff --git a/src/nodes/Tabbar.tsx b/src/nodes/Tabbar.tsx
index 6871e72..ca293cf 100644
--- a/src/nodes/Tabbar.tsx
+++ b/src/nodes/Tabbar.tsx
@@ -60,7 +60,7 @@ const tabBarOptions = [
Send email
),
- position: { x: 250, y: 0 }
+ position: { x: 400, y: 0 }
},
{
key: 'ifelse',
@@ -91,10 +91,11 @@ const tabBarOptions = [
Replied to conversation?
),
- position: { x: 250, y: 290 }
+ position: { x: 400, y: 290 }
},
{
key: 'send-survey',
+ branchKey: 'no',
label: 'Send survey',
id: '5',
type: 'output',
@@ -122,10 +123,11 @@ const tabBarOptions = [
Send survey
),
- position: { x: 250, y: 400 }
+ position: { x: 400, y: 400 }
},
{
key: 'contact-exists',
+ branchKey: 'yes',
label: 'Contact Exists',
id: '6',
type: 'output',
@@ -153,7 +155,7 @@ const tabBarOptions = [