feat(analyzer): phase 7 — share-via-email
sendAnalysisShareEmail() reuses the existing nodemailer SMTP transport
(same path as magic-link/invitation mail). Share route persists the
audit row first, then attempts send; on failure returns
{share, emailSent:false, emailError} at HTTP 200 so the audit log
stays intact. Modal surfaces send failures as a warning toast.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8f8b5ab7be
commit
ed3b363d02
4 changed files with 231 additions and 9 deletions
|
|
@ -39,11 +39,22 @@ export function ShareModal({ analysisId }: ShareModalProps) {
|
|||
note: note.trim() || undefined,
|
||||
}),
|
||||
});
|
||||
const data = (await res.json().catch(() => ({}))) as {
|
||||
error?: string;
|
||||
message?: string;
|
||||
emailSent?: boolean;
|
||||
emailError?: string | null;
|
||||
};
|
||||
if (!res.ok) {
|
||||
const data = (await res.json().catch(() => ({}))) as { error?: string; message?: string };
|
||||
throw new Error(data.message ?? data.error ?? `Request failed: ${res.status}`);
|
||||
}
|
||||
toast.success(`Shared with ${recipientEmail}`);
|
||||
if (data.emailSent === false) {
|
||||
toast.warning(
|
||||
`Share recorded for ${recipientEmail}, but email failed: ${data.emailError ?? 'unknown error'}`
|
||||
);
|
||||
} else {
|
||||
toast.success(`Shared with ${recipientEmail}`);
|
||||
}
|
||||
setOpen(false);
|
||||
setRecipientEmail('');
|
||||
setNote('');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue