"use client"; import { useEffect, useState } from "react"; import { useParams } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Loader2 } from "lucide-react"; import { screenApi } from "@/lib/api/screen"; import { ScreenDefinition, LayoutData } from "@/types/screen"; import { InteractiveScreenViewer } from "@/components/screen/InteractiveScreenViewerDynamic"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; export default function ScreenViewPage() { const params = useParams(); const router = useRouter(); const screenId = parseInt(params.screenId as string); const [screen, setScreen] = useState(null); const [layout, setLayout] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [formData, setFormData] = useState>({}); useEffect(() => { const loadScreen = async () => { try { setLoading(true); setError(null); // 화면 정보 로드 const screenData = await screenApi.getScreen(screenId); setScreen(screenData); // 레이아웃 로드 try { const layoutData = await screenApi.getLayout(screenId); setLayout(layoutData); } catch (layoutError) { console.warn("레이아웃 로드 실패, 빈 레이아웃 사용:", layoutError); setLayout({ components: [], gridSettings: { columns: 12, gap: 16, padding: 16 }, }); } } catch (error) { console.error("화면 로드 실패:", error); setError("화면을 불러오는데 실패했습니다."); toast.error("화면을 불러오는데 실패했습니다."); } finally { setLoading(false); } }; if (screenId) { loadScreen(); } }, [screenId]); if (loading) { return (

화면을 불러오는 중...

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

화면을 찾을 수 없습니다

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

); } // 화면 해상도 정보가 있으면 해당 크기로, 없으면 기본 크기 사용 const screenWidth = layout?.screenResolution?.width || 1200; const screenHeight = layout?.screenResolution?.height || 800; return (
{layout && layout.components.length > 0 ? ( // 캔버스 컴포넌트들을 정확한 해상도로 표시
{layout.components .filter((comp) => !comp.parentId) // 최상위 컴포넌트만 렌더링 (그룹 포함) .map((component) => { // 그룹 컴포넌트인 경우 특별 처리 if (component.type === "group") { const groupChildren = layout.components.filter((child) => child.parentId === component.id); return (
{/* 그룹 제목 */} {(component as any).title && (
{(component as any).title}
)} {/* 그룹 내 자식 컴포넌트들 렌더링 */} {groupChildren.map((child) => (
{ setFormData((prev) => ({ ...prev, [fieldName]: value, })); }} />
))}
); } // 라벨 표시 여부 계산 const templateTypes = ["datatable"]; const shouldShowLabel = component.style?.labelDisplay !== false && (component.label || component.style?.labelText) && !templateTypes.includes(component.type); const labelText = component.style?.labelText || component.label || ""; const labelStyle = { fontSize: component.style?.labelFontSize || "14px", color: component.style?.labelColor || "#374151", fontWeight: component.style?.labelFontWeight || "500", backgroundColor: component.style?.labelBackgroundColor || "transparent", padding: component.style?.labelPadding || "0", borderRadius: component.style?.labelBorderRadius || "0", marginBottom: component.style?.labelMarginBottom || "4px", }; // 일반 컴포넌트 렌더링 return (
{/* 라벨을 외부에 별도로 렌더링 */} {shouldShowLabel && (
{labelText} {component.required && *}
)} {/* 실제 컴포넌트 */}
{ setFormData((prev) => ({ ...prev, [fieldName]: value, })); }} hideLabel={true} // 라벨 숨김 플래그 전달 screenInfo={{ id: screenId, tableName: screen?.tableName, }} />
); })}
) : ( // 빈 화면일 때도 깔끔하게 표시
📄

화면이 비어있습니다

이 화면에는 아직 설계된 컴포넌트가 없습니다.

)}
); }