"use client"; import React, { useState, useEffect, useRef } from "react"; import { ComponentRendererProps } from "../../types"; import { V2WebViewConfig } from "./types"; import { filterDOMProps } from "@/lib/utils/domPropsFilter"; export interface V2WebViewComponentProps extends ComponentRendererProps {} export const V2WebViewComponent: React.FC = ({ component, isDesignMode = false, isSelected = false, onClick, ...props }) => { const config = (component.componentConfig || {}) as V2WebViewConfig; const [iframeSrc, setIframeSrc] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const iframeRef = useRef(null); const baseUrl = config.url ?? ""; useEffect(() => { if (!baseUrl) { setIframeSrc(null); return; } if (!config.useSSO) { setIframeSrc(baseUrl); return; } let cancelled = false; setLoading(true); setError(null); const paramName = "sso_token"; fetch("/api/system/raw-token") .then((r) => r.json()) .then((data) => { if (cancelled) return; if (data.token) { const separator = baseUrl.includes("?") ? "&" : "?"; setIframeSrc(`${baseUrl}${separator}${encodeURIComponent(paramName)}=${encodeURIComponent(data.token)}`); } else { setError(data.error ?? "토큰을 가져올 수 없습니다"); } }) .catch(() => { if (!cancelled) setError("토큰 조회 실패"); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [baseUrl, config.useSSO]); const containerStyle: React.CSSProperties = { position: "absolute", left: `${component.style?.positionX || 0}px`, top: `${component.style?.positionY || 0}px`, width: `${component.style?.width || 400}px`, height: `${component.style?.height || 300}px`, zIndex: component.style?.positionZ || 1, cursor: isDesignMode ? "pointer" : "default", border: isSelected ? "2px solid #3b82f6" : config.showBorder ? "1px solid #e0e0e0" : "none", borderRadius: config.borderRadius || "8px", overflow: "hidden", background: "#fafafa", }; const handleClick = (e: React.MouseEvent) => { if (isDesignMode) { e.stopPropagation(); onClick?.(e); } }; const domProps = filterDOMProps(props); // 디자인 모드: URL 미리보기 표시 if (isDesignMode) { return (
웹 뷰 {baseUrl ? ( {baseUrl} ) : ( URL을 설정하세요 )} {config.useSSO && SSO: ?sso_token=JWT}
); } // 런타임 모드 return (
{loading && (
{config.loadingText || "로딩 중..."}
)} {error && (
{error}
)} {!loading && !error && iframeSrc && (