feat(deps): adopt react-email for portal-auth template
Migrates the activation + reset email templates from hand-strung HTML strings to React components rendered via @react-email/components. Concrete wins this lands: - React auto-escapes interpolation — drops the hand-rolled escapeHtml() helper. Eliminates the entire class of "I forgot to escape" XSS bugs. - @react-email primitives (Button, Hr, Link, Text) render to Outlook/Gmail/AppleMail-safe inline-styled HTML. - JSX over template strings makes the templates editable / reviewable. - Sets the pattern for the remaining 7 templates (crm-invite, document-signing, inquiry-*, notification-digest, admin-email-change, residential-inquiry). Migrate opportunistically when those files are next touched. The shell (logo, blurred background, table-based wrapper) stays via renderShell so this is a strictly inner-body migration — visual parity preserved. Vitest config: added @vitejs/plugin-react so .tsx files imported by tests (transitively via the service that uses the template) transform correctly under Next's tsconfig `jsx: 'preserve'` setting. Verified: tsc clean, vitest 1293/1293 pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -147,7 +147,7 @@ async function issueActivationToken(
|
||||
const link = `${env.APP_URL}/portal/activate?token=${encodeURIComponent(raw)}`;
|
||||
const subjectOverride = await loadSubjectOverride(portId, 'portal_activation');
|
||||
const branding = await getBrandingShell(portId);
|
||||
const { subject, html, text } = activationEmail(
|
||||
const { subject, html, text } = await activationEmail(
|
||||
{
|
||||
portName,
|
||||
link,
|
||||
@@ -408,7 +408,7 @@ export async function requestPasswordReset(email: string): Promise<void> {
|
||||
const link = `${env.APP_URL}/portal/reset-password?token=${encodeURIComponent(raw)}`;
|
||||
const subjectOverride = await loadSubjectOverride(user.portId, 'portal_reset');
|
||||
const branding = await getBrandingShell(user.portId);
|
||||
const { subject, html, text } = resetEmail(
|
||||
const { subject, html, text } = await resetEmail(
|
||||
{
|
||||
portName,
|
||||
link,
|
||||
|
||||
Reference in New Issue
Block a user