"use client"; import { useState, useEffect, useCallback } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { MoreHorizontal, Trash2, Copy, Plus, Search, Network, Database, Calendar, User } from "lucide-react"; import { DataFlowAPI, DataFlowDiagram } from "@/lib/api/dataflow"; import { toast } from "sonner"; import { useAuth } from "@/hooks/useAuth"; interface DataFlowListProps { onDesignDiagram: (diagram: DataFlowDiagram | null) => void; } export default function DataFlowList({ onDesignDiagram }: DataFlowListProps) { const { user } = useAuth(); const [diagrams, setDiagrams] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [total, setTotal] = useState(0); // 사용자 회사 코드 가져오기 (기본값: "*") const companyCode = user?.company_code || user?.companyCode || "*"; // 모달 상태 const [showCopyModal, setShowCopyModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); const [selectedDiagramForAction, setSelectedDiagramForAction] = useState(null); // 목록 로드 함수 분리 const loadDiagrams = useCallback(async () => { try { setLoading(true); const response = await DataFlowAPI.getJsonDataFlowDiagrams(currentPage, 20, searchTerm, companyCode); // JSON API 응답을 기존 형식으로 변환 const convertedDiagrams = response.diagrams.map((diagram) => ({ diagramId: diagram.diagram_id, relationshipId: diagram.diagram_id, // 호환성을 위해 추가 diagramName: diagram.diagram_name, connectionType: "json-based", // 새로운 JSON 기반 타입 relationshipType: "multi-relationship", // 다중 관계 타입 relationshipCount: diagram.relationships?.relationships?.length || 0, tableCount: diagram.relationships?.tables?.length || 0, tables: diagram.relationships?.tables || [], companyCode: diagram.company_code, // 회사 코드 추가 createdAt: new Date(diagram.created_at || new Date()), createdBy: diagram.created_by || "SYSTEM", updatedAt: new Date(diagram.updated_at || diagram.created_at || new Date()), updatedBy: diagram.updated_by || "SYSTEM", lastUpdated: diagram.updated_at || diagram.created_at || new Date().toISOString(), })); setDiagrams(convertedDiagrams); setTotal(response.pagination.total || 0); setTotalPages(Math.max(1, Math.ceil((response.pagination.total || 0) / 20))); } catch (error) { console.error("관계도 목록 조회 실패", error); toast.error("관계도 목록을 불러오는데 실패했습니다."); } finally { setLoading(false); } }, [currentPage, searchTerm, companyCode]); // 관계도 목록 로드 useEffect(() => { loadDiagrams(); }, [loadDiagrams]); const handleDelete = (diagram: DataFlowDiagram) => { setSelectedDiagramForAction(diagram); setShowDeleteModal(true); }; const handleCopy = (diagram: DataFlowDiagram) => { setSelectedDiagramForAction(diagram); setShowCopyModal(true); }; // 복사 확인 const handleConfirmCopy = async () => { if (!selectedDiagramForAction) return; try { setLoading(true); const copiedDiagram = await DataFlowAPI.copyJsonDataFlowDiagram( selectedDiagramForAction.diagramId, companyCode, undefined, user?.userId || "SYSTEM", ); toast.success(`관계도가 성공적으로 복사되었습니다: ${copiedDiagram.diagram_name}`); // 목록 새로고침 await loadDiagrams(); } catch (error) { console.error("관계도 복사 실패:", error); toast.error("관계도 복사에 실패했습니다."); } finally { setLoading(false); setShowCopyModal(false); setSelectedDiagramForAction(null); } }; // 삭제 확인 const handleConfirmDelete = async () => { if (!selectedDiagramForAction) return; try { setLoading(true); await DataFlowAPI.deleteJsonDataFlowDiagram(selectedDiagramForAction.diagramId, companyCode); toast.success(`관계도가 삭제되었습니다: ${selectedDiagramForAction.diagramName}`); // 목록 새로고침 await loadDiagrams(); } catch (error) { console.error("관계도 삭제 실패:", error); toast.error("관계도 삭제에 실패했습니다."); } finally { setLoading(false); setShowDeleteModal(false); setSelectedDiagramForAction(null); } }; if (loading) { return (
로딩 중...
); } return (
{/* 검색 및 필터 */}
setSearchTerm(e.target.value)} className="w-80 pl-10" />
{/* 관계도 목록 테이블 */} 데이터 흐름 관계도 ({total}) 관계도명 회사 코드 테이블 수 관계 수 최근 수정 작업 {diagrams.map((diagram) => (
{diagram.diagramName}
테이블: {diagram.tables.slice(0, 3).join(", ")} {diagram.tables.length > 3 && ` 외 ${diagram.tables.length - 3}개`}
{diagram.companyCode || "*"}
{diagram.tableCount}
{diagram.relationshipCount}
{new Date(diagram.updatedAt).toLocaleDateString()}
{diagram.updatedBy}
onDesignDiagram(diagram)}> 관계도 설계 handleCopy(diagram)}> 복사 handleDelete(diagram)} className="text-red-600"> 삭제
))}
{diagrams.length === 0 && (
관계도가 없습니다
새 관계도를 생성하여 테이블 간 데이터 관계를 설정해보세요.
)}
{/* 페이지네이션 */} {totalPages > 1 && (
{currentPage} / {totalPages}
)} {/* 복사 확인 모달 */} 관계도 복사 “{selectedDiagramForAction?.diagramName}” 관계도를 복사하시겠습니까?
새로운 관계도는 원본 이름 뒤에 (1), (2), (3)... 형태로 생성됩니다.
{/* 삭제 확인 모달 */} 관계도 삭제 “{selectedDiagramForAction?.diagramName}” 관계도를 완전히 삭제하시겠습니까?
이 작업은 되돌릴 수 없으며, 모든 관계 정보가 영구적으로 삭제됩니다.
); }