feat: add frontend/src/components/Compose.tsx
This commit is contained in:
parent
e4f634f3fb
commit
cc8ea14bf6
83
frontend/src/components/Compose.tsx
Normal file
83
frontend/src/components/Compose.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import { useState } from 'react'
|
||||
import { mailApi } from '../api/mailApi'
|
||||
import { useMailStore } from '../store/mailStore'
|
||||
|
||||
export default function Compose() {
|
||||
const { replyTo, closeCompose, username } = useMailStore()
|
||||
const [to, setTo] = useState(replyTo?.sender_addr || '')
|
||||
const [cc, setCc] = useState('')
|
||||
const [subject, setSubject] = useState(
|
||||
replyTo ? (replyTo.subject.startsWith('Re:') ? replyTo.subject : `Re: ${replyTo.subject}`) : ''
|
||||
)
|
||||
const [body, setBody] = useState(
|
||||
replyTo
|
||||
? `\n\n---\n${replyTo.date}에 ${replyTo.sender} (${replyTo.sender_addr}) 님이 작성:\n${replyTo.body_text || '(HTML 메일)'}\n`
|
||||
: ''
|
||||
)
|
||||
const [sending, setSending] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
const [success, setSuccess] = useState(false)
|
||||
const [showCc, setShowCc] = useState(false)
|
||||
|
||||
const send = async () => {
|
||||
if (!to.trim() || !subject.trim()) { setError('받는사람과 제목은 필수입니다'); return }
|
||||
setSending(true); setError('')
|
||||
try {
|
||||
await mailApi.send({ to, cc: cc || undefined, subject, body })
|
||||
setSuccess(true)
|
||||
setTimeout(closeCompose, 1500)
|
||||
} catch (e: any) {
|
||||
setError(e.response?.data?.detail || '발송에 실패했습니다')
|
||||
} finally { setSending(false) }
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="compose-overlay" onClick={e => e.target === e.currentTarget && closeCompose()}>
|
||||
<div className="compose-box">
|
||||
<div className="compose-header">
|
||||
<span>✏️ {replyTo ? '답장' : '새 메일'}</span>
|
||||
<button className="compose-close" onClick={closeCompose}>✕</button>
|
||||
</div>
|
||||
|
||||
<div className="compose-fields">
|
||||
<div className="compose-field">
|
||||
<label>보내는 사람</label>
|
||||
<span className="compose-from">{username}</span>
|
||||
</div>
|
||||
<div className="compose-field">
|
||||
<label>받는 사람</label>
|
||||
<input value={to} onChange={e => setTo(e.target.value)} placeholder="수신자 이메일" />
|
||||
<button className="btn-cc-toggle" onClick={() => setShowCc(v => !v)}>참조</button>
|
||||
</div>
|
||||
{showCc && (
|
||||
<div className="compose-field">
|
||||
<label>참조</label>
|
||||
<input value={cc} onChange={e => setCc(e.target.value)} placeholder="참조 이메일" />
|
||||
</div>
|
||||
)}
|
||||
<div className="compose-field">
|
||||
<label>제목</label>
|
||||
<input value={subject} onChange={e => setSubject(e.target.value)} placeholder="제목 입력" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
className="compose-body"
|
||||
value={body}
|
||||
onChange={e => setBody(e.target.value)}
|
||||
placeholder="내용을 입력하세요..."
|
||||
/>
|
||||
|
||||
{error && <div className="compose-error">⚠️ {error}</div>}
|
||||
{success && <div className="compose-success">✅ 발송 완료!</div>}
|
||||
|
||||
<div className="compose-footer">
|
||||
<button className="btn-send" onClick={send} disabled={sending}>
|
||||
{sending ? '발송 중...' : '📨 보내기'}
|
||||
</button>
|
||||
<button className="btn-cancel" onClick={closeCompose}>취소</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user