"use client"; import React, { useEffect, useState } from "react"; import { useParams, useSearchParams } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Loader2, ArrowLeft, Smartphone, Tablet, RotateCcw, RotateCw } from "lucide-react"; import { screenApi } from "@/lib/api/screen"; import { ScreenDefinition } from "@/types/screen"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { ScreenPreviewProvider } from "@/contexts/ScreenPreviewContext"; import { useAuth } from "@/hooks/useAuth"; import { TableOptionsProvider } from "@/contexts/TableOptionsContext"; import { TableSearchWidgetHeightProvider } from "@/contexts/TableSearchWidgetHeightContext"; import { ScreenContextProvider } from "@/contexts/ScreenContext"; import { SplitPanelProvider } from "@/lib/registry/components/split-panel-layout/SplitPanelContext"; import { ActiveTabProvider } from "@/contexts/ActiveTabContext"; import { PopLayoutDataV5, GridMode, isV5Layout, createEmptyPopLayoutV5, } from "@/components/pop/designer/types/pop-layout"; import PopRenderer from "@/components/pop/designer/renderers/PopRenderer"; import { useResponsiveModeWithOverride, type DeviceType, } from "@/hooks/useDeviceOrientation"; // 디바이스별 크기 (프리뷰 모드용) const DEVICE_SIZES: Record> = { mobile: { landscape: { width: 667, height: 375, label: "모바일 가로" }, portrait: { width: 375, height: 667, label: "모바일 세로" }, }, tablet: { landscape: { width: 1024, height: 768, label: "태블릿 가로" }, portrait: { width: 768, height: 1024, label: "태블릿 세로" }, }, }; // 모드 키 변환 const getModeKey = (device: DeviceType, isLandscape: boolean): GridMode => { if (device === "tablet") { return isLandscape ? "tablet_landscape" : "tablet_portrait"; } return isLandscape ? "mobile_landscape" : "mobile_portrait"; }; // ======================================== // 메인 컴포넌트 (v5 그리드 시스템 전용) // ======================================== function PopScreenViewPage() { const params = useParams(); const searchParams = useSearchParams(); const router = useRouter(); const screenId = parseInt(params.screenId as string); const isPreviewMode = searchParams.get("preview") === "true"; // 반응형 모드 감지 (화면 크기에 따라 tablet/mobile, landscape/portrait 자동 전환) // 프리뷰 모드에서는 수동 전환 가능 const { mode, setDevice, setOrientation, isAutoDetect } = useResponsiveModeWithOverride( isPreviewMode ? "tablet" : undefined, isPreviewMode ? true : undefined ); // 현재 모드 정보 const deviceType = mode.device; const isLandscape = mode.isLandscape; const currentModeKey = getModeKey(deviceType, isLandscape); const { user } = useAuth(); const [screen, setScreen] = useState(null); const [layout, setLayout] = useState(createEmptyPopLayoutV5()); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // 뷰포트 너비 (클라이언트 사이드에서만 계산, 최대 1366px) const [viewportWidth, setViewportWidth] = useState(1024); // 기본값: 태블릿 가로 useEffect(() => { const updateViewportWidth = () => { setViewportWidth(Math.min(window.innerWidth, 1366)); }; updateViewportWidth(); window.addEventListener("resize", updateViewportWidth); return () => window.removeEventListener("resize", updateViewportWidth); }, []); // 화면 및 POP 레이아웃 로드 useEffect(() => { const loadScreen = async () => { try { setLoading(true); setError(null); const screenData = await screenApi.getScreen(screenId); setScreen(screenData); try { const popLayout = await screenApi.getLayoutPop(screenId); if (popLayout && isV5Layout(popLayout)) { // v5 레이아웃 로드 setLayout(popLayout); const componentCount = Object.keys(popLayout.components).length; console.log(`[POP] v5 레이아웃 로드됨: ${componentCount}개 컴포넌트`); } else if (popLayout) { // 다른 버전 레이아웃은 빈 v5로 처리 console.log("[POP] 레거시 레이아웃 감지, 빈 레이아웃으로 시작합니다:", popLayout.version); setLayout(createEmptyPopLayoutV5()); } else { console.log("[POP] 레이아웃 없음"); setLayout(createEmptyPopLayoutV5()); } } catch (layoutError) { console.warn("[POP] 레이아웃 로드 실패:", layoutError); setLayout(createEmptyPopLayoutV5()); } } catch (error) { console.error("[POP] 화면 로드 실패:", error); setError("화면을 불러오는데 실패했습니다."); toast.error("화면을 불러오는데 실패했습니다."); } finally { setLoading(false); } }; if (screenId) { loadScreen(); } }, [screenId]); const currentDevice = DEVICE_SIZES[deviceType][isLandscape ? "landscape" : "portrait"]; const hasComponents = Object.keys(layout.components).length > 0; if (loading) { return (

POP 화면 로딩 중...

); } if (error || !screen) { return (
!

화면을 찾을 수 없습니다

{error || "요청하신 POP 화면이 존재하지 않습니다."}

); } return (
{/* 상단 툴바 (프리뷰 모드에서만) */} {isPreviewMode && (
{screen.screenName} ({currentModeKey.replace("_", " ")})
{/* 자동 감지 모드 버튼 */}
)} {/* POP 화면 컨텐츠 */}
{/* 현재 모드 표시 (일반 모드) */} {!isPreviewMode && (
{currentModeKey.replace("_", " ")}
)}
{/* v5 그리드 렌더러 */} {hasComponents ? (
) : ( // 빈 화면

화면이 비어있습니다

POP 화면 디자이너에서 컴포넌트를 추가하여 화면을 구성하세요.

)}
); } // Provider 래퍼 export default function PopScreenViewPageWrapper() { return ( ); }