"use client"; import { useState, useEffect, useCallback, useMemo } from "react"; import { useSearchParams } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Plus, RefreshCw, Search, LayoutGrid, LayoutList, TestTube2, Monitor, MoreHorizontal, PanelLeftClose, PanelLeftOpen } from "lucide-react"; import ScreenDesigner from "@/components/screen/ScreenDesigner"; import TemplateManager from "@/components/screen/TemplateManager"; import { ScreenGroupTreeView } from "@/components/screen/ScreenGroupTreeView"; import { ScreenRelationFlow } from "@/components/screen/ScreenRelationFlow"; import { V2ComponentsDemo } from "@/components/v2"; import { ScrollToTop } from "@/components/common/ScrollToTop"; import { ScreenDefinition } from "@/types/screen"; import { screenApi } from "@/lib/api/screen"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Badge } from "@/components/ui/badge"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import CreateScreenModal from "@/components/screen/CreateScreenModal"; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from "@/components/ui/sheet"; // 단계별 진행을 위한 타입 정의 type Step = "list" | "design" | "template" | "v2-test"; type ViewMode = "flow" | "card"; export default function ScreenManagementPage() { const searchParams = useSearchParams(); const [currentStep, setCurrentStep] = useState("list"); const [selectedScreen, setSelectedScreen] = useState(null); const [selectedGroup, setSelectedGroup] = useState<{ id: number; name: string; company_code?: string } | null>(null); const [focusedScreenIdInGroup, setFocusedScreenIdInGroup] = useState(null); const [stepHistory, setStepHistory] = useState(["list"]); const [viewMode, setViewMode] = useState("flow"); const [screens, setScreens] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); const [isCreateOpen, setIsCreateOpen] = useState(false); const [isDetailOpen, setIsDetailOpen] = useState(false); const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const tableCount = useMemo(() => new Set(screens.map((s) => s.tableName).filter(Boolean)).size, [screens]); // 화면 목록 로드 const loadScreens = useCallback(async () => { try { setLoading(true); const result = await screenApi.getScreens({ page: 1, size: 1000, searchTerm: "", excludePop: true }); // screenApi.getScreens는 { data: ScreenDefinition[], total, page, size, totalPages } 형태 반환 if (result.data && result.data.length > 0) { setScreens(result.data); } } catch (error) { console.error("화면 목록 로드 실패:", error); } finally { setLoading(false); } }, []); useEffect(() => { loadScreens(); }, [loadScreens]); // 화면 목록 새로고침 이벤트 리스너 useEffect(() => { const handleScreenListRefresh = () => { console.log("🔄 화면 목록 새로고침 이벤트 수신"); loadScreens(); }; window.addEventListener("screen-list-refresh", handleScreenListRefresh); return () => { window.removeEventListener("screen-list-refresh", handleScreenListRefresh); }; }, [loadScreens]); // URL 쿼리 파라미터로 화면 디자이너 자동 열기 useEffect(() => { const openDesignerId = searchParams.get("openDesigner"); if (openDesignerId && screens.length > 0) { const screenId = parseInt(openDesignerId, 10); const targetScreen = screens.find((s) => s.screenId === screenId); if (targetScreen) { setSelectedScreen(targetScreen); setCurrentStep("design"); setStepHistory(["list", "design"]); } } }, [searchParams, screens]); // 화면 설계 모드일 때는 전체 화면 사용 const isDesignMode = currentStep === "design"; // 다음 단계로 이동 const goToNextStep = (nextStep: Step) => { setStepHistory((prev) => [...prev, nextStep]); setCurrentStep(nextStep); }; // 특정 단계로 이동 const goToStep = (step: Step) => { setCurrentStep(step); const stepIndex = stepHistory.findIndex((s) => s === step); if (stepIndex !== -1) { setStepHistory(stepHistory.slice(0, stepIndex + 1)); } }; // 화면 선택 핸들러 (개별 화면 선택 시 그룹 선택 해제) const handleScreenSelect = (screen: ScreenDefinition) => { setSelectedScreen(screen); setIsDetailOpen(true); setSelectedGroup(null); // 그룹 선택 해제 }; // 화면 디자인 핸들러 const handleDesignScreen = (screen: ScreenDefinition) => { setSelectedScreen(screen); goToNextStep("design"); }; // 검색어로 필터링된 화면 // 검색어가 여러 키워드(폴더 계층 검색)이면 화면 필터링 없이 모든 화면 표시 // 단일 키워드면 해당 키워드로 화면 필터링 const searchKeywords = searchTerm.toLowerCase().trim().split(/\s+/).filter(Boolean); const filteredScreens = searchKeywords.length > 1 ? screens // 폴더 계층 검색 시에는 화면 필터링 없음 (폴더에서 이미 필터링됨) : screens.filter((screen) => screen.screenName.toLowerCase().includes(searchTerm.toLowerCase()) || screen.screenCode.toLowerCase().includes(searchTerm.toLowerCase()) ); // 화면 설계 모드일 때는 레이아웃 없이 전체 화면 사용 if (isDesignMode) { return (
goToStep("list")} onScreenUpdate={(updatedFields) => { if (selectedScreen) { const updated = { ...selectedScreen, ...updatedFields }; setSelectedScreen(updated); setScreens((prev) => prev.map((s) => s.screenId === selectedScreen.screenId ? { ...s, ...updatedFields } : s ) ); } }} />
); } // V2 컴포넌트 테스트 모드 if (currentStep === "v2-test") { return (
goToStep("list")} />
); } return (
{/* 페이지 헤더 */}

화면 관리

{screens.length}개 화면
{/* 뷰 모드 전환 */} setViewMode(v as ViewMode)}> 관계도 카드 goToNextStep("v2-test")}> V2 테스트
{/* 메인 콘텐츠 */} {viewMode === "flow" ? (
{/* 왼쪽: 트리 구조 (접기/펼기 지원) */}
{/* 사이드바 헤더 */}
{!sidebarCollapsed && 탐색}
{/* 사이드바 접힘 시 아이콘 컬럼 */} {sidebarCollapsed && (
{screens.length}
)} {/* 사이드바 펼침 시 전체 UI */} {!sidebarCollapsed && ( <> {/* 검색 */}
setSearchTerm(e.target.value)} className="pl-9 h-9 rounded-xl bg-muted/30 border-border/50 focus:bg-background focus:ring-2 focus:ring-primary/30 transition-colors" />
{/* 트리 뷰 */}
{ setSelectedGroup(group); setSelectedScreen(null); setFocusedScreenIdInGroup(null); }} onScreenSelectInGroup={(group, screenId) => { const isNewGroup = selectedGroup?.id !== group.id; if (isNewGroup) { setSelectedGroup(group); setFocusedScreenIdInGroup(null); } else { setFocusedScreenIdInGroup(screenId); } setSelectedScreen(null); }} />
)}
{/* 오른쪽: 관계 시각화 (React Flow) */}
) : (
{filteredScreens.map((screen) => (
handleScreenSelect(screen)} onDoubleClick={() => handleDesignScreen(screen)} >
{screen.screenName}
{screen.screenCode}
{screen.tableName || "테이블 없음"}
))}
{filteredScreens.length === 0 && (

검색 결과가 없습니다

)}
)} {/* 화면 디테일 Sheet */} {selectedScreen?.screenName || "화면 상세"} {selectedScreen?.screenCode} {selectedScreen && (
테이블 {selectedScreen.tableName || "없음"}
화면 ID {selectedScreen.screenId}
)}
{/* 화면 생성 모달 */} { setIsCreateOpen(false); loadScreens(); }} /> {/* Scroll to Top 버튼 */}
); }