Fix email template preview UX and debug template loading
- Convert EmailTemplatePreview from bottom card to modal Dialog component - Replace problematic bottom preview with clean modal popup - Add proper modal state management (open/close handlers) - Debug template loading with comprehensive error handling and logging - Add user feedback for template seeding and loading errors - Improve fetchData() and seedTemplates() with try-catch blocks - Add console logging for debugging template initialization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -346,36 +346,93 @@ export function NotifikasiTab() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [expandedTemplates, setExpandedTemplates] = useState<Set<string>>(new Set());
|
||||
const [testingTemplate, setTestingTemplate] = useState<string | null>(null);
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<NotificationTemplate | null>(null);
|
||||
const [previewMode, setPreviewMode] = useState<'master' | 'content'>('master');
|
||||
const [previewTemplate, setPreviewTemplate] = useState<NotificationTemplate | null>(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() {
|
||||
<Button
|
||||
onClick={() => {
|
||||
updateTemplate(template);
|
||||
setSelectedTemplate(template);
|
||||
setPreviewTemplate(template);
|
||||
setIsPreviewOpen(true);
|
||||
}}
|
||||
className="shadow-sm flex-1"
|
||||
>
|
||||
@@ -620,33 +678,14 @@ export function NotifikasiTab() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Consolidated Email Preview */}
|
||||
{selectedTemplate && (
|
||||
<Card className="border-2 border-border">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center justify-between">
|
||||
<span>Preview: {selectedTemplate.name}</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setSelectedTemplate(null)}
|
||||
>
|
||||
Tutup Preview
|
||||
</Button>
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Preview template email dengan master styling
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<EmailTemplatePreview
|
||||
template={selectedTemplate}
|
||||
onTest={sendTestEmail}
|
||||
isTestSending={testingTemplate === selectedTemplate.id}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{/* Modal Email Preview */}
|
||||
<EmailTemplatePreview
|
||||
template={previewTemplate!}
|
||||
open={isPreviewOpen}
|
||||
onClose={() => setIsPreviewOpen(false)}
|
||||
onTest={sendTestEmail}
|
||||
isTestSending={testingTemplate === previewTemplate?.id}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user