From efc085e2313a8f0f764c65150ffcb1e9aea7b91d Mon Sep 17 00:00:00 2001 From: dwindown Date: Mon, 22 Dec 2025 19:56:23 +0700 Subject: [PATCH] Implement modular email template system with preview and testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create modular EmailTemplateRenderer with master shell and content separation - Build reusable email components library (buttons, alerts, OTP boxes, etc.) - Add EmailTemplatePreview component with master/content preview modes - Implement test email functionality for each notification template - Update NotifikasiTab to use new preview system with shortcode processing - Add dummy shortcode data for testing (nama, email, order_id, etc.) - Maintain design consistency between web and email 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- email-master-template.html | 310 ++++++++++++++ src/components/admin/EmailTemplatePreview.tsx | 164 ++++++++ .../admin/settings/NotifikasiTab.tsx | 157 ++++--- src/lib/email-templates/master-template.ts | 382 ++++++++++++++++++ 4 files changed, 967 insertions(+), 46 deletions(-) create mode 100644 email-master-template.html create mode 100644 src/components/admin/EmailTemplatePreview.tsx create mode 100644 src/lib/email-templates/master-template.ts diff --git a/email-master-template.html b/email-master-template.html new file mode 100644 index 0000000..72b916e --- /dev/null +++ b/email-master-template.html @@ -0,0 +1,310 @@ + + + + + + Notification + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/src/components/admin/EmailTemplatePreview.tsx b/src/components/admin/EmailTemplatePreview.tsx new file mode 100644 index 0000000..73cff74 --- /dev/null +++ b/src/components/admin/EmailTemplatePreview.tsx @@ -0,0 +1,164 @@ +import { useState } from 'react'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { toast } from '@/hooks/use-toast'; +import { Eye, Send, Mail } from 'lucide-react'; +import { EmailTemplateRenderer, ShortcodeProcessor } from '@/lib/email-templates/master-template'; + +interface NotificationTemplate { + id: string; + key: string; + name: string; + is_active: boolean; + email_subject: string; + email_body_html: string; + webhook_url: string; + last_payload_example?: Record | null; +} + +interface EmailTemplatePreviewProps { + template: NotificationTemplate; + onTest?: (template: NotificationTemplate) => void; + isTestSending?: boolean; +} + +export function EmailTemplatePreview({ template, onTest, isTestSending = false }: EmailTemplatePreviewProps) { + const [previewMode, setPreviewMode] = useState<'master' | 'content'>('master'); + const [testEmail, setTestEmail] = useState(''); + const [showTestForm, setShowTestForm] = useState(false); + + // Generate preview with dummy shortcode data + const generatePreview = () => { + const processedSubject = ShortcodeProcessor.process(template.email_subject); + const processedContent = ShortcodeProcessor.process(template.email_body_html); + + if (previewMode === 'master') { + const fullHtml = EmailTemplateRenderer.render({ + subject: processedSubject, + content: processedContent, + brandName: 'ACCESS HUB' + }); + return fullHtml; + } else { + return processedContent; + } + }; + + const handleTestEmail = async () => { + if (!testEmail) { + toast({ title: 'Error', description: 'Masukkan email tujuan', variant: 'destructive' }); + return; + } + + if (onTest) { + await onTest({ ...template, test_email: testEmail }); + } + }; + + const previewHtml = generatePreview(); + + return ( +
+ {/* Preview Controls */} +
+
+ + +
+ +
+ +
+
+ + {/* Test Email Form */} + {showTestForm && ( +
+
+ +
+ setTestEmail(e.target.value)} + placeholder="test@example.com" + className="flex-1" + /> + +
+

+ This will send a test email with dummy data for all available shortcodes. +

+
+
+ )} + + {/* Preview Info */} + + + + {previewMode === 'master' + ? 'Showing complete email template with header, footer, and styling applied.' + : 'Showing only the content section without master template styling.' + } + + + + {/* Email Preview */} +
+
+ + {previewMode === 'master' ? 'Full Email Preview' : 'Content Preview'} + +
+
+