"use client"; import React, { useState, useEffect } from "react"; import Link from "next/link"; interface Dashboard { id: string; title: string; description?: string; thumbnail?: string; elementsCount: number; createdAt: string; updatedAt: string; isPublic: boolean; } /** * 대시보드 목록 페이지 * - 저장된 대시보드들의 목록 표시 * - 새 대시보드 생성 링크 * - 대시보드 미리보기 및 관리 */ export default function DashboardListPage() { const [dashboards, setDashboards] = useState([]); const [isLoading, setIsLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); // 대시보드 목록 로딩 useEffect(() => { loadDashboards(); }, []); const loadDashboards = async () => { setIsLoading(true); try { // 실제 API 호출 시도 const { dashboardApi } = await import("@/lib/api/dashboard"); try { const result = await dashboardApi.getDashboards({ page: 1, limit: 50 }); // API에서 가져온 대시보드들을 Dashboard 형식으로 변환 const apiDashboards: Dashboard[] = result.dashboards.map((dashboard: any) => ({ id: dashboard.id, title: dashboard.title, description: dashboard.description, elementsCount: dashboard.elementsCount || dashboard.elements?.length || 0, createdAt: dashboard.createdAt, updatedAt: dashboard.updatedAt, isPublic: dashboard.isPublic, creatorName: dashboard.creatorName, })); setDashboards(apiDashboards); } catch (apiError) { console.warn("API 호출 실패, 로컬 스토리지 및 샘플 데이터 사용:", apiError); // API 실패 시 로컬 스토리지 + 샘플 데이터 사용 const savedDashboards = JSON.parse(localStorage.getItem("savedDashboards") || "[]"); // 샘플 대시보드들 const sampleDashboards: Dashboard[] = [ { id: "sales-overview", title: "📊 매출 현황 대시보드", description: "월별 매출 추이 및 상품별 판매 현황을 한눈에 확인할 수 있습니다.", elementsCount: 3, createdAt: "2024-09-30T10:00:00Z", updatedAt: "2024-09-30T14:30:00Z", isPublic: true, }, { id: "user-analytics", title: "👥 사용자 분석 대시보드", description: "사용자 행동 패턴 및 가입 추이 분석", elementsCount: 1, createdAt: "2024-09-29T15:00:00Z", updatedAt: "2024-09-30T09:15:00Z", isPublic: false, }, { id: "inventory-status", title: "📦 재고 현황 대시보드", description: "실시간 재고 현황 및 입출고 내역", elementsCount: 4, createdAt: "2024-09-28T11:30:00Z", updatedAt: "2024-09-29T16:45:00Z", isPublic: true, }, ]; // 저장된 대시보드를 Dashboard 형식으로 변환 const userDashboards: Dashboard[] = savedDashboards.map((dashboard: any) => ({ id: dashboard.id, title: dashboard.title, description: dashboard.description, elementsCount: dashboard.elements?.length || 0, createdAt: dashboard.createdAt, updatedAt: dashboard.updatedAt, isPublic: false, // 사용자가 만든 대시보드는 기본적으로 비공개 })); // 사용자 대시보드를 맨 앞에 배치 setDashboards([...userDashboards, ...sampleDashboards]); } } catch (error) { console.error("Dashboard loading error:", error); } finally { setIsLoading(false); } }; // 검색 필터링 const filteredDashboards = dashboards.filter( (dashboard) => dashboard.title.toLowerCase().includes(searchTerm.toLowerCase()) || dashboard.description?.toLowerCase().includes(searchTerm.toLowerCase()), ); return (
{/* 헤더 */}

📊 대시보드

데이터를 시각화하고 인사이트를 얻어보세요

➕ 새 대시보드 만들기
{/* 검색 바 */}
setSearchTerm(e.target.value)} className="w-full rounded-lg border border-input bg-background py-2 pr-4 pl-10 text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2" />
🔍
{/* 메인 콘텐츠 */}
{isLoading ? ( // 로딩 상태
{[1, 2, 3, 4, 5, 6].map((i) => (
))}
) : filteredDashboards.length === 0 ? ( // 빈 상태
📊

{searchTerm ? "검색 결과가 없습니다" : "아직 대시보드가 없습니다"}

{searchTerm ? "다른 검색어로 시도해보세요" : "첫 번째 대시보드를 만들어보세요"}

{!searchTerm && ( ➕ 대시보드 만들기 )}
) : ( // 대시보드 그리드
{filteredDashboards.map((dashboard) => ( ))}
)}
); } interface DashboardCardProps { dashboard: Dashboard; } /** * 개별 대시보드 카드 컴포넌트 */ function DashboardCard({ dashboard }: DashboardCardProps) { return (
{/* 썸네일 영역 */}
📊
{dashboard.elementsCount}개 요소
{/* 카드 내용 */}

{dashboard.title}

{dashboard.isPublic ? ( 공개 ) : ( 비공개 )}
{dashboard.description &&

{dashboard.description}

} {/* 메타 정보 */}
생성: {new Date(dashboard.createdAt).toLocaleDateString()}
수정: {new Date(dashboard.updatedAt).toLocaleDateString()}
{/* 액션 버튼들 */}
보기 편집
); }