fix: Email Preview Issues - All 5 Fixed! 🔧
## Issues Fixed: ### 1. Button Not Rendering ✅ - Buttons now use custom primary_color - Button text uses button_text_color - Outline buttons use secondary_color - Applied to .button and .button-outline classes ### 2. Double Hash in Order Number ✅ - Changed order_number from "#12345" to "12345" - Templates already have # prefix - Prevents ##12345 display ### 3. Duplicate Icons in Social Selector ✅ - Removed duplicate icon from SelectTrigger - SelectValue already shows the icon - Clean single icon display ### 4. Header/Footer Not Reflecting Customization ✅ - Fetch email settings in EditTemplate - Apply logo_url or header_text to header - Apply footer_text with {current_year} replacement - Render social icons in footer ### 5. Hero Heading Not Using Custom Color ✅ - Apply hero_text_color to all hero card types - .card-hero, .card-success, .card-highlight - All text and headings use custom color ## Preview Now Shows: ✅ Custom logo (if set) or header text ✅ Custom hero gradient colors ✅ Custom hero text color (white/custom) ✅ Custom button colors (primary & secondary) ✅ Custom footer text with {current_year} ✅ Social icons in footer ## Files: - `routes/Settings/Notifications/EditTemplate.tsx` - Preview integration - `routes/Settings/Notifications/EmailCustomization.tsx` - UI fix Everything synced! Preview matches actual emails! 🎉
This commit is contained in:
@@ -38,6 +38,12 @@ export default function EditTemplate() {
|
|||||||
const [activeTab, setActiveTab] = useState('editor');
|
const [activeTab, setActiveTab] = useState('editor');
|
||||||
const [codeMode, setCodeMode] = useState(false);
|
const [codeMode, setCodeMode] = useState(false);
|
||||||
|
|
||||||
|
// Fetch email customization settings
|
||||||
|
const { data: emailSettings } = useQuery({
|
||||||
|
queryKey: ['email-settings'],
|
||||||
|
queryFn: () => api.get('/notifications/email-settings'),
|
||||||
|
});
|
||||||
|
|
||||||
// Fetch template
|
// Fetch template
|
||||||
const { data: template, isLoading, error } = useQuery({
|
const { data: template, isLoading, error } = useQuery({
|
||||||
queryKey: ['notification-template', eventId, channelId],
|
queryKey: ['notification-template', eventId, channelId],
|
||||||
@@ -187,7 +193,7 @@ export default function EditTemplate() {
|
|||||||
|
|
||||||
// Replace dynamic variables with sample data (not just highlighting)
|
// Replace dynamic variables with sample data (not just highlighting)
|
||||||
const sampleData: { [key: string]: string } = {
|
const sampleData: { [key: string]: string } = {
|
||||||
order_number: '#12345',
|
order_number: '12345',
|
||||||
order_total: '$99.99',
|
order_total: '$99.99',
|
||||||
order_status: 'Processing',
|
order_status: 'Processing',
|
||||||
order_date: new Date().toLocaleDateString(),
|
order_date: new Date().toLocaleDateString(),
|
||||||
@@ -262,6 +268,33 @@ export default function EditTemplate() {
|
|||||||
// Parse [card] tags
|
// Parse [card] tags
|
||||||
previewBody = parseCardsForPreview(previewBody);
|
previewBody = parseCardsForPreview(previewBody);
|
||||||
|
|
||||||
|
// Get email settings for preview
|
||||||
|
const settings = emailSettings || {};
|
||||||
|
const primaryColor = settings.primary_color || '#7f54b3';
|
||||||
|
const secondaryColor = settings.secondary_color || '#7f54b3';
|
||||||
|
const heroGradientStart = settings.hero_gradient_start || '#667eea';
|
||||||
|
const heroGradientEnd = settings.hero_gradient_end || '#764ba2';
|
||||||
|
const heroTextColor = settings.hero_text_color || '#ffffff';
|
||||||
|
const buttonTextColor = settings.button_text_color || '#ffffff';
|
||||||
|
const logoUrl = settings.logo_url || '';
|
||||||
|
const headerText = settings.header_text || 'My WordPress Store';
|
||||||
|
const footerText = settings.footer_text || `© ${new Date().getFullYear()} My WordPress Store. All rights reserved.`;
|
||||||
|
const socialLinks = settings.social_links || [];
|
||||||
|
|
||||||
|
// Replace {current_year} in footer
|
||||||
|
const processedFooter = footerText.replace('{current_year}', new Date().getFullYear().toString());
|
||||||
|
|
||||||
|
// Generate social icons HTML
|
||||||
|
const socialIconsHtml = socialLinks.length > 0 ? `
|
||||||
|
<div style="margin-top: 16px;">
|
||||||
|
${socialLinks.map((link: any) => `
|
||||||
|
<a href="${link.url}" style="display: inline-block; margin: 0 8px; text-decoration: none;">
|
||||||
|
<span style="font-size: 24px;">${getSocialIcon(link.platform)}</span>
|
||||||
|
</a>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
` : '';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
@@ -272,17 +305,20 @@ export default function EditTemplate() {
|
|||||||
.header { padding: 32px; text-align: center; background: #f8f8f8; }
|
.header { padding: 32px; text-align: center; background: #f8f8f8; }
|
||||||
.card-gutter { padding: 0 16px; }
|
.card-gutter { padding: 0 16px; }
|
||||||
.card { background: #ffffff; border-radius: 8px; margin-bottom: 24px; padding: 32px 40px; }
|
.card { background: #ffffff; border-radius: 8px; margin-bottom: 24px; padding: 32px 40px; }
|
||||||
.card-success { background: #e8f5e9; border: 1px solid #4caf50; }
|
.card-success { background: linear-gradient(135deg, ${heroGradientStart} 0%, ${heroGradientEnd} 100%); color: ${heroTextColor}; }
|
||||||
.card-highlight { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; }
|
.card-success * { color: ${heroTextColor} !important; }
|
||||||
.card-highlight * { color: #fff !important; }
|
.card-highlight { background: linear-gradient(135deg, ${heroGradientStart} 0%, ${heroGradientEnd} 100%); color: ${heroTextColor}; }
|
||||||
|
.card-highlight * { color: ${heroTextColor} !important; }
|
||||||
|
.card-hero { background: linear-gradient(135deg, ${heroGradientStart} 0%, ${heroGradientEnd} 100%); color: ${heroTextColor}; }
|
||||||
|
.card-hero * { color: ${heroTextColor} !important; }
|
||||||
.card-info { background: #f0f7ff; border: 1px solid #0071e3; }
|
.card-info { background: #f0f7ff; border: 1px solid #0071e3; }
|
||||||
.card-warning { background: #fff8e1; border: 1px solid #ff9800; }
|
.card-warning { background: #fff8e1; border: 1px solid #ff9800; }
|
||||||
h1 { font-size: 26px; margin-top: 0; margin-bottom: 16px; color: #333; }
|
h1 { font-size: 26px; margin-top: 0; margin-bottom: 16px; color: #333; }
|
||||||
h2 { font-size: 18px; margin-top: 0; margin-bottom: 16px; color: #333; }
|
h2 { font-size: 18px; margin-top: 0; margin-bottom: 16px; color: #333; }
|
||||||
h3 { font-size: 16px; margin-top: 0; margin-bottom: 8px; color: #333; }
|
h3 { font-size: 16px; margin-top: 0; margin-bottom: 8px; color: #333; }
|
||||||
p { font-size: 16px; line-height: 1.6; color: #555; margin-bottom: 16px; }
|
p { font-size: 16px; line-height: 1.6; color: #555; margin-bottom: 16px; }
|
||||||
.button { display: inline-block; background: #7f54b3; color: #fff !important; padding: 14px 28px; border-radius: 6px; text-decoration: none; font-weight: 600; }
|
.button { display: inline-block; background: ${primaryColor}; color: ${buttonTextColor} !important; padding: 14px 28px; border-radius: 6px; text-decoration: none; font-weight: 600; }
|
||||||
.button-outline { display: inline-block; background: transparent; color: #7f54b3 !important; padding: 12px 26px; border: 2px solid #7f54b3; border-radius: 6px; text-decoration: none; font-weight: 600; }
|
.button-outline { display: inline-block; background: transparent; color: ${secondaryColor} !important; padding: 12px 26px; border: 2px solid ${secondaryColor}; border-radius: 6px; text-decoration: none; font-weight: 600; }
|
||||||
.info-box { background: #f6f6f6; border-radius: 6px; padding: 20px; margin: 16px 0; }
|
.info-box { background: #f6f6f6; border-radius: 6px; padding: 20px; margin: 16px 0; }
|
||||||
.footer { padding: 32px; text-align: center; color: #888; font-size: 13px; }
|
.footer { padding: 32px; text-align: center; color: #888; font-size: 13px; }
|
||||||
</style>
|
</style>
|
||||||
@@ -290,13 +326,14 @@ export default function EditTemplate() {
|
|||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<strong style="font-size: 24px; color: #333;">My WordPress Store</strong>
|
${logoUrl ? `<img src="${logoUrl}" alt="${headerText}" style="max-width: 200px; max-height: 60px;">` : `<strong style="font-size: 24px; color: #333;">${headerText}</strong>`}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-gutter">
|
<div class="card-gutter">
|
||||||
${previewBody}
|
${previewBody}
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<p>© ${new Date().getFullYear()} My WordPress Store. All rights reserved.</p>
|
<p>${processedFooter}</p>
|
||||||
|
${socialIconsHtml}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
@@ -304,6 +341,19 @@ export default function EditTemplate() {
|
|||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper function to get social icon emoji
|
||||||
|
const getSocialIcon = (platform: string) => {
|
||||||
|
const icons: Record<string, string> = {
|
||||||
|
facebook: '📘',
|
||||||
|
twitter: '🐦',
|
||||||
|
instagram: '📷',
|
||||||
|
linkedin: '💼',
|
||||||
|
youtube: '📺',
|
||||||
|
website: '🌐',
|
||||||
|
};
|
||||||
|
return icons[platform] || '🔗';
|
||||||
|
};
|
||||||
|
|
||||||
if (!eventId || !channelId) {
|
if (!eventId || !channelId) {
|
||||||
return (
|
return (
|
||||||
<SettingsLayout
|
<SettingsLayout
|
||||||
|
|||||||
@@ -496,10 +496,7 @@ export default function EmailCustomization() {
|
|||||||
onValueChange={(value) => updateSocialLink(index, 'platform', value)}
|
onValueChange={(value) => updateSocialLink(index, 'platform', value)}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="h-9">
|
<SelectTrigger className="h-9">
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
{getSocialIcon(link.platform)}
|
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
</div>
|
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="facebook">
|
<SelectItem value="facebook">
|
||||||
|
|||||||
Reference in New Issue
Block a user