"use client"; import React, { useState, useMemo } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { ComponentRegistry } from "@/lib/registry/ComponentRegistry"; import { ComponentDefinition, ComponentCategory } from "@/types/component"; import { Search, Package, Grid, Layers, Palette, Zap, RotateCcw } from "lucide-react"; interface ComponentsPanelProps { className?: string; } export function ComponentsPanel({ className }: ComponentsPanelProps) { const [searchQuery, setSearchQuery] = useState(""); const [selectedCategory, setSelectedCategory] = useState("all"); // 레지스트리에서 모든 컴포넌트 조회 const allComponents = useMemo(() => { const components = ComponentRegistry.getAllComponents(); console.log("🔍 ComponentsPanel - 로드된 컴포넌트:", components.map(c => ({ id: c.id, name: c.name, category: c.category }))); // 수동으로 table-list 컴포넌트 추가 (임시) const hasTableList = components.some(c => c.id === 'table-list'); if (!hasTableList) { console.log("⚠️ table-list 컴포넌트가 없어서 수동 추가"); components.push({ id: "table-list", name: "테이블 리스트", nameEng: "TableList Component", description: "데이터베이스 테이블의 데이터를 목록으로 표시하는 컴포넌트", category: "display", webType: "text", defaultConfig: {}, defaultSize: { width: 800, height: 400 }, icon: "Table", tags: ["테이블", "데이터", "목록", "그리드"], version: "1.0.0", author: "개발팀", }); } return components; }, []); // 카테고리별 분류 (input 카테고리 제외) const componentsByCategory = useMemo(() => { // input 카테고리 컴포넌트들을 제외한 컴포넌트만 필터링 const filteredComponents = allComponents.filter((component) => component.category !== "input"); const categories: Record = { all: filteredComponents, // input 카테고리 제외된 컴포넌트들만 포함 input: [], // 빈 배열로 유지 (사용되지 않음) display: [], action: [], layout: [], utility: [], }; filteredComponents.forEach((component) => { if (categories[component.category]) { categories[component.category].push(component); } }); return categories; }, [allComponents]); // 검색 및 필터링된 컴포넌트 const filteredComponents = useMemo(() => { let components = componentsByCategory[selectedCategory] || []; if (searchQuery.trim()) { const query = searchQuery.toLowerCase(); components = components.filter( (component) => component.name.toLowerCase().includes(query) || component.description.toLowerCase().includes(query) || component.tags?.some((tag) => tag.toLowerCase().includes(query)), ); } return components; }, [componentsByCategory, selectedCategory, searchQuery]); // 드래그 시작 핸들러 const handleDragStart = (e: React.DragEvent, component: ComponentDefinition) => { const dragData = { type: "component", component: component, }; console.log("🚀 컴포넌트 드래그 시작:", component.name, dragData); e.dataTransfer.setData("application/json", JSON.stringify(dragData)); e.dataTransfer.effectAllowed = "copy"; }; // 카테고리별 아이콘 const getCategoryIcon = (category: ComponentCategory | "all") => { switch (category) { case "input": return ; case "display": return ; case "action": return ; case "layout": return ; case "utility": return ; default: return ; } }; // 컴포넌트 새로고침 const handleRefresh = () => { // Hot Reload 트리거 (개발 모드에서만) if (process.env.NODE_ENV === "development") { ComponentRegistry.refreshComponents?.(); } window.location.reload(); }; return (
컴포넌트 ({componentsByCategory.all.length})
{/* 검색창 */}
setSearchQuery(e.target.value)} className="pl-8" />
setSelectedCategory(value as ComponentCategory | "all")} > {/* 카테고리 탭 (input 카테고리 제외) */} 전체 표시 액션 레이아웃 유틸 {/* 컴포넌트 목록 */}
{filteredComponents.length > 0 ? (
{filteredComponents.map((component) => (
handleDragStart(e, component)} className="hover:bg-accent flex cursor-grab items-center rounded-lg border p-3 transition-colors active:cursor-grabbing" title={component.description} >

{component.name}

{/* 카테고리 뱃지 */} {getCategoryIcon(component.category)} {component.category} {/* 새 컴포넌트 뱃지 */} 신규

{component.description}

{/* 웹타입 및 크기 정보 */}
웹타입: {component.webType} {component.defaultSize.width}×{component.defaultSize.height}
{/* 태그 */} {component.tags && component.tags.length > 0 && (
{component.tags.slice(0, 3).map((tag, index) => ( {tag} ))} {component.tags.length > 3 && ( +{component.tags.length - 3} )}
)}
))}
) : (

{searchQuery ? `"${searchQuery}"에 대한 검색 결과가 없습니다.` : "이 카테고리에 컴포넌트가 없습니다."}

)}
{/* 통계 정보 */}
{filteredComponents.length}
표시된 컴포넌트
{allComponents.length}
전체 컴포넌트
{/* 개발 정보 (개발 모드에서만) */} {process.env.NODE_ENV === "development" && (
🔧 레지스트리 기반 시스템
⚡ Hot Reload 지원
🛡️ 완전한 타입 안전성
)}
); } export default ComponentsPanel;