import React, { useState, useMemo } from "react"; import { useLayer } from "@/contexts/LayerContext"; import { Button } from "@/components/ui/button"; import { ScrollArea } from "@/components/ui/scroll-area"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, DropdownMenuSeparator, } from "@/components/ui/dropdown-menu"; import { Badge } from "@/components/ui/badge"; import { Eye, EyeOff, Lock, Unlock, Plus, Trash2, GripVertical, Layers, SplitSquareVertical, PanelRight, ChevronDown, Settings2, } from "lucide-react"; import { cn } from "@/lib/utils"; import { LayerType, LayerDefinition, ComponentData } from "@/types/screen-management"; // 레이어 타입별 아이콘 const getLayerTypeIcon = (type: LayerType) => { switch (type) { case "base": return ; case "conditional": return ; case "modal": return ; case "drawer": return ; default: return ; } }; // 레이어 타입별 라벨 function getLayerTypeLabel(type: LayerType): string { switch (type) { case "base": return "기본"; case "conditional": return "조건부"; case "modal": return "모달"; case "drawer": return "드로어"; default: return type; } } // 레이어 타입별 색상 function getLayerTypeColor(type: LayerType): string { switch (type) { case "base": return "bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300"; case "conditional": return "bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300"; case "modal": return "bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300"; case "drawer": return "bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300"; default: return "bg-gray-100 text-gray-700 dark:bg-gray-900 dark:text-gray-300"; } } interface LayerItemProps { layer: LayerDefinition; isActive: boolean; componentCount: number; // 🆕 실제 컴포넌트 수 (layout.components 기반) onSelect: () => void; onToggleVisibility: () => void; onToggleLock: () => void; onRemove: () => void; onUpdateName: (name: string) => void; } const LayerItem: React.FC = ({ layer, isActive, componentCount, onSelect, onToggleVisibility, onToggleLock, onRemove, onUpdateName, }) => { const [isEditing, setIsEditing] = useState(false); return ( {/* 드래그 핸들 */} {/* 레이어 정보 */} {/* 레이어 타입 아이콘 */} {getLayerTypeIcon(layer.type)} {/* 레이어 이름 */} {isEditing ? ( onUpdateName(e.target.value)} onBlur={() => setIsEditing(false)} onKeyDown={(e) => { if (e.key === "Enter") setIsEditing(false); }} className="flex-1 bg-transparent outline-none border-b border-primary text-sm" autoFocus onClick={(e) => e.stopPropagation()} /> ) : ( { e.stopPropagation(); setIsEditing(true); }} > {layer.name} )} {/* 레이어 메타 정보 */} {getLayerTypeLabel(layer.type)} {componentCount}개 컴포넌트 {/* 액션 버튼들 */} { e.stopPropagation(); onToggleVisibility(); }} > {layer.isVisible ? ( ) : ( )} { e.stopPropagation(); onToggleLock(); }} > {layer.isLocked ? ( ) : ( )} {layer.type !== "base" && ( { e.stopPropagation(); onRemove(); }} > )} ); }; interface LayerManagerPanelProps { components?: ComponentData[]; // layout.components를 전달받음 } export const LayerManagerPanel: React.FC = ({ components = [] }) => { const { layers, activeLayerId, setActiveLayerId, addLayer, removeLayer, toggleLayerVisibility, toggleLayerLock, updateLayer, } = useLayer(); // 🆕 각 레이어별 컴포넌트 수 계산 (layout.components 기반) const componentCountByLayer = useMemo(() => { const counts: Record = {}; // 모든 레이어를 0으로 초기화 layers.forEach(layer => { counts[layer.id] = 0; }); // layout.components에서 layerId별로 카운트 components.forEach(comp => { const layerId = comp.layerId || "default-layer"; if (counts[layerId] !== undefined) { counts[layerId]++; } else { // layerId가 존재하지 않는 레이어인 경우 default-layer로 카운트 if (counts["default-layer"] !== undefined) { counts["default-layer"]++; } } }); return counts; }, [components, layers]); return ( {/* 헤더 */} 레이어 {layers.length} {/* 레이어 추가 드롭다운 */} addLayer("conditional", "조건부 레이어")}> 조건부 레이어 addLayer("modal", "모달 레이어")}> 모달 레이어 addLayer("drawer", "드로어 레이어")}> 드로어 레이어 {/* 레이어 목록 */} {layers.length === 0 ? ( 레이어가 없습니다. 위의 + 버튼으로 추가하세요. ) : ( layers .slice() .reverse() // 상위 레이어가 위에 표시 .map((layer) => ( setActiveLayerId(layer.id)} onToggleVisibility={() => toggleLayerVisibility(layer.id)} onToggleLock={() => toggleLayerLock(layer.id)} onRemove={() => removeLayer(layer.id)} onUpdateName={(name) => updateLayer(layer.id, { name })} /> )) )} {/* 도움말 */} 더블클릭: 이름 편집 | 드래그: 순서 변경 ); };
더블클릭: 이름 편집 | 드래그: 순서 변경