/** * Vendor Email Templates Management Page * * Allows vendors to customize email templates sent to their customers. * Platform-only templates (billing, subscription) cannot be overridden. */ const vendorEmailTemplatesLog = window.LogConfig?.loggers?.vendorEmailTemplates || window.LogConfig?.createLogger?.('vendorEmailTemplates', false) || { info: () => {}, debug: () => {}, warn: () => {}, error: console.error }; vendorEmailTemplatesLog.info('Loading...'); function vendorEmailTemplates() { vendorEmailTemplatesLog.info('vendorEmailTemplates() called'); return { // Inherit base layout state ...data(), // Set page identifier currentPage: 'email-templates', // Loading states loading: true, error: '', saving: false, // Data templates: [], supportedLanguages: ['en', 'fr', 'de', 'lb'], // Edit Modal showEditModal: false, editingTemplate: null, editLanguage: 'en', loadingTemplate: false, templateSource: 'platform', editForm: { subject: '', body_html: '', body_text: '' }, reverting: false, // Preview Modal showPreviewModal: false, previewData: null, // Test Email Modal showTestEmailModal: false, testEmailAddress: '', sendingTest: false, // Lifecycle async init() { await this.loadData(); }, // Data Loading async loadData() { this.loading = true; this.error = ''; try { const response = await fetch('/api/v1/vendor/email-templates', { headers: { 'Authorization': `Bearer ${this.getAuthToken()}` } }); if (response.ok) { const data = await response.json(); this.templates = data.templates || []; this.supportedLanguages = data.supported_languages || ['en', 'fr', 'de', 'lb']; } else { const error = await response.json(); this.error = error.detail || 'Failed to load templates'; } } catch (error) { vendorEmailTemplatesLog.error('Failed to load templates:', error); this.error = 'Failed to load templates'; } finally { this.loading = false; } }, // Auth token helper getAuthToken() { // Get from cookie or localStorage depending on your auth setup return document.cookie .split('; ') .find(row => row.startsWith('vendor_token=')) ?.split('=')[1] || ''; }, // Category styling getCategoryClass(category) { const classes = { 'AUTH': 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400', 'ORDERS': 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400', 'BILLING': 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400', 'SYSTEM': 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400', 'MARKETING': 'bg-pink-100 text-pink-700 dark:bg-pink-900/30 dark:text-pink-400', 'TEAM': 'bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-400' }; return classes[category] || 'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300'; }, // Edit Template async editTemplate(template) { this.editingTemplate = template; this.editLanguage = 'en'; this.showEditModal = true; await this.loadTemplateLanguage(); }, async loadTemplateLanguage() { if (!this.editingTemplate) return; this.loadingTemplate = true; try { const response = await fetch( `/api/v1/vendor/email-templates/${this.editingTemplate.code}/${this.editLanguage}`, { headers: { 'Authorization': `Bearer ${this.getAuthToken()}` } } ); if (response.ok) { const data = await response.json(); this.templateSource = data.source; this.editForm = { subject: data.subject || '', body_html: data.body_html || '', body_text: data.body_text || '' }; } else if (response.status === 404) { // No template for this language this.templateSource = 'none'; this.editForm = { subject: '', body_html: '', body_text: '' }; this.showNotification(`No template available for ${this.editLanguage.toUpperCase()}`, 'info'); } } catch (error) { vendorEmailTemplatesLog.error('Failed to load template:', error); this.showNotification('Failed to load template', 'error'); } finally { this.loadingTemplate = false; } }, closeEditModal() { this.showEditModal = false; this.editingTemplate = null; this.editForm = { subject: '', body_html: '', body_text: '' }; }, async saveTemplate() { if (!this.editingTemplate) return; this.saving = true; try { const response = await fetch( `/api/v1/vendor/email-templates/${this.editingTemplate.code}/${this.editLanguage}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.getAuthToken()}` }, body: JSON.stringify({ subject: this.editForm.subject, body_html: this.editForm.body_html, body_text: this.editForm.body_text || null }) } ); if (response.ok) { this.showNotification('Template saved successfully', 'success'); this.templateSource = 'vendor_override'; // Refresh list to show updated status await this.loadData(); } else { const error = await response.json(); this.showNotification(error.detail || 'Failed to save template', 'error'); } } catch (error) { vendorEmailTemplatesLog.error('Failed to save template:', error); this.showNotification('Failed to save template', 'error'); } finally { this.saving = false; } }, async revertToDefault() { if (!this.editingTemplate) return; if (!confirm('Are you sure you want to delete your customization and revert to the platform default?')) { return; } this.reverting = true; try { const response = await fetch( `/api/v1/vendor/email-templates/${this.editingTemplate.code}/${this.editLanguage}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${this.getAuthToken()}` } } ); if (response.ok) { this.showNotification('Reverted to platform default', 'success'); // Reload the template to show platform version await this.loadTemplateLanguage(); // Refresh list await this.loadData(); } else { const error = await response.json(); this.showNotification(error.detail || 'Failed to revert', 'error'); } } catch (error) { vendorEmailTemplatesLog.error('Failed to revert template:', error); this.showNotification('Failed to revert', 'error'); } finally { this.reverting = false; } }, // Preview async previewTemplate() { if (!this.editingTemplate) return; try { const response = await fetch( `/api/v1/vendor/email-templates/${this.editingTemplate.code}/preview`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.getAuthToken()}` }, body: JSON.stringify({ language: this.editLanguage, variables: {} }) } ); if (response.ok) { this.previewData = await response.json(); this.showPreviewModal = true; } else { this.showNotification('Failed to load preview', 'error'); } } catch (error) { vendorEmailTemplatesLog.error('Failed to preview template:', error); this.showNotification('Failed to load preview', 'error'); } }, // Test Email sendTestEmail() { this.showTestEmailModal = true; }, async confirmSendTestEmail() { if (!this.testEmailAddress || !this.editingTemplate) return; this.sendingTest = true; try { const response = await fetch( `/api/v1/vendor/email-templates/${this.editingTemplate.code}/test`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.getAuthToken()}` }, body: JSON.stringify({ to_email: this.testEmailAddress, language: this.editLanguage, variables: {} }) } ); const result = await response.json(); if (result.success) { this.showNotification(`Test email sent to ${this.testEmailAddress}`, 'success'); this.showTestEmailModal = false; this.testEmailAddress = ''; } else { this.showNotification(result.message || 'Failed to send test email', 'error'); } } catch (error) { vendorEmailTemplatesLog.error('Failed to send test email:', error); this.showNotification('Failed to send test email', 'error'); } finally { this.sendingTest = false; } }, // Notifications showNotification(message, type = 'info') { // Use global notification system if available if (window.showToast) { window.showToast(message, type); } else if (window.Alpine && Alpine.store('notifications')) { Alpine.store('notifications').add(message, type); } else { console.log(`[${type.toUpperCase()}] ${message}`); } } }; }