graph + mail dispatcher, test-email endpoint, notifications global
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
|
||||
/**
|
||||
* Admin UI: a small "send test email" tool for the SiteIntegrations email tab.
|
||||
* Enter an address, click Send, and it POSTs to /api/ipal/test-email, which
|
||||
* sends through the currently-selected transport (SMTP or Graph). Shows the
|
||||
* result inline so you can confirm delivery — or read the exact error — without
|
||||
* leaving the panel.
|
||||
*
|
||||
* Assigned via a `ui` field's admin.components.Field.
|
||||
*/
|
||||
export const TestEmailButton = () => {
|
||||
const [to, setTo] = useState('')
|
||||
const [status, setStatus] = useState<
|
||||
| { kind: 'error'; msg: string }
|
||||
| { kind: 'idle' }
|
||||
| { kind: 'ok'; msg: string }
|
||||
| { kind: 'sending' }
|
||||
>({ kind: 'idle' })
|
||||
|
||||
const send = async () => {
|
||||
if (!to.trim()) {
|
||||
setStatus({ kind: 'error', msg: 'Enter a recipient address.' })
|
||||
return
|
||||
}
|
||||
setStatus({ kind: 'sending' })
|
||||
try {
|
||||
const res = await fetch('/api/ipal/test-email', {
|
||||
body: JSON.stringify({ to: to.trim() }),
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
method: 'POST',
|
||||
})
|
||||
const data = await res.json()
|
||||
if (data.ok) {
|
||||
setStatus({ kind: 'ok', msg: data.message ?? 'Test email sent.' })
|
||||
} else {
|
||||
setStatus({ kind: 'error', msg: data.error ?? 'Send failed.' })
|
||||
}
|
||||
} catch {
|
||||
setStatus({ kind: 'error', msg: 'Request failed. Is the server running?' })
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="field-type" style={{ marginTop: '1rem' }}>
|
||||
<label className="field-label">Send a test email</label>
|
||||
<p style={{ fontSize: '.85rem', marginTop: 0, opacity: 0.7 }}>
|
||||
Sends through the transport selected above. Save your changes first.
|
||||
</p>
|
||||
<div style={{ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '.5rem' }}>
|
||||
<input
|
||||
onChange={(e) => setTo(e.target.value)}
|
||||
placeholder="[email protected]"
|
||||
style={{ flex: 1, minWidth: '220px' }}
|
||||
type="email"
|
||||
value={to}
|
||||
/>
|
||||
<button
|
||||
className="btn btn--style-secondary"
|
||||
disabled={status.kind === 'sending'}
|
||||
onClick={send}
|
||||
style={{ whiteSpace: 'nowrap' }}
|
||||
type="button"
|
||||
>
|
||||
{status.kind === 'sending' ? 'Sending…' : 'Send test'}
|
||||
</button>
|
||||
</div>
|
||||
{status.kind === 'ok' && (
|
||||
<p style={{ color: 'var(--theme-success-500, green)', marginTop: '.5rem' }}>
|
||||
✓ {status.msg}
|
||||
</p>
|
||||
)}
|
||||
{status.kind === 'error' && (
|
||||
<p style={{ color: 'var(--theme-error-500, crimson)', marginTop: '.5rem' }}>
|
||||
✗ {status.msg}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TestEmailButton
|
||||
Reference in New Issue
Block a user