"use client"; /** * 플로우 에디터 상단 툴바 */ import { useState } from "react"; import { Play, Save, FileCheck, Undo2, Redo2, ZoomIn, ZoomOut, FolderOpen, Download, Trash2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { useFlowEditorStore } from "@/lib/stores/flowEditorStore"; import { useReactFlow } from "reactflow"; import { LoadFlowDialog } from "./dialogs/LoadFlowDialog"; import { getNodeFlow } from "@/lib/api/nodeFlows"; export function FlowToolbar() { const { zoomIn, zoomOut, fitView } = useReactFlow(); const { flowName, setFlowName, validateFlow, saveFlow, exportFlow, isExecuting, isSaving, selectedNodes, removeNodes, } = useFlowEditorStore(); const [showLoadDialog, setShowLoadDialog] = useState(false); const handleValidate = () => { const result = validateFlow(); if (result.valid) { alert("✅ 검증 성공! 오류가 없습니다."); } else { alert(`❌ 검증 실패\n\n${result.errors.map((e) => `- ${e.message}`).join("\n")}`); } }; const handleSave = async () => { const result = await saveFlow(); if (result.success) { alert(`✅ ${result.message}\nFlow ID: ${result.flowId}`); } else { alert(`❌ 저장 실패\n\n${result.message}`); } }; const handleExport = () => { const json = exportFlow(); const blob = new Blob([json], { type: "application/json" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `${flowName || "flow"}.json`; a.click(); URL.revokeObjectURL(url); alert("✅ JSON 파일로 내보내기 완료!"); }; const handleLoad = async (flowId: number) => { try { const flow = await getNodeFlow(flowId); // flowData가 이미 객체인지 문자열인지 확인 const parsedData = typeof flow.flowData === "string" ? JSON.parse(flow.flowData) : flow.flowData; // Zustand 스토어의 loadFlow 함수 호출 useFlowEditorStore .getState() .loadFlow(flow.flowId, flow.flowName, flow.flowDescription, parsedData.nodes, parsedData.edges); alert(`✅ "${flow.flowName}" 플로우를 불러왔습니다!`); } catch (error) { console.error("플로우 불러오기 오류:", error); alert(error instanceof Error ? error.message : "플로우를 불러올 수 없습니다."); } }; const handleExecute = () => { // TODO: 실행 로직 구현 alert("실행 기능 구현 예정"); }; const handleDelete = () => { if (selectedNodes.length === 0) { alert("삭제할 노드를 선택해주세요."); return; } if (confirm(`선택된 ${selectedNodes.length}개 노드를 삭제하시겠습니까?`)) { removeNodes(selectedNodes); alert(`✅ ${selectedNodes.length}개 노드가 삭제되었습니다.`); } }; return ( <>
{/* 플로우 이름 */} setFlowName(e.target.value)} className="h-8 w-[200px] text-sm" placeholder="플로우 이름" />
{/* 실행 취소/다시 실행 */}
{/* 삭제 버튼 */}
{/* 줌 컨트롤 */}
{/* 불러오기 */} {/* 저장 */} {/* 내보내기 */}
{/* 검증 */} {/* 테스트 실행 */}
); }