"use client"; import React, { useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Mail, Type, Image as ImageIcon, Square, MousePointer, Eye, Send, Save, Plus, Trash2, Settings } from "lucide-react"; export interface MailComponent { id: string; type: "text" | "button" | "image" | "spacer" | "table"; content?: string; text?: string; url?: string; src?: string; height?: number; styles?: Record; } export interface QueryConfig { id: string; name: string; sql: string; parameters: Array<{ name: string; type: string; value?: any; }>; } interface MailDesignerProps { templateId?: string; onSave?: (data: any) => void; onPreview?: (data: any) => void; onSend?: (data: any) => void; } export default function MailDesigner({ templateId, onSave, onPreview, onSend, }: MailDesignerProps) { const [components, setComponents] = useState([]); const [selectedComponent, setSelectedComponent] = useState(null); const [templateName, setTemplateName] = useState(""); const [subject, setSubject] = useState(""); const [queries, setQueries] = useState([]); // 컴포넌트 타입 정의 const componentTypes = [ { type: "text", icon: Type, label: "텍스트", color: "bg-blue-100 hover:bg-blue-200" }, { type: "button", icon: MousePointer, label: "버튼", color: "bg-green-100 hover:bg-green-200" }, { type: "image", icon: ImageIcon, label: "이미지", color: "bg-purple-100 hover:bg-purple-200" }, { type: "spacer", icon: Square, label: "여백", color: "bg-gray-100 hover:bg-gray-200" }, ]; // 컴포넌트 추가 const addComponent = (type: string) => { const newComponent: MailComponent = { id: `comp-${Date.now()}`, type: type as any, content: type === "text" ? "

텍스트를 입력하세요...

" : undefined, text: type === "button" ? "버튼" : undefined, url: type === "button" || type === "image" ? "https://example.com" : undefined, src: type === "image" ? "https://placehold.co/600x200/e5e7eb/64748b?text=Image" : undefined, height: type === "spacer" ? 20 : undefined, styles: { padding: "10px", backgroundColor: type === "button" ? "#007bff" : "transparent", color: type === "button" ? "#fff" : "#333", }, }; setComponents([...components, newComponent]); }; // 컴포넌트 삭제 const removeComponent = (id: string) => { setComponents(components.filter(c => c.id !== id)); if (selectedComponent === id) { setSelectedComponent(null); } }; // 컴포넌트 선택 const selectComponent = (id: string) => { setSelectedComponent(id); }; // 컴포넌트 내용 업데이트 const updateComponent = (id: string, updates: Partial) => { setComponents( components.map(c => c.id === id ? { ...c, ...updates } : c) ); }; // 저장 const handleSave = () => { const data = { name: templateName, subject, components, queries, }; if (onSave) { onSave(data); } }; // 미리보기 const handlePreview = () => { if (onPreview) { onPreview({ components, subject }); } }; // 발송 const handleSend = () => { if (onSend) { onSend({ components, subject, queries }); } }; // 선택된 컴포넌트 가져오기 const selected = components.find(c => c.id === selectedComponent); return (
{/* 왼쪽: 컴포넌트 팔레트 */}

컴포넌트

{componentTypes.map(({ type, icon: Icon, label, color }) => ( ))}
{/* 템플릿 정보 */} 템플릿 정보
setTemplateName(e.target.value)} placeholder="예: 고객 환영 메일" className="mt-1" />
setSubject(e.target.value)} placeholder="예: {customer_name}님 환영합니다!" className="mt-1" />
{/* 액션 버튼 */}
{/* 중앙: 캔버스 */}
메일 미리보기 {components.length}개 컴포넌트 {/* 제목 영역 */} {subject && (

제목:

{subject}

)} {/* 컴포넌트 렌더링 */}
{components.length === 0 ? (

왼쪽에서 컴포넌트를 추가하세요

) : ( components.map((comp) => (
selectComponent(comp.id)} className={`relative group cursor-pointer rounded-lg transition-all ${ selectedComponent === comp.id ? "ring-2 ring-orange-500 bg-orange-50/30" : "hover:ring-2 hover:ring-gray-300" }`} style={comp.styles} > {/* 삭제 버튼 */} {/* 컴포넌트 내용 */} {comp.type === "text" && (
)} {comp.type === "button" && ( {comp.text} )} {comp.type === "image" && ( 메일 이미지 )} {comp.type === "spacer" && (
)}
)) )}
{/* 오른쪽: 속성 패널 */}
{selected ? (

속성 편집

{/* 텍스트 컴포넌트 */} {selected.type === "text" && (