2025-11-14 17:40:07 +09:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
|
|
|
import { ConditionalSectionViewerProps } from "./types";
|
|
|
|
|
import { InteractiveScreenViewer } from "@/components/screen/InteractiveScreenViewer";
|
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
|
import { Loader2 } from "lucide-react";
|
2025-11-14 18:20:52 +09:00
|
|
|
import { screenApi } from "@/lib/api/screen";
|
|
|
|
|
import { ComponentData } from "@/types/screen";
|
2025-11-14 17:40:07 +09:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 조건부 섹션 뷰어 컴포넌트
|
|
|
|
|
* 각 조건에 해당하는 화면을 표시
|
|
|
|
|
*/
|
|
|
|
|
export function ConditionalSectionViewer({
|
|
|
|
|
sectionId,
|
|
|
|
|
condition,
|
|
|
|
|
label,
|
|
|
|
|
screenId,
|
|
|
|
|
screenName,
|
|
|
|
|
isActive,
|
|
|
|
|
isDesignMode,
|
|
|
|
|
showBorder = true,
|
|
|
|
|
formData,
|
|
|
|
|
onFormDataChange,
|
|
|
|
|
}: ConditionalSectionViewerProps) {
|
|
|
|
|
const [isLoading, setIsLoading] = useState(false);
|
2025-11-14 18:20:52 +09:00
|
|
|
const [components, setComponents] = useState<ComponentData[]>([]);
|
|
|
|
|
const [screenInfo, setScreenInfo] = useState<{ id: number; tableName?: string } | null>(null);
|
|
|
|
|
|
|
|
|
|
// 화면 로드
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!screenId) {
|
|
|
|
|
setComponents([]);
|
|
|
|
|
setScreenInfo(null);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const loadScreen = async () => {
|
|
|
|
|
setIsLoading(true);
|
|
|
|
|
try {
|
|
|
|
|
const [layout, screen] = await Promise.all([
|
|
|
|
|
screenApi.getLayout(screenId),
|
|
|
|
|
screenApi.getScreen(screenId),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
setComponents(layout.components || []);
|
|
|
|
|
setScreenInfo({
|
|
|
|
|
id: screenId,
|
|
|
|
|
tableName: screen.tableName,
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("화면 로드 실패:", error);
|
|
|
|
|
setComponents([]);
|
|
|
|
|
setScreenInfo(null);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
loadScreen();
|
|
|
|
|
}, [screenId]);
|
2025-11-14 17:40:07 +09:00
|
|
|
|
|
|
|
|
// 디자인 모드가 아니고 비활성 섹션이면 렌더링하지 않음
|
|
|
|
|
if (!isDesignMode && !isActive) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={cn(
|
|
|
|
|
"relative min-h-[200px] transition-all",
|
|
|
|
|
showBorder && "rounded-lg border-2",
|
|
|
|
|
isDesignMode ? (
|
|
|
|
|
"border-dashed border-muted-foreground/30 bg-muted/20"
|
|
|
|
|
) : (
|
|
|
|
|
showBorder ? "border-border bg-card" : ""
|
|
|
|
|
),
|
|
|
|
|
!isDesignMode && !isActive && "hidden"
|
|
|
|
|
)}
|
|
|
|
|
data-section-id={sectionId}
|
|
|
|
|
>
|
|
|
|
|
{/* 섹션 라벨 (디자인 모드에서만 표시) */}
|
|
|
|
|
{isDesignMode && (
|
|
|
|
|
<div className="absolute -top-3 left-4 bg-background px-2 text-xs font-medium text-muted-foreground z-10">
|
|
|
|
|
{label} {isActive && "(활성)"}
|
|
|
|
|
{screenId && ` - 화면 ID: ${screenId}`}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* 화면 미선택 안내 (디자인 모드 + 화면 없을 때) */}
|
|
|
|
|
{isDesignMode && !screenId && (
|
|
|
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
|
|
|
<div className="text-center text-muted-foreground">
|
|
|
|
|
<p className="text-sm">설정 패널에서 화면을 선택하세요</p>
|
|
|
|
|
<p className="text-xs mt-1">조건: {condition}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* 로딩 중 */}
|
|
|
|
|
{isLoading && (
|
|
|
|
|
<div className="absolute inset-0 flex items-center justify-center bg-background/50 z-20">
|
|
|
|
|
<div className="flex flex-col items-center gap-2">
|
|
|
|
|
<Loader2 className="h-6 w-6 animate-spin text-primary" />
|
|
|
|
|
<p className="text-xs text-muted-foreground">화면 로드 중...</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* 화면 렌더링 */}
|
2025-11-14 18:20:52 +09:00
|
|
|
{screenId && components.length > 0 && (
|
|
|
|
|
<div className="relative min-h-[200px] w-full">
|
|
|
|
|
{components.map((component) => (
|
|
|
|
|
<InteractiveScreenViewer
|
|
|
|
|
key={component.id}
|
|
|
|
|
component={component}
|
|
|
|
|
allComponents={components}
|
|
|
|
|
formData={formData}
|
|
|
|
|
onFormDataChange={onFormDataChange}
|
|
|
|
|
hideLabel={false}
|
|
|
|
|
screenInfo={screenInfo || undefined}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
2025-11-14 17:40:07 +09:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|