"use client"; import { 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, CardContent } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { useToast } from "@/hooks/use-toast"; import { Plus, Search, Edit, Trash2, Copy, LayoutDashboard, MoreHorizontal } from "lucide-react"; /** * 대시보드 관리 페이지 * - 대시보드 목록 조회 * - 대시보드 생성/수정/삭제/복사 */ export default function DashboardListPage() { const router = useRouter(); const { toast } = useToast(); const [dashboards, setDashboards] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); // 모달 상태 const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteTarget, setDeleteTarget] = useState<{ id: string; title: string } | null>(null); // 대시보드 목록 로드 const loadDashboards = async () => { try { setLoading(true); const result = await dashboardApi.getMyDashboards({ search: searchTerm }); setDashboards(result.dashboards); } catch (err) { console.error("Failed to load dashboards:", err); toast({ title: "오류", description: "대시보드 목록을 불러오는데 실패했습니다.", variant: "destructive", }); } finally { setLoading(false); } }; useEffect(() => { loadDashboards(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [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); toast({ title: "성공", description: "대시보드가 삭제되었습니다.", }); loadDashboards(); } catch (err) { console.error("Failed to delete dashboard:", err); setDeleteDialogOpen(false); toast({ title: "오류", description: "대시보드 삭제에 실패했습니다.", variant: "destructive", }); } }; // 대시보드 복사 const handleCopy = async (dashboard: Dashboard) => { try { const fullDashboard = await dashboardApi.getDashboard(dashboard.id); await dashboardApi.createDashboard({ title: `${fullDashboard.title} (복사본)`, description: fullDashboard.description, elements: fullDashboard.elements || [], isPublic: false, tags: fullDashboard.tags, category: fullDashboard.category, settings: fullDashboard.settings as { resolution?: string; backgroundColor?: string }, }); toast({ title: "성공", description: "대시보드가 복사되었습니다.", }); loadDashboards(); } catch (err) { console.error("Failed to copy dashboard:", err); toast({ title: "오류", description: "대시보드 복사에 실패했습니다.", variant: "destructive", }); } }; // 포맷팅 헬퍼 const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString("ko-KR", { year: "numeric", month: "2-digit", day: "2-digit", }); }; return (
{/* 페이지 제목 */}

대시보드 관리

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

{/* 검색 및 필터 */}
setSearchTerm(e.target.value)} className="w-64 pl-10" />
{/* 대시보드 목록 */} {loading ? (
로딩 중...
) : dashboards.length === 0 ? (

등록된 대시보드가 없습니다

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

) : ( 제목 설명 생성일 작업 {dashboards.map((dashboard) => (
{dashboard.title}
{dashboard.description || "-"} {formatDate(dashboard.createdAt)}
))}
)}
{/* 삭제 확인 모달 */} 대시보드 삭제 확인 "{deleteTarget?.title}" 대시보드를 삭제하시겠습니까?
이 작업은 되돌릴 수 없습니다.
취소 삭제
); }