"use client"; /** * 플로우 에디터 상단 툴바 */ import { useState } from "react"; import { Save, Undo2, Redo2, ZoomIn, ZoomOut, 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 { SaveConfirmDialog } from "./dialogs/SaveConfirmDialog"; import { validateFlow, summarizeValidations } from "@/lib/utils/flowValidation"; import type { FlowValidation } from "@/lib/utils/flowValidation"; import { useToast } from "@/hooks/use-toast"; interface FlowToolbarProps { validations?: FlowValidation[]; } export function FlowToolbar({ validations = [] }: FlowToolbarProps) { const { toast } = useToast(); const { zoomIn, zoomOut, fitView } = useReactFlow(); const { flowName, setFlowName, nodes, edges, saveFlow, exportFlow, isSaving, selectedNodes, removeNodes, undo, redo, canUndo, canRedo, } = useFlowEditorStore(); const [showSaveDialog, setShowSaveDialog] = useState(false); const handleSave = async () => { // 검증 수행 const currentValidations = validations.length > 0 ? validations : validateFlow(nodes, edges); const summary = summarizeValidations(currentValidations); // 오류나 경고가 있으면 다이얼로그 표시 if (currentValidations.length > 0) { setShowSaveDialog(true); return; } // 문제 없으면 바로 저장 await performSave(); }; const performSave = async () => { const result = await saveFlow(); if (result.success) { toast({ title: "✅ 플로우 저장 완료", description: `${result.message}\nFlow ID: ${result.flowId}`, variant: "default", }); } else { toast({ title: "❌ 저장 실패", description: result.message, variant: "destructive", }); } setShowSaveDialog(false); }; 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); toast({ title: "✅ 내보내기 완료", description: "JSON 파일로 저장되었습니다.", variant: "default", }); }; const handleDelete = () => { if (selectedNodes.length === 0) { toast({ title: "⚠️ 선택된 노드 없음", description: "삭제할 노드를 선택해주세요.", variant: "default", }); return; } if (confirm(`선택된 ${selectedNodes.length}개 노드를 삭제하시겠습니까?`)) { removeNodes(selectedNodes); toast({ title: "✅ 노드 삭제 완료", description: `${selectedNodes.length}개 노드가 삭제되었습니다.`, variant: "default", }); } }; return ( <>