diff --git a/src/components/admin/EmailTemplatePreview.tsx b/src/components/admin/EmailTemplatePreview.tsx
index 59035e3..25aa838 100644
--- a/src/components/admin/EmailTemplatePreview.tsx
+++ b/src/components/admin/EmailTemplatePreview.tsx
@@ -3,8 +3,16 @@ 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 {
+ Dialog,
+ DialogContent,
+ DialogHeader,
+ DialogTitle,
+ DialogDescription,
+ DialogFooter,
+} from '@/components/ui/dialog';
import { toast } from '@/hooks/use-toast';
-import { Eye, Send, Mail } from 'lucide-react';
+import { Eye, Send, Mail, X } from 'lucide-react';
import { EmailTemplateRenderer, ShortcodeProcessor } from '@/lib/email-templates/master-template';
interface NotificationTemplate {
@@ -22,9 +30,17 @@ interface EmailTemplatePreviewProps {
template: NotificationTemplate;
onTest?: (template: NotificationTemplate) => void;
isTestSending?: boolean;
+ open: boolean;
+ onClose: () => void;
}
-export function EmailTemplatePreview({ template, onTest, isTestSending = false }: EmailTemplatePreviewProps) {
+export function EmailTemplatePreview({
+ template,
+ onTest,
+ isTestSending = false,
+ open,
+ onClose
+}: EmailTemplatePreviewProps) {
const [previewMode, setPreviewMode] = useState<'master' | 'content'>('master');
const [testEmail, setTestEmail] = useState('');
const [showTestForm, setShowTestForm] = useState(false);
@@ -60,109 +76,154 @@ export function EmailTemplatePreview({ template, onTest, isTestSending = false }
const previewHtml = generatePreview();
return (
-
- {/* Preview Controls */}
-
-
-
-
-
-
-
+
-
+
- {/* Test Email Form */}
- {showTestForm && (
-
-
-
-
-
setTestEmail(e.target.value)}
- placeholder="test@example.com"
- className="flex-1"
- />
-
- )}
- {/* Preview Info */}
-
-
-
- {previewMode === 'master'
- ? 'Showing complete email template with header, footer, and styling applied.'
- : 'Showing only the content section without master template styling.'
- }
-
-
+ {/* Test Email Form */}
+ {showTestForm && (
+
+
+
+
+ setTestEmail(e.target.value)}
+ placeholder="test@example.com"
+ className="flex-1"
+ />
+
+
+ {isTestSending ? 'Sending...' : 'Send Test'}
+
+
+
+ This will send a test email with dummy data for all available shortcodes.
+
+
+
+ )}
- {/* Email Preview */}
-
-
-
- {previewMode === 'master' ? 'Full Email Preview' : 'Content Preview'}
-
-
-
-
-
-
+ {/* Preview Info */}
+
+
+
+ {previewMode === 'master'
+ ? 'Showing complete email template with header, footer, and styling applied.'
+ : 'Showing only the content section without master template styling.'
+ }
+
+
- {/* Shortcodes Used */}
-
-
Shortcodes Used in This Template:
-
- {['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}',
- '{produk}', '{link_akses}', '{tanggal_konsultasi}', '{jam_konsultasi}', '{link_meet}',
- '{judul_event}', '{tanggal_event}', '{jam_event}', '{link_event}'].filter(shortcode =>
- template.email_subject.includes(shortcode) || template.email_body_html.includes(shortcode)
- ).map(shortcode => (
-
- {shortcode}
-
- ))}
+ {/* Email Preview */}
+
+
+
+ {previewMode === 'master' ? 'Full Email Preview' : 'Content Preview'}
+
+
+
+
+
+
+
+ {/* Shortcodes Used */}
+
+
Shortcodes Used in This Template:
+
+ {['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}',
+ '{produk}', '{link_akses}', '{tanggal_konsultasi}', '{jam_konsultasi}', '{link_meet}',
+ '{judul_event}', '{tanggal_event}', '{jam_event}', '{link_event}'].filter(shortcode =>
+ template.email_subject.includes(shortcode) || template.email_body_html.includes(shortcode)
+ ).map(shortcode => (
+
+ {shortcode}
+
+ ))}
+
+
+
+ {/* Template Actions */}
+
+
+ Close
+
+ {!showTestForm && (
+ setShowTestForm(true)}
+ className="flex-1"
+ >
+
+ Test Email
+
+ )}
+ {showTestForm && (
+ setShowTestForm(false)}
+ variant="outline"
+ >
+ Cancel
+
+ )}
+
-
-
+
+
);
}
\ No newline at end of file
diff --git a/src/components/admin/settings/NotifikasiTab.tsx b/src/components/admin/settings/NotifikasiTab.tsx
index 6799047..0a2fe6a 100644
--- a/src/components/admin/settings/NotifikasiTab.tsx
+++ b/src/components/admin/settings/NotifikasiTab.tsx
@@ -346,36 +346,93 @@ export function NotifikasiTab() {
const [loading, setLoading] = useState(true);
const [expandedTemplates, setExpandedTemplates] = useState
>(new Set());
const [testingTemplate, setTestingTemplate] = useState(null);
- const [selectedTemplate, setSelectedTemplate] = useState(null);
- const [previewMode, setPreviewMode] = useState<'master' | 'content'>('master');
+ const [previewTemplate, setPreviewTemplate] = useState(null);
+ const [isPreviewOpen, setIsPreviewOpen] = useState(false);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
- // Fetch templates
- const { data: templatesData } = await supabase.from('notification_templates').select('*').order('key');
- if (templatesData && templatesData.length > 0) {
- setTemplates(templatesData);
- } else {
- // Seed default templates if none exist
- await seedTemplates();
+ try {
+ console.log('Fetching templates...');
+ // Fetch templates
+ const { data: templatesData, error: fetchError } = await supabase.from('notification_templates').select('*').order('key');
+
+ if (fetchError) {
+ console.error('Error fetching templates:', fetchError);
+ toast({
+ title: 'Error',
+ description: 'Gagal mengambil template: ' + fetchError.message,
+ variant: 'destructive'
+ });
+ setLoading(false);
+ return;
+ }
+
+ console.log('Templates data:', templatesData);
+
+ if (templatesData && templatesData.length > 0) {
+ console.log('Setting templates from database:', templatesData.length);
+ setTemplates(templatesData);
+ } else {
+ console.log('No templates found, seeding default templates...');
+ // Seed default templates if none exist
+ await seedTemplates();
+ }
+ } catch (error) {
+ console.error('Unexpected error in fetchData:', error);
+ toast({
+ title: 'Error',
+ description: 'Terjadi kesalahan tak terduga saat mengambil data',
+ variant: 'destructive'
+ });
+ } finally {
+ setLoading(false);
}
- setLoading(false);
};
const seedTemplates = async () => {
- const toInsert = DEFAULT_TEMPLATES.map(t => ({
- key: t.key,
- name: t.name,
- is_active: false,
- email_subject: t.defaultSubject,
- email_body_html: t.defaultBody,
- webhook_url: '',
- }));
- const { data, error } = await supabase.from('notification_templates').insert(toInsert).select();
- if (!error && data) setTemplates(data);
+ try {
+ console.log('Seeding default templates...');
+ const toInsert = DEFAULT_TEMPLATES.map(t => ({
+ key: t.key,
+ name: t.name,
+ is_active: false,
+ email_subject: t.defaultSubject,
+ email_body_html: t.defaultBody,
+ webhook_url: '',
+ }));
+
+ console.log('Inserting templates:', toInsert.length);
+ const { data, error } = await supabase.from('notification_templates').insert(toInsert).select();
+
+ if (error) {
+ console.error('Error seeding templates:', error);
+ toast({
+ title: 'Error',
+ description: 'Gagal membuat template default: ' + error.message,
+ variant: 'destructive'
+ });
+ return;
+ }
+
+ console.log('Templates seeded successfully:', data);
+ if (data) {
+ setTemplates(data);
+ toast({
+ title: 'Berhasil',
+ description: `Berhasil membuat ${data.length} template default`
+ });
+ }
+ } catch (error) {
+ console.error('Unexpected error in seedTemplates:', error);
+ toast({
+ title: 'Error',
+ description: 'Terjadi kesalahan saat membuat template default',
+ variant: 'destructive'
+ });
+ }
};
@@ -587,7 +644,8 @@ export function NotifikasiTab() {
{
updateTemplate(template);
- setSelectedTemplate(template);
+ setPreviewTemplate(template);
+ setIsPreviewOpen(true);
}}
className="shadow-sm flex-1"
>
@@ -620,33 +678,14 @@ export function NotifikasiTab() {
- {/* Consolidated Email Preview */}
- {selectedTemplate && (
-
-
-
- Preview: {selectedTemplate.name}
- setSelectedTemplate(null)}
- >
- Tutup Preview
-
-
-
- Preview template email dengan master styling
-
-
-
-
-
-
- )}
+ {/* Modal Email Preview */}
+ setIsPreviewOpen(false)}
+ onTest={sendTestEmail}
+ isTestSending={testingTemplate === previewTemplate?.id}
+ />
);
}