diff --git a/frontend/src/components/EmailDetail.jsx b/frontend/src/components/EmailDetail.jsx new file mode 100644 index 0000000..8671efd --- /dev/null +++ b/frontend/src/components/EmailDetail.jsx @@ -0,0 +1,115 @@ +import { useEffect, useState } from 'react'; +import { EmailApi } from '../api/client.js'; + +// ── helpers ────────────────────────────────────────────────────────────────── + +const fmtSize = (b) => { + if (!b) return ''; + if (b < 1024) return `${b} B`; + if (b < 1048576) return `${(b / 1024).toFixed(0)} KB`; + return `${(b / 1048576).toFixed(1)} MB`; +}; + +/** + * Shared reading-pane / full single-email view. + * + * Accepts either an `email` summary object (as emitted by the list rows) or a + * bare `emailId`. Fetches the full detail via EmailApi.get(id) and the AI + * summary lazily via EmailApi.summary(id). Renders subject, metadata, an AI + * summary button, the body, and per-email actions including "Open in Gmail". + * + * `onClose` collapses the pane. + */ +export default function EmailDetail({ email: summary, emailId, onClose }) { + const id = summary?.id ?? emailId; + + const [detail, setDetail] = useState(null); + const [loading, setLoading] = useState(true); + const [aiSummary, setAiSummary] = useState(null); + const [aiLoading, setAiLoading] = useState(false); + + useEffect(() => { + if (id == null) return; + let cancelled = false; + setDetail(null); + setLoading(true); + setAiSummary(null); + setAiLoading(false); + EmailApi.get(id) + .then((d) => { if (!cancelled) setDetail(d); }) + .catch(() => { if (!cancelled) setDetail(null); }) + .finally(() => { if (!cancelled) setLoading(false); }); + return () => { cancelled = true; }; + }, [id]); + + const email = detail ?? summary ?? {}; + + const fetchAiSummary = () => { + if (id == null) return; + setAiLoading(true); + EmailApi.summary(id) + .then((r) => setAiSummary(r.summary)) + .catch(() => setAiSummary(null)) + .finally(() => setAiLoading(false)); + }; + + const openInGmail = () => window.open( + `https://mail.google.com/mail/u/0/#all/${email.gmailMessageId}`, + '_blank', 'noopener,noreferrer' + ); + + return ( +