"use client"; import React, { useState, useEffect } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Plus, FileText, Loader2, RefreshCw, Search, LayoutDashboard } from "lucide-react"; import { useRouter } from "next/navigation"; import { MailTemplate, getMailTemplates, createMailTemplate, updateMailTemplate, deleteMailTemplate, CreateMailTemplateDto, UpdateMailTemplateDto, } from "@/lib/api/mail"; import MailTemplateCard from "@/components/mail/MailTemplateCard"; import MailTemplatePreviewModal from "@/components/mail/MailTemplatePreviewModal"; import MailTemplateEditorModal from "@/components/mail/MailTemplateEditorModal"; import ConfirmDeleteModal from "@/components/mail/ConfirmDeleteModal"; export default function MailTemplatesPage() { const router = useRouter(); const [templates, setTemplates] = useState([]); const [loading, setLoading] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [categoryFilter, setCategoryFilter] = useState('all'); // 모달 상태 const [isEditorOpen, setIsEditorOpen] = useState(false); const [isPreviewOpen, setIsPreviewOpen] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [selectedTemplate, setSelectedTemplate] = useState(null); const [editorMode, setEditorMode] = useState<'create' | 'edit'>('create'); // 템플릿 목록 불러오기 const loadTemplates = async () => { setLoading(true); try { const data = await getMailTemplates(); setTemplates(data); } catch (error) { console.error('템플릿 로드 실패:', error); alert('템플릿 목록을 불러오는데 실패했습니다.'); } finally { setLoading(false); } }; useEffect(() => { loadTemplates(); }, []); // 필터링된 템플릿 const filteredTemplates = templates.filter((template) => { const matchesSearch = template.name.toLowerCase().includes(searchTerm.toLowerCase()) || template.subject.toLowerCase().includes(searchTerm.toLowerCase()); const matchesCategory = categoryFilter === 'all' || template.category === categoryFilter; return matchesSearch && matchesCategory; }); // 카테고리 목록 추출 const categories = Array.from(new Set(templates.map((t) => t.category).filter(Boolean))); const handleOpenCreateModal = () => { setEditorMode('create'); setSelectedTemplate(null); setIsEditorOpen(true); }; const handleOpenEditModal = (template: MailTemplate) => { setEditorMode('edit'); setSelectedTemplate(template); setIsEditorOpen(true); }; const handleOpenPreviewModal = (template: MailTemplate) => { setSelectedTemplate(template); setIsPreviewOpen(true); }; const handleOpenDeleteModal = (template: MailTemplate) => { setSelectedTemplate(template); setIsDeleteModalOpen(true); }; const handleSaveTemplate = async (data: CreateMailTemplateDto | UpdateMailTemplateDto) => { try { if (editorMode === 'create') { await createMailTemplate(data as CreateMailTemplateDto); } else if (editorMode === 'edit' && selectedTemplate) { await updateMailTemplate(selectedTemplate.id, data as UpdateMailTemplateDto); } await loadTemplates(); setIsEditorOpen(false); } catch (error) { throw error; // 모달에서 에러 처리 } }; const handleDeleteTemplate = async () => { if (!selectedTemplate) return; try { await deleteMailTemplate(selectedTemplate.id); await loadTemplates(); alert('템플릿이 삭제되었습니다.'); } catch (error) { console.error('템플릿 삭제 실패:', error); alert('템플릿 삭제에 실패했습니다.'); } }; const handleDuplicateTemplate = async (template: MailTemplate) => { try { await createMailTemplate({ name: `${template.name} (복사본)`, subject: template.subject, components: template.components, category: template.category, }); await loadTemplates(); alert('템플릿이 복사되었습니다.'); } catch (error) { console.error('템플릿 복사 실패:', error); alert('템플릿 복사에 실패했습니다.'); } }; return (
{/* 페이지 제목 */}

메일 템플릿 관리

드래그 앤 드롭으로 메일 템플릿을 만들고 관리합니다

{/* 검색 및 필터 */}
setSearchTerm(e.target.value)} placeholder="템플릿 이름, 제목으로 검색..." className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500" />
{/* 메인 컨텐츠 */} {loading ? ( ) : filteredTemplates.length === 0 ? (

{templates.length === 0 ? '아직 생성된 템플릿이 없습니다' : '검색 결과가 없습니다'}

{templates.length === 0 && ( )}
) : (
{filteredTemplates.map((template) => ( ))}
)} {/* 안내 정보 */} 템플릿 디자이너

💡 드래그 앤 드롭으로 손쉽게 메일 템플릿을 만들 수 있어요!

  • 텍스트, 버튼, 이미지, 여백 컴포넌트 지원
  • 실시간 미리보기로 즉시 확인 가능
  • 동적 변수 지원 (예: {"{customer_name}"})
{/* 모달들 */} setIsEditorOpen(false)} onSave={handleSaveTemplate} template={selectedTemplate} mode={editorMode} /> setIsPreviewOpen(false)} template={selectedTemplate} /> setIsDeleteModalOpen(false)} onConfirm={handleDeleteTemplate} title="템플릿 삭제" message="이 템플릿을 삭제하시겠습니까?" itemName={selectedTemplate?.name} />
); }