const API_BASE_EMAIL = window.__LARAVEL_API_URL || 'https://api.techyfuel.com/api'; // Email screen — reads/sends through a mailbox via IMAP/SMTP (api/email-list.js, // api/email-message.js, api/email-send.js, api/email-accounts.js). No OAuth -- // this is for plain cPanel/Hostinger-style mailboxes. By default it uses the // one shared TechyFuel inbox (Vercel env vars) but each team member can also // connect their own separate mailbox from here; those credentials are // encrypted server-side and never touch the client, keyed to whoever is // signed in (verified from their own Supabase session token on every call). (() => { const { Badge } = window.TechyFuelOSDesignSystem_be0222; async function authHeader() { try { const { data } = await window.db.auth.getSession(); const token = data?.session?.access_token; return token ? { Authorization: `Bearer ${token}` } : {}; } catch { return {}; } } function fmtWhen(ds) { if (!ds) return ''; const d = new Date(ds); const now = new Date(); const sameDay = d.toDateString() === now.toDateString(); return sameDay ? d.toLocaleTimeString('en', { hour: 'numeric', minute: '2-digit' }) : d.toLocaleDateString('en', { month: 'short', day: 'numeric' }); } // Normalize an address that the API may send as an object ({name,address}), // a plain string, or null (bounce / system mail) — so we never show a raw blank. function addrText(a) { if (!a) return ''; if (typeof a === 'string') return a; return a.name || a.address || ''; } function MessageRow({ msg, active, onClick, mailbox }) { const [hover, setHover] = React.useState(false); const isSent = mailbox === 'sent'; const who = isSent ? (addrText(msg.to && msg.to[0]) || 'Unknown recipient') : (addrText(msg.from) || 'Unknown sender'); const seen = !msg.unseen; // backend sends `unseen`, not `seen` return (
setHover(true)} onMouseLeave={() => setHover(false)} style={{ display: 'flex', alignItems: 'flex-start', gap: 10, padding: '12px 14px', cursor: 'pointer', userSelect: 'none', WebkitUserSelect: 'none', WebkitTapHighlightColor: 'transparent', borderLeft: `3px solid ${active ? 'var(--blue-600)' : 'transparent'}`, background: active ? 'var(--blue-50)' : hover ? 'var(--slate-50)' : 'transparent', borderBottom: '1px solid var(--border-subtle)' }}>
{isSent ? `To: ${who}` : who} {fmtWhen(msg.date)}
{msg.subject}
); } function ComposeModal({ open, onClose, onSent, accountId, initial, title }) { const [form, setForm] = React.useState({ to: '', subject: '', body: '' }); const [sending, setSending] = React.useState(false); const [error, setError] = React.useState(''); function set(k, v) { setForm(f => ({ ...f, [k]: v })); } React.useEffect(() => { if (open) { setForm(initial || { to: '', subject: '', body: '' }); setError(''); } }, [open]); async function handleSend() { if (!form.to.trim() || !form.subject.trim() || !form.body.trim()) { setError('To, subject and message are all required.'); return; } setSending(true); setError(''); try { const headers = { 'Content-Type': 'application/json', ...(await authHeader()) }; const res = await fetch(API_BASE_EMAIL+'/email-send', { method: 'POST', headers, body: JSON.stringify({ ...form, accountId }) }); const data = await res.json(); if (!data.ok) { setError(data.error || 'Could not send the email.'); return; } setForm({ to: '', subject: '', body: '' }); onClose(); if (onSent) onSent(); } catch (err) { setError(err.message || 'Could not send the email.'); } finally { setSending(false); } } return ( {error && (
{error}
)} set('to', e.target.value)} autoFocus /> set('subject', e.target.value)} />