"use client"; /** * Modal 메타 컴포넌트 렌더러 * - 트리거: shadcn Button (config.triggerLabel) * - 모달: shadcn Dialog * - 모달 내용: 간단한 폼 구조 (config.content.fields → Label + Input) * - 저장/취소 버튼 (DialogFooter) * - 디자인 모드: 트리거 버튼만 비활성 표시 */ import React, { useState } from "react"; import { cn } from "@/lib/utils"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; interface ModalField { columnName: string; label: string; type?: "text" | "number" | "date" | "textarea"; } interface ModalRendererProps { id: string; config: { triggerLabel?: string; title?: string; description?: string; content: { fields: ModalField[]; }; size?: "sm" | "md" | "lg" | "xl"; }; isDesignMode?: boolean; disabled?: boolean; className?: string; } export function ModalRenderer({ id, config, isDesignMode = false, disabled = false, className, }: ModalRendererProps) { const { triggerLabel = "모달 열기", title = "모달", description, content, size = "md", } = config; const [isOpen, setIsOpen] = useState(false); const [formData, setFormData] = useState>({}); // 모달 크기 매핑 const sizeClass = { sm: "sm:max-w-[400px]", md: "sm:max-w-[500px]", lg: "sm:max-w-[700px]", xl: "sm:max-w-[900px]", }[size]; const handleOpen = () => { if (isDesignMode || disabled) return; setIsOpen(true); }; const handleClose = () => { setIsOpen(false); setFormData({}); }; const handleSave = () => { // TODO: 실제 저장 로직 (API 호출) console.log("Modal save:", formData); handleClose(); }; const handleFieldChange = (columnName: string, value: any) => { setFormData((prev) => ({ ...prev, [columnName]: value })); }; return ( <> {/* 트리거 버튼 */} {/* 모달 */} {title} {description && ( {description} )} {/* 폼 필드들 */}
{content.fields.map((field) => (
{field.type === "textarea" ? (