"use client"; import React, { useEffect, useState, useMemo } from "react"; import { useParams, useSearchParams } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Loader2, ArrowLeft, Smartphone, Tablet, Monitor, RotateCcw } from "lucide-react"; import { screenApi } from "@/lib/api/screen"; import { ScreenDefinition, LayoutData, ComponentData } from "@/types/screen"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { initializeComponents } from "@/lib/registry/components"; import { DynamicComponentRenderer } from "@/lib/registry/DynamicComponentRenderer"; 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 { ScreenMultiLangProvider } from "@/contexts/ScreenMultiLangContext"; import { convertV2ToLegacy, isValidV2Layout } from "@/lib/utils/layoutV2Converter"; // POP 디바이스 타입 type DeviceType = "mobile" | "tablet"; // 디바이스별 크기 const DEVICE_SIZES = { mobile: { width: 375, height: 812, label: "모바일" }, tablet: { width: 768, height: 1024, label: "태블릿" }, }; function PopScreenViewPage() { const params = useParams(); const searchParams = useSearchParams(); const router = useRouter(); const screenId = parseInt(params.screenId as string); // URL 쿼리에서 디바이스 타입 가져오기 (기본: tablet) const deviceParam = searchParams.get("device") as DeviceType | null; const [deviceType, setDeviceType] = useState(deviceParam || "tablet"); // 프리뷰 모드 (디자이너에서 열렸을 때) const isPreviewMode = searchParams.get("preview") === "true"; // 사용자 정보 const { user, userName, companyCode } = useAuth(); const [screen, setScreen] = useState(null); const [layout, setLayout] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [formData, setFormData] = useState>({}); const [selectedRowsData, setSelectedRowsData] = useState([]); const [tableRefreshKey, setTableRefreshKey] = useState(0); // 컴포넌트 초기화 useEffect(() => { const initComponents = async () => { try { await initializeComponents(); } catch (error) { console.error("POP 화면 컴포넌트 초기화 실패:", error); } }; initComponents(); }, []); // 화면 및 POP 레이아웃 로드 useEffect(() => { const loadScreen = async () => { try { setLoading(true); setError(null); // 화면 정보 로드 const screenData = await screenApi.getScreen(screenId); setScreen(screenData); // POP 레이아웃 로드 (screen_layouts_pop 테이블에서) // POP 레이아웃은 sections[] 구조 사용 (데스크톱의 components[]와 다름) try { const popLayout = await screenApi.getLayoutPop(screenId); if (popLayout && popLayout.sections && popLayout.sections.length > 0) { // POP 레이아웃 (sections 구조) - 그대로 저장 console.log("POP 레이아웃 로드:", popLayout.sections?.length || 0, "개 섹션"); setLayout(popLayout as any); // sections 구조 그대로 사용 } else if (popLayout && popLayout.components && popLayout.components.length > 0) { // 이전 형식 (components 구조) - 호환성 유지 console.log("POP 레이아웃 로드 (이전 형식):", popLayout.components?.length || 0, "개 컴포넌트"); setLayout(popLayout as LayoutData); } else { // POP 레이아웃이 비어있으면 빈 레이아웃 console.log("POP 레이아웃 없음, 빈 화면 표시"); setLayout({ screenId, sections: [], components: [], gridSettings: { columns: 12, gap: 8, padding: 16, enabled: true, size: 8, color: "#e0e0e0", opacity: 0.5, snapToGrid: true, }, } as any); } } catch (layoutError) { console.warn("POP 레이아웃 로드 실패:", layoutError); setLayout({ screenId, sections: [], components: [], gridSettings: { columns: 12, gap: 8, padding: 16, enabled: true, size: 8, color: "#e0e0e0", opacity: 0.5, snapToGrid: true, }, } as any); } } catch (error) { console.error("POP 화면 로드 실패:", error); setError("화면을 불러오는데 실패했습니다."); toast.error("화면을 불러오는데 실패했습니다."); } finally { setLoading(false); } }; if (screenId) { loadScreen(); } }, [screenId]); // 현재 디바이스 크기 const currentDevice = DEVICE_SIZES[deviceType]; if (loading) { return (

POP 화면 로딩 중...

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

화면을 찾을 수 없습니다

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

); } return (
{/* 상단 툴바 (프리뷰 모드에서만) */} {isPreviewMode && (
{screen.screenName}
{/* 디바이스 전환 버튼 */}
)} {/* POP 화면 컨텐츠 */}
{/* POP 레이아웃: sections 구조 렌더링 */} {layout && (layout as any).sections && (layout as any).sections.length > 0 ? (
{/* 그리드 레이아웃으로 섹션 배치 */}
{(layout as any).sections.map((section: any) => (
{/* 섹션 라벨 */} {section.label && (
{section.label}
)} {/* 섹션 내 컴포넌트들 */} {section.components && section.components.length > 0 ? (
{section.components.map((comp: any) => (
{/* TODO: POP 전용 컴포넌트 렌더러 구현 필요 */} {comp.label || comp.type || comp.id}
))}
) : (
빈 섹션
)}
))}
) : layout && layout.components && layout.components.length > 0 ? ( // 이전 형식 (components 구조) - 호환성 유지
{layout.components .filter((component) => !component.parentId) .map((component) => (
{ }} screenId={screenId} tableName={screen?.tableName} userId={user?.userId} userName={userName} companyCode={companyCode} selectedRowsData={selectedRowsData} onSelectedRowsChange={(_, selectedData) => { setSelectedRowsData(selectedData); }} refreshKey={tableRefreshKey} onRefresh={() => { setTableRefreshKey((prev) => prev + 1); setSelectedRowsData([]); }} onFormDataChange={(fieldName, value) => { setFormData((prev) => ({ ...prev, [fieldName]: value })); }} />
))}
) : ( // 빈 화면

화면이 비어있습니다

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

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