"use client"; import { useState } from "react"; import { useDrag } from "react-dnd"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { Plus, Settings, Type, MousePointer, List, Activity, ScanLine, Calculator, Trash2, ChevronDown, GripVertical, } from "lucide-react"; import { cn } from "@/lib/utils"; import { PopLayoutDataV3, PopLayoutModeKey, PopComponentDefinition, PopComponentType, MODE_RESOLUTIONS, } from "../types/pop-layout"; // ======================================== // 드래그 아이템 타입 // ======================================== export const DND_ITEM_TYPES = { COMPONENT: "component", } as const; export interface DragItemComponent { type: typeof DND_ITEM_TYPES.COMPONENT; componentType: PopComponentType; } // ======================================== // 컴포넌트 팔레트 정의 // ======================================== const COMPONENT_PALETTE: { type: PopComponentType; label: string; icon: React.ElementType; description: string; }[] = [ { type: "pop-field", label: "필드", icon: Type, description: "텍스트, 숫자 등 데이터 입력", }, { type: "pop-button", label: "버튼", icon: MousePointer, description: "저장, 삭제 등 액션 실행", }, { type: "pop-list", label: "리스트", icon: List, description: "데이터 목록 (카드 템플릿 지원)", }, { type: "pop-indicator", label: "인디케이터", icon: Activity, description: "KPI, 상태 표시", }, { type: "pop-scanner", label: "스캐너", icon: ScanLine, description: "바코드/QR 스캔", }, { type: "pop-numpad", label: "숫자패드", icon: Calculator, description: "숫자 입력 전용", }, ]; // ======================================== // Props (v3: 섹션 없음) // ======================================== interface PopPanelProps { layout: PopLayoutDataV3; activeModeKey: PopLayoutModeKey; selectedComponentId: string | null; selectedComponent: PopComponentDefinition | null; onUpdateComponentDefinition: (id: string, updates: Partial) => void; onDeleteComponent: (id: string) => void; activeDevice: "mobile" | "tablet"; } // ======================================== // 메인 컴포넌트 // ======================================== export function PopPanel({ layout, activeModeKey, selectedComponentId, selectedComponent, onUpdateComponentDefinition, onDeleteComponent, activeDevice, }: PopPanelProps) { const [activeTab, setActiveTab] = useState("components"); // 현재 모드의 컴포넌트 위치 const currentModeLayout = layout.layouts[activeModeKey]; const selectedComponentPosition = selectedComponentId ? currentModeLayout.componentPositions[selectedComponentId] : null; return (
컴포넌트 편집 {/* 컴포넌트 탭 */}
{/* 현재 모드 표시 */}

편집 중: {getModeLabel(activeModeKey)}

{MODE_RESOLUTIONS[activeModeKey].width} x {MODE_RESOLUTIONS[activeModeKey].height}

{/* 컴포넌트 팔레트 */}

컴포넌트

{COMPONENT_PALETTE.map((item) => ( ))}

캔버스로 드래그하여 배치

{/* 편집 탭 */} {selectedComponent && selectedComponentPosition ? ( onUpdateComponentDefinition(selectedComponent.id, updates) } onDelete={() => onDeleteComponent(selectedComponent.id)} /> ) : (
컴포넌트를 선택하세요
)}
); } // ======================================== // 모드 라벨 헬퍼 // ======================================== function getModeLabel(modeKey: PopLayoutModeKey): string { const labels: Record = { tablet_landscape: "태블릿 가로", tablet_portrait: "태블릿 세로", mobile_landscape: "모바일 가로", mobile_portrait: "모바일 세로", }; return labels[modeKey]; } // ======================================== // 드래그 가능한 컴포넌트 아이템 // ======================================== interface DraggableComponentItemProps { type: PopComponentType; label: string; icon: React.ElementType; description: string; } function DraggableComponentItem({ type, label, icon: Icon, description, }: DraggableComponentItemProps) { const [{ isDragging }, drag] = useDrag(() => ({ type: DND_ITEM_TYPES.COMPONENT, item: { type: DND_ITEM_TYPES.COMPONENT, componentType: type } as DragItemComponent, collect: (monitor) => ({ isDragging: monitor.isDragging(), }), })); return (

{label}

{description}

); } // ======================================== // v3 컴포넌트 편집기 // ======================================== interface ComponentEditorV3Props { component: PopComponentDefinition; position: { col: number; row: number; colSpan: number; rowSpan: number }; activeModeKey: PopLayoutModeKey; onUpdateDefinition: (updates: Partial) => void; onDelete: () => void; } function ComponentEditorV3({ component, position, activeModeKey, onUpdateDefinition, onDelete, }: ComponentEditorV3Props) { const [isPositionOpen, setIsPositionOpen] = useState(true); // 컴포넌트 타입 라벨 const typeLabels: Record = { "pop-field": "필드", "pop-button": "버튼", "pop-list": "리스트", "pop-indicator": "인디케이터", "pop-scanner": "스캐너", "pop-numpad": "숫자패드", }; return (
{/* 컴포넌트 기본 정보 */}
{typeLabels[component.type]}

{component.id}

{/* 라벨 */}
onUpdateDefinition({ label: e.target.value })} placeholder="컴포넌트 이름" className="h-8 text-xs" />
{/* 현재 모드 위치 (읽기 전용) */} 현재 모드 위치

{getModeLabel(activeModeKey)}

시작 열: {position.col}
시작 행: {position.row}
열 크기: {position.colSpan}
행 크기: {position.rowSpan}

위치/크기는 캔버스에서 드래그하여 조정하세요. 각 모드(가로/세로)별로 별도 저장됩니다.

{/* TODO: 컴포넌트별 설정 (config) */}

컴포넌트별 상세 설정은 추후 추가 예정

); }