"use client"; /** * 플로우 관리 메인 페이지 * - 플로우 정의 목록 * - 플로우 생성/수정/삭제 * - 플로우 편집기로 이동 */ import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { Plus, Edit2, Trash2, Play, Workflow, Table, Calendar, User } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { useToast } from "@/hooks/use-toast"; import { getFlowDefinitions, createFlowDefinition, deleteFlowDefinition } from "@/lib/api/flow"; import { FlowDefinition } from "@/types/flow"; export default function FlowManagementPage() { const router = useRouter(); const { toast } = useToast(); // 상태 const [flows, setFlows] = useState([]); const [loading, setLoading] = useState(true); const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [selectedFlow, setSelectedFlow] = useState(null); // 생성 폼 상태 const [formData, setFormData] = useState({ name: "", description: "", tableName: "", }); // 플로우 목록 조회 const loadFlows = async () => { setLoading(true); try { const response = await getFlowDefinitions({ isActive: true }); if (response.success && response.data) { setFlows(response.data); } else { toast({ title: "조회 실패", description: response.error || "플로우 목록을 불러올 수 없습니다.", variant: "destructive", }); } } catch (error: any) { toast({ title: "오류 발생", description: error.message, variant: "destructive", }); } finally { setLoading(false); } }; useEffect(() => { loadFlows(); }, []); // 플로우 생성 const handleCreate = async () => { if (!formData.name || !formData.tableName) { toast({ title: "입력 오류", description: "플로우 이름과 테이블 이름은 필수입니다.", variant: "destructive", }); return; } try { const response = await createFlowDefinition(formData); if (response.success && response.data) { toast({ title: "생성 완료", description: "플로우가 성공적으로 생성되었습니다.", }); setIsCreateDialogOpen(false); setFormData({ name: "", description: "", tableName: "" }); loadFlows(); } else { toast({ title: "생성 실패", description: response.error || response.message, variant: "destructive", }); } } catch (error: any) { toast({ title: "오류 발생", description: error.message, variant: "destructive", }); } }; // 플로우 삭제 const handleDelete = async () => { if (!selectedFlow) return; try { const response = await deleteFlowDefinition(selectedFlow.id); if (response.success) { toast({ title: "삭제 완료", description: "플로우가 삭제되었습니다.", }); setIsDeleteDialogOpen(false); setSelectedFlow(null); loadFlows(); } else { toast({ title: "삭제 실패", description: response.error, variant: "destructive", }); } } catch (error: any) { toast({ title: "오류 발생", description: error.message, variant: "destructive", }); } }; // 플로우 편집기로 이동 const handleEdit = (flowId: number) => { router.push(`/admin/flow-management/${flowId}`); }; return (
{/* 헤더 */}

플로우 관리

업무 프로세스 플로우를 생성하고 관리합니다

{/* 플로우 카드 목록 */} {loading ? (

로딩 중...

) : flows.length === 0 ? (

생성된 플로우가 없습니다

) : (
{flows.map((flow) => ( handleEdit(flow.id)} >
{flow.name} {flow.isActive && ( 활성 )} {flow.description || "설명 없음"}
{flow.tableName}
생성자: {flow.createdBy}
{new Date(flow.updatedAt).toLocaleDateString("ko-KR")}
))} )} {/* 생성 다이얼로그 */} 새 플로우 생성 새로운 업무 프로세스 플로우를 생성합니다
setFormData({ ...formData, name: e.target.value })} placeholder="예: 제품 수명주기 관리" className="h-8 text-xs sm:h-10 sm:text-sm" />
setFormData({ ...formData, tableName: e.target.value })} placeholder="예: products" className="h-8 text-xs sm:h-10 sm:text-sm" />

플로우가 관리할 데이터 테이블 이름을 입력하세요