"use client"; import React, { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { dashboardApi } from "@/lib/api/dashboard"; import { Dashboard } from "@/lib/api/dashboard"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Plus, Search, MoreVertical, Edit, Trash2, Copy, CheckCircle2 } from "lucide-react"; /** * 대시보드 관리 페이지 * - 대시보드 목록 조회 * - 대시보드 생성/수정/삭제/복사 */ export default function DashboardListPage() { const router = useRouter(); const [dashboards, setDashboards] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); const [error, setError] = useState(null); // 모달 상태 const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteTarget, setDeleteTarget] = useState<{ id: string; title: string } | null>(null); const [successDialogOpen, setSuccessDialogOpen] = useState(false); const [successMessage, setSuccessMessage] = useState(""); // 대시보드 목록 로드 const loadDashboards = async () => { try { setLoading(true); setError(null); const result = await dashboardApi.getMyDashboards({ search: searchTerm }); setDashboards(result.dashboards); } catch (err) { console.error("Failed to load dashboards:", err); setError("대시보드 목록을 불러오는데 실패했습니다."); } finally { setLoading(false); } }; useEffect(() => { loadDashboards(); }, [searchTerm]); // 대시보드 삭제 확인 모달 열기 const handleDeleteClick = (id: string, title: string) => { setDeleteTarget({ id, title }); setDeleteDialogOpen(true); }; // 대시보드 삭제 실행 const handleDeleteConfirm = async () => { if (!deleteTarget) return; try { await dashboardApi.deleteDashboard(deleteTarget.id); setDeleteDialogOpen(false); setDeleteTarget(null); setSuccessMessage("대시보드가 삭제되었습니다."); setSuccessDialogOpen(true); loadDashboards(); } catch (err) { console.error("Failed to delete dashboard:", err); setDeleteDialogOpen(false); setError("대시보드 삭제에 실패했습니다."); } }; // 대시보드 복사 const handleCopy = async (dashboard: Dashboard) => { try { // 전체 대시보드 정보(요소 포함)를 가져오기 const fullDashboard = await dashboardApi.getDashboard(dashboard.id); const newDashboard = await dashboardApi.createDashboard({ title: `${fullDashboard.title} (복사본)`, description: fullDashboard.description, elements: fullDashboard.elements || [], isPublic: false, tags: fullDashboard.tags, category: fullDashboard.category, settings: (fullDashboard as any).settings, // 해상도와 배경색 설정도 복사 }); setSuccessMessage("대시보드가 복사되었습니다."); setSuccessDialogOpen(true); loadDashboards(); } catch (err) { console.error("Failed to copy dashboard:", err); setError("대시보드 복사에 실패했습니다."); } }; // 포맷팅 헬퍼 const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString("ko-KR", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", }); }; if (loading) { return (
로딩 중...
대시보드 목록을 불러오고 있습니다
); } return (
{/* 헤더 */}

대시보드 관리

대시보드를 생성하고 관리할 수 있습니다

{/* 액션 바 */}
setSearchTerm(e.target.value)} className="pl-9" />
{/* 에러 메시지 */} {error && (

{error}

)} {/* 대시보드 목록 */} {dashboards.length === 0 ? (

대시보드가 없습니다

첫 번째 대시보드를 생성하여 데이터 시각화를 시작하세요

) : ( 제목 설명 생성일 수정일 작업 {dashboards.map((dashboard) => ( {dashboard.title} {dashboard.description || "-"} {formatDate(dashboard.createdAt)} {formatDate(dashboard.updatedAt)} router.push(`/admin/dashboard/edit/${dashboard.id}`)} className="gap-2" > 편집 handleCopy(dashboard)} className="gap-2"> 복사 handleDeleteClick(dashboard.id, dashboard.title)} className="gap-2 text-red-600 focus:text-red-600" > 삭제 ))}
)}
{/* 삭제 확인 모달 */} 대시보드 삭제 "{deleteTarget?.title}" 대시보드를 삭제하시겠습니까?
이 작업은 되돌릴 수 없습니다.
취소 삭제
{/* 성공 모달 */}
완료 {successMessage}
); }