"use client"; import React, { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"; import { InteractiveScreenViewerDynamic } from "@/components/screen/InteractiveScreenViewerDynamic"; import { screenApi } from "@/lib/api/screen"; import { ComponentData } from "@/types/screen"; import { toast } from "sonner"; interface ScreenModalState { isOpen: boolean; screenId: number | null; title: string; size: "sm" | "md" | "lg" | "xl"; } interface ScreenModalProps { className?: string; } export const ScreenModal: React.FC = ({ className }) => { const [modalState, setModalState] = useState({ isOpen: false, screenId: null, title: "", size: "md", }); const [screenData, setScreenData] = useState<{ components: ComponentData[]; screenInfo: any; } | null>(null); const [loading, setLoading] = useState(false); const [screenDimensions, setScreenDimensions] = useState<{ width: number; height: number; } | null>(null); // 폼 데이터 상태 추가 const [formData, setFormData] = useState>({}); // 화면의 실제 크기 계산 함수 const calculateScreenDimensions = (components: ComponentData[]) => { let maxWidth = 800; // 최소 너비 let maxHeight = 600; // 최소 높이 console.log("🔍 화면 크기 계산 시작:", { componentsCount: components.length }); components.forEach((component, index) => { // position과 size는 BaseComponent에서 별도 속성으로 관리 const x = parseFloat(component.position?.x?.toString() || "0"); const y = parseFloat(component.position?.y?.toString() || "0"); const width = parseFloat(component.size?.width?.toString() || "100"); const height = parseFloat(component.size?.height?.toString() || "40"); // 컴포넌트의 오른쪽 끝과 아래쪽 끝 계산 const rightEdge = x + width; const bottomEdge = y + height; console.log( `📏 컴포넌트 ${index + 1} (${component.id}): x=${x}, y=${y}, w=${width}, h=${height}, rightEdge=${rightEdge}, bottomEdge=${bottomEdge}`, ); const newMaxWidth = Math.max(maxWidth, rightEdge + 100); // 여백 증가 const newMaxHeight = Math.max(maxHeight, bottomEdge + 100); // 여백 증가 if (newMaxWidth > maxWidth || newMaxHeight > maxHeight) { console.log(`🔄 크기 업데이트: ${maxWidth}×${maxHeight} → ${newMaxWidth}×${newMaxHeight}`); maxWidth = newMaxWidth; maxHeight = newMaxHeight; } }); console.log("📊 컴포넌트 기반 계산 결과:", { maxWidth, maxHeight }); // 브라우저 크기 제한 확인 (더욱 관대하게 설정) const maxAllowedWidth = window.innerWidth * 0.98; // 95% -> 98% const maxAllowedHeight = window.innerHeight * 0.95; // 90% -> 95% console.log("📐 크기 제한 정보:", { 계산된크기: { maxWidth, maxHeight }, 브라우저제한: { maxAllowedWidth, maxAllowedHeight }, 브라우저크기: { width: window.innerWidth, height: window.innerHeight }, }); // 컴포넌트 기반 크기를 우선 적용하되, 브라우저 제한을 고려 const finalDimensions = { width: Math.min(maxWidth, maxAllowedWidth), height: Math.min(maxHeight, maxAllowedHeight), }; console.log("✅ 최종 화면 크기:", finalDimensions); console.log("🔧 크기 적용 분석:", { width적용: maxWidth <= maxAllowedWidth ? "컴포넌트기준" : "브라우저제한", height적용: maxHeight <= maxAllowedHeight ? "컴포넌트기준" : "브라우저제한", 컴포넌트크기: { maxWidth, maxHeight }, 최종크기: finalDimensions, }); return finalDimensions; }; // 전역 모달 이벤트 리스너 useEffect(() => { const handleOpenModal = (event: CustomEvent) => { const { screenId, title, size } = event.detail; setModalState({ isOpen: true, screenId, title, size, }); }; window.addEventListener("openScreenModal", handleOpenModal as EventListener); return () => { window.removeEventListener("openScreenModal", handleOpenModal as EventListener); }; }, []); // 화면 데이터 로딩 useEffect(() => { if (modalState.isOpen && modalState.screenId) { loadScreenData(modalState.screenId); } }, [modalState.isOpen, modalState.screenId]); const loadScreenData = async (screenId: number) => { try { setLoading(true); console.log("화면 데이터 로딩 시작:", screenId); // 화면 정보와 레이아웃 데이터 로딩 const [screenInfo, layoutData] = await Promise.all([ screenApi.getScreen(screenId), screenApi.getLayout(screenId), ]); console.log("API 응답:", { screenInfo, layoutData }); // screenApi는 직접 데이터를 반환하므로 .success 체크 불필요 if (screenInfo && layoutData) { const components = layoutData.components || []; // 화면의 실제 크기 계산 const dimensions = calculateScreenDimensions(components); setScreenDimensions(dimensions); setScreenData({ components, screenInfo: screenInfo, }); console.log("화면 데이터 설정 완료:", { componentsCount: components.length, dimensions, screenInfo, }); } else { throw new Error("화면 데이터가 없습니다"); } } catch (error) { console.error("화면 데이터 로딩 오류:", error); toast.error("화면을 불러오는 중 오류가 발생했습니다."); handleClose(); } finally { setLoading(false); } }; const handleClose = () => { setModalState({ isOpen: false, screenId: null, title: "", size: "md", }); setScreenData(null); setFormData({}); // 폼 데이터 초기화 }; // 모달 크기 설정 - 화면 내용에 맞게 동적 조정 const getModalStyle = () => { if (!screenDimensions) { return { className: "w-fit min-w-[400px] max-w-4xl max-h-[80vh] overflow-hidden", style: {}, }; } // 헤더 높이와 패딩을 고려한 전체 높이 계산 (실제 측정값 기반) const headerHeight = 80; // DialogHeader + 패딩 (더 정확한 값) const totalHeight = screenDimensions.height + headerHeight; return { className: "overflow-hidden p-0", style: { width: `${Math.min(screenDimensions.width + 48, window.innerWidth * 0.98)}px`, // 브라우저 제한 적용 height: `${Math.min(totalHeight, window.innerHeight * 0.95)}px`, // 브라우저 제한 적용 maxWidth: "98vw", // 안전장치 maxHeight: "95vh", // 안전장치 }, }; }; const modalStyle = getModalStyle(); return ( {modalState.title} {loading ? "화면을 불러오는 중입니다..." : "화면 내용을 표시합니다."}
{loading ? (

화면을 불러오는 중...

) : screenData ? (
{screenData.components.map((component) => ( { console.log(`🎯 ScreenModal onFormDataChange 호출: ${fieldName} = "${value}"`); console.log("📋 현재 formData:", formData); setFormData((prev) => { const newFormData = { ...prev, [fieldName]: value, }; console.log("📝 ScreenModal 업데이트된 formData:", newFormData); return newFormData; }); }} screenInfo={{ id: modalState.screenId!, tableName: screenData.screenInfo?.tableName, }} /> ))}
) : (

화면 데이터가 없습니다.

)}
); }; export default ScreenModal;