feat: add frontend/src/components/MailView.tsx

This commit is contained in:
zio 2026-06-01 22:13:00 +09:00
parent 3cd4ff055a
commit 03211c0260

View File

@ -0,0 +1,91 @@
import DOMPurify from 'dompurify'
import { useMailStore } from '../store/mailStore'
import { mailApi } from '../api/mailApi'
export default function MailView() {
const { selectedMail, currentFolder, openCompose } = useMailStore()
if (!selectedMail) return (
<div className="mail-view-empty">
<div className="empty-icon"></div>
<div> </div>
</div>
)
const m = selectedMail
const cleanHtml = m.body_html
? DOMPurify.sanitize(m.body_html, { FORBID_TAGS: ['script', 'iframe', 'object'] })
: null
const reply = () => openCompose(m)
const forward = () => openCompose({ ...m, subject: `Fw: ${m.subject}`, to: '', uid: '' } as any)
return (
<div className="mail-view">
<div className="mail-view-header">
<h2 className="mail-subject">{m.subject}</h2>
<div className="mail-meta">
<div className="mail-from">
<span className="meta-label"></span>
<span>{m.sender} &lt;{m.sender_addr}&gt;</span>
</div>
<div className="mail-to">
<span className="meta-label"></span>
<span>{m.to}</span>
</div>
{m.cc && (
<div className="mail-cc">
<span className="meta-label"></span>
<span>{m.cc}</span>
</div>
)}
<div className="mail-date-row">
<span className="meta-label"></span>
<span>{m.date}</span>
</div>
</div>
<div className="mail-actions">
<button className="btn-reply" onClick={reply}> </button>
<button className="btn-forward" onClick={forward}> </button>
</div>
</div>
{/* 첨부파일 */}
{m.attachments?.length > 0 && (
<div className="mail-attachments">
<div className="attach-title">📎 ({m.attachments.length})</div>
<div className="attach-list">
{m.attachments.map(a => (
<a
key={a.part_id}
href={mailApi.attachmentUrl(m.uid, a.part_id, currentFolder)}
className="attach-item" download={a.filename}
>
<span className="attach-name">{a.filename}</span>
<span className="attach-size">({fmtSize(a.size)})</span>
</a>
))}
</div>
</div>
)}
{/* 본문 */}
<div className="mail-body-content">
{cleanHtml ? (
<div
className="mail-html-body"
dangerouslySetInnerHTML={{ __html: cleanHtml }}
/>
) : (
<pre className="mail-text-body">{m.body_text}</pre>
)}
</div>
</div>
)
}
function fmtSize(b: number) {
if (b < 1024) return `${b}B`
if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)}KB`
return `${(b / 1024 / 1024).toFixed(1)}MB`
}