"use client"; import { useState, useEffect, useCallback } 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, Smartphone, Tablet, Eye } from "lucide-react"; import { PopDesigner } from "@/components/pop/designer"; import { ScreenRelationFlow } from "@/components/screen/ScreenRelationFlow"; 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 CreateScreenModal from "@/components/screen/CreateScreenModal"; import { Badge } from "@/components/ui/badge"; // 단계별 진행을 위한 타입 정의 type Step = "list" | "design"; type ViewMode = "tree" | "table"; type DevicePreview = "mobile" | "tablet"; export default function PopScreenManagementPage() { 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("tree"); const [screens, setScreens] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); const [isCreateOpen, setIsCreateOpen] = useState(false); const [devicePreview, setDevicePreview] = useState("tablet"); // POP 레이아웃 존재 화면 ID const [popLayoutScreenIds, setPopLayoutScreenIds] = useState>(new Set()); // 화면 목록 및 POP 레이아웃 존재 여부 로드 const loadScreens = useCallback(async () => { try { setLoading(true); const [result, popScreenIds] = await Promise.all([ screenApi.getScreens({ page: 1, size: 1000, searchTerm: "" }), screenApi.getScreenIdsWithPopLayout(), ]); if (result.data && result.data.length > 0) { setScreens(result.data); } setPopLayoutScreenIds(new Set(popScreenIds)); } catch (error) { console.error("POP 화면 목록 로드 실패:", error); } finally { setLoading(false); } }, []); useEffect(() => { loadScreens(); }, [loadScreens]); // 화면 목록 새로고침 이벤트 리스너 useEffect(() => { const handleScreenListRefresh = () => { console.log("🔄 POP 화면 목록 새로고침 이벤트 수신"); 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); setSelectedGroup(null); }; // 화면 디자인 핸들러 const handleDesignScreen = (screen: ScreenDefinition) => { setSelectedScreen(screen); goToNextStep("design"); }; // POP 화면 미리보기 (새 탭에서 열기) const handlePreviewScreen = (screen: ScreenDefinition) => { const previewUrl = `/pop/screens/${screen.screenId}?preview=true&device=${devicePreview}`; window.open(previewUrl, "_blank", "width=800,height=900"); }; // POP 화면만 필터링 (POP 레이아웃이 있는 화면만) const popScreens = screens.filter((screen) => popLayoutScreenIds.has(screen.screenId)); // 검색어 필터링 const searchKeywords = searchTerm.toLowerCase().trim().split(/\s+/).filter(Boolean); const filteredScreens = popScreens.filter((screen) => { if (searchKeywords.length > 1) { return true; // 폴더 계층 검색 시 화면 필터링 없음 } if (!searchTerm) return true; return ( screen.screenName.toLowerCase().includes(searchTerm.toLowerCase()) || screen.screenCode.toLowerCase().includes(searchTerm.toLowerCase()) ); }); // POP 화면 수 const popScreenCount = popLayoutScreenIds.size; // 화면 설계 모드일 때는 POP 전용 디자이너 사용 if (isDesignMode && selectedScreen) { return (
goToStep("list")} onScreenUpdate={(updatedFields) => { setSelectedScreen({ ...selectedScreen, ...updatedFields, }); }} />
); } return (
{/* 페이지 헤더 */}

POP 화면 관리

모바일/태블릿

POP 화면을 그룹별로 관리하고 모바일/태블릿에 최적화된 화면을 설계합니다

{/* 디바이스 미리보기 선택 */} setDevicePreview(v as DevicePreview)}> 모바일 태블릿
{/* 뷰 모드 전환 */} setViewMode(v as ViewMode)}> 트리 테이블
{/* 메인 콘텐츠 */} {popScreenCount === 0 ? ( // POP 화면이 없을 때 빈 상태 표시

POP 화면이 없습니다

아직 생성된 POP 화면이 없습니다.
"새 POP 화면" 버튼을 클릭하여 모바일/태블릿용 화면을 만들어보세요.

) : viewMode === "tree" ? (
{/* 왼쪽: POP 화면 목록 */}
{/* 검색 */}
setSearchTerm(e.target.value)} className="pl-9 h-9" />
{/* POP 화면 수 표시 */}
POP 화면 {popScreenCount}개
{/* POP 화면 리스트 */}
{filteredScreens.length === 0 ? (
검색 결과가 없습니다
) : (
{filteredScreens.map((screen) => (
handleScreenSelect(screen)} onDoubleClick={() => handleDesignScreen(screen)} >
{screen.screenName}
{screen.screenCode} {screen.tableName && `| ${screen.tableName}`}
))}
)}
{/* 오른쪽: 관계 시각화 (React Flow) */}
) : ( // 테이블 뷰 - POP 화면만 표시
{filteredScreens.map((screen) => ( handleScreenSelect(screen)} > ))}
화면명 화면코드 테이블명 생성일 작업
{screen.screenName} {screen.screenCode} {screen.tableName || "-"} {screen.createdDate ? new Date(screen.createdDate).toLocaleDateString("ko-KR") : "-"}
)} {/* 화면 생성 모달 */} { setIsCreateOpen(open); if (!open) loadScreens(); }} onCreated={() => { setIsCreateOpen(false); loadScreens(); }} isPop={true} /> {/* Scroll to Top 버튼 */}
); }