"use client"; import React, { useState, useEffect } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Inbox, Search, Filter, Eye, Trash2, RefreshCw, CheckCircle2, XCircle, Mail, Calendar, User, Paperclip, Loader2, X, File, LayoutDashboard, } from "lucide-react"; import { useRouter } from "next/navigation"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { SentMailHistory, getSentMailList, deleteSentMail, getMailAccounts, MailAccount, } from "@/lib/api/mail"; import { useToast } from "@/hooks/use-toast"; export default function SentMailPage() { const router = useRouter(); const { toast } = useToast(); const [mails, setMails] = useState([]); const [accounts, setAccounts] = useState([]); const [loading, setLoading] = useState(false); const [selectedMail, setSelectedMail] = useState(null); // 필터 및 페이징 const [searchTerm, setSearchTerm] = useState(""); const [filterStatus, setFilterStatus] = useState<'all' | 'success' | 'failed'>('all'); const [filterAccountId, setFilterAccountId] = useState('all'); const [sortBy, setSortBy] = useState<'sentAt' | 'subject'>('sentAt'); const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc'); const [page, setPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [total, setTotal] = useState(0); useEffect(() => { loadAccounts(); loadMails(); }, [page, filterStatus, filterAccountId, sortBy, sortOrder]); const loadAccounts = async () => { try { const data = await getMailAccounts(); setAccounts(data); } catch (error: unknown) { const err = error as Error; toast({ title: "계정 로드 실패", description: err.message, variant: "destructive", }); } }; const loadMails = async () => { try { setLoading(true); const result = await getSentMailList({ page, limit: 20, searchTerm: searchTerm || undefined, status: filterStatus, accountId: filterAccountId !== 'all' ? filterAccountId : undefined, sortBy, sortOrder, }); setMails(result.items); setTotalPages(result.totalPages); setTotal(result.total); } catch (error: unknown) { const err = error as Error; toast({ title: "발송 이력 로드 실패", description: err.message, variant: "destructive", }); } finally { setLoading(false); } }; const handleSearch = () => { setPage(1); loadMails(); }; const handleDelete = async (id: string) => { if (!confirm("이 발송 이력을 삭제하시겠습니까?")) { return; } try { await deleteSentMail(id); toast({ title: "삭제 완료", description: "발송 이력이 삭제되었습니다.", }); loadMails(); } catch (error: unknown) { const err = error as Error; toast({ title: "삭제 실패", description: err.message, variant: "destructive", }); } }; const formatDate = (dateString: string) => { const date = new Date(dateString); return date.toLocaleString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }); }; const formatFileSize = (bytes: number) => { if (bytes === 0) return "0 Bytes"; const k = 1024; const sizes = ["Bytes", "KB", "MB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i]; }; if (loading && page === 1) { return (
); } return (
{/* 헤더 */}

보낸메일함

발송된 메일의 이력을 확인하고 관리하세요

{/* 필터 및 검색 */} 필터 및 검색
{/* 검색 */}
setSearchTerm(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} placeholder="제목 또는 받는사람 검색..." />
{/* 상태 필터 */}
{/* 계정 필터 */}
{/* 메일 목록 */} 발송 이력 ({total}건) {mails.length === 0 ? (

발송된 메일이 없습니다

) : (
{mails.map((mail) => (
{mail.status === 'success' ? ( ) : ( )}

{mail.subject}

{mail.attachments && mail.attachments.length > 0 && ( )}
{mail.accountName}
받는사람: {mail.to.length}명 {mail.cc && mail.cc.length > 0 && ( (참조 {mail.cc.length}명) )}
{formatDate(mail.sentAt)}
{mail.status === 'failed' && mail.errorMessage && (
오류: {mail.errorMessage}
)}
))}
)} {/* 페이징 */} {totalPages > 1 && (
{page} / {totalPages}
)}
{/* 상세보기 모달 */} !open && setSelectedMail(null)}>
{selectedMail?.status === 'success' ? ( ) : ( )} 발송 상세 정보
{selectedMail && (
{/* 발송 정보 */} 발송 정보

{selectedMail.accountName} ({selectedMail.accountEmail})

{formatDate(selectedMail.sentAt)}

{selectedMail.status === 'success' ? ( 발송 성공 ) : ( 발송 실패 )}
{selectedMail.messageId && (

{selectedMail.messageId}

)} {selectedMail.errorMessage && (

{selectedMail.errorMessage}

)}
{/* 수신자 정보 */} 수신자 정보
{selectedMail.to.map((email, i) => ( {email} ))}
{selectedMail.cc && selectedMail.cc.length > 0 && (
{selectedMail.cc.map((email, i) => ( {email} ))}
)} {selectedMail.bcc && selectedMail.bcc.length > 0 && (
{selectedMail.bcc.map((email, i) => ( {email} ))}
)} {selectedMail.accepted && selectedMail.accepted.length > 0 && (

{selectedMail.accepted.join(", ")}

)} {selectedMail.rejected && selectedMail.rejected.length > 0 && (

{selectedMail.rejected.join(", ")}

)}
{/* 메일 내용 */} 메일 내용

{selectedMail.subject}

{selectedMail.templateName && (

{selectedMail.templateName}

)}
{/* 첨부파일 */} {selectedMail.attachments && selectedMail.attachments.length > 0 && ( 첨부파일 ({selectedMail.attachments.length})
{selectedMail.attachments.map((file, i) => (

{file.originalName}

{formatFileSize(file.size)} • {file.mimetype}

))}
)}
)}
); }