"use client"; import React, { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Grid, Layout, Navigation, Building, FileText, Table, LayoutDashboard, Plus, Minus, Info, Wand2, } from "lucide-react"; import { LayoutCategory } from "@/types/layout"; import { toast } from "sonner"; interface LayoutFormModalProps { open: boolean; onOpenChange: (open: boolean) => void; onSuccess: () => void; } // 카테고리 정의 const CATEGORIES = [ { id: "basic", name: "기본", icon: Grid, description: "그리드, 플렉스박스 등 기본 레이아웃" }, { id: "navigation", name: "네비게이션", icon: Navigation, description: "메뉴, 탭, 아코디언 등" }, { id: "business", name: "비즈니스", icon: Building, description: "대시보드, 차트, 리포트 등" }, { id: "form", name: "폼", icon: FileText, description: "입력 폼, 설정 패널 등" }, { id: "table", name: "테이블", icon: Table, description: "데이터 테이블, 목록 등" }, { id: "dashboard", name: "대시보드", icon: LayoutDashboard, description: "위젯, 카드 레이아웃 등" }, ] as const; // 레이아웃 템플릿 정의 const LAYOUT_TEMPLATES = [ { id: "2-column", name: "2열 레이아웃", description: "좌우 2개 영역으로 구성", zones: 2, example: "사이드바 + 메인 콘텐츠", icon: "▢ ▢", }, { id: "3-column", name: "3열 레이아웃", description: "좌측, 중앙, 우측 3개 영역", zones: 3, example: "네비 + 콘텐츠 + 사이드", icon: "▢ ▢ ▢", }, { id: "header-content", name: "헤더-콘텐츠", description: "상단 헤더 + 하단 콘텐츠", zones: 2, example: "제목 + 내용 영역", icon: "▬\n▢", }, { id: "card-grid", name: "카드 그리드", description: "2x2 카드 격자 구조", zones: 4, example: "대시보드, 통계 패널", icon: "▢▢\n▢▢", }, { id: "accordion", name: "아코디언", description: "접고 펼칠 수 있는 섹션들", zones: 3, example: "FAQ, 설정 패널", icon: "▷ ▽ ▷", }, { id: "tabs", name: "탭 레이아웃", description: "탭으로 구성된 다중 패널", zones: 3, example: "설정, 상세 정보", icon: "[Tab1][Tab2][Tab3]", }, ]; export const LayoutFormModal: React.FC = ({ open, onOpenChange, onSuccess }) => { const [step, setStep] = useState<"basic" | "template" | "advanced">("basic"); const [formData, setFormData] = useState({ name: "", nameEng: "", description: "", category: "" as LayoutCategory | "", zones: 2, template: "", author: "Developer", }); const [isGenerating, setIsGenerating] = useState(false); const [generationResult, setGenerationResult] = useState<{ success: boolean; message: string; files?: string[]; } | null>(null); const handleReset = () => { setStep("basic"); setFormData({ name: "", nameEng: "", description: "", category: "", zones: 2, template: "", author: "Developer", }); setGenerationResult(null); }; const handleClose = () => { handleReset(); onOpenChange(false); }; const handleNext = () => { if (step === "basic") { setStep("template"); } else if (step === "template") { setStep("advanced"); } }; const handleBack = () => { if (step === "template") { setStep("basic"); } else if (step === "advanced") { setStep("template"); } }; const validateBasic = () => { return formData.name.trim() && formData.category && formData.description.trim(); }; const validateTemplate = () => { return formData.template && formData.zones > 0; }; const generateLayout = async () => { try { setIsGenerating(true); // CLI 명령어 구성 const command = [ formData.name.toLowerCase().replace(/[^a-z0-9-]/g, "-"), `--category=${formData.category}`, `--zones=${formData.zones}`, `--description="${formData.description}"`, formData.author !== "Developer" ? `--author="${formData.author}"` : null, ] .filter(Boolean) .join(" "); // API 호출로 CLI 명령어 실행 const response = await fetch("/api/admin/layouts/generate", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ command, layoutData: formData, }), }); const result = await response.json(); if (result.success) { setGenerationResult({ success: true, message: "레이아웃이 성공적으로 생성되었습니다!", files: result.files || [], }); toast.success("레이아웃 생성 완료"); // 3초 후 자동으로 모달 닫고 새로고침 setTimeout(() => { handleClose(); onSuccess(); }, 3000); } else { setGenerationResult({ success: false, message: result.message || "레이아웃 생성에 실패했습니다.", }); toast.error("레이아웃 생성 실패"); } } catch (error) { console.error("레이아웃 생성 오류:", error); setGenerationResult({ success: false, message: "서버 오류가 발생했습니다.", }); toast.error("서버 오류"); } finally { setIsGenerating(false); } }; return ( 새 레이아웃 생성 GUI를 통해 새로운 레이아웃을 쉽게 생성할 수 있습니다. {/* 단계 표시기 */}
1
기본 정보
2
템플릿 선택
3
고급 설정
{/* 단계별 컨텐츠 */}
{step === "basic" && (
setFormData((prev) => ({ ...prev, name: e.target.value }))} />
setFormData((prev) => ({ ...prev, nameEng: e.target.value }))} />
{CATEGORIES.map((category) => { const IconComponent = category.icon; return ( setFormData((prev) => ({ ...prev, category: category.id }))} >
{category.name}
{category.description}
); })}