diff --git a/backend/src/services/emailProcessor.js b/backend/src/services/emailProcessor.js index ea4537d0..5e07f517 100644 --- a/backend/src/services/emailProcessor.js +++ b/backend/src/services/emailProcessor.js @@ -162,29 +162,52 @@ function darkenColor(hex, amount = 0.15) { // Wrap HTML body in the styled email template with header, footer, and logo async function wrapEmailHtml(htmlBody, subject, language = 'en') { - // Get branding settings for logo and email colors + // Email colour palette. The two original settings (email_primary_color and + // email_secondary_color) keep their existing semantics so emails sent by + // upgraded instances render byte-for-byte identically until an admin + // touches the new fields. The six new tokens unlock full email theming + // (body bg, container card, list panel, body text, muted text, button text) + // and default to the previously hard-coded literals when absent. let logoUrl = ''; let companyName = 'PicPeak'; let primaryColor = '#5C8762'; let secondaryColor = '#f9f9f9'; + let bodyBgColor = '#f5f5f5'; // outer wrapper + body background + let containerBgColor = '#ffffff'; // email card + let listBgColor = '#f9f9f9'; //
${ci18n.desc}
- ${ci18n.link} + ${ci18n.link}
${ci18n.pin}: ${processedVariables.client_password}
⚠️ ${ci18n.warning}
diff --git a/frontend/src/pages/admin/EmailConfigPage.tsx b/frontend/src/pages/admin/EmailConfigPage.tsx index 66bd5e99..60814535 100644 --- a/frontend/src/pages/admin/EmailConfigPage.tsx +++ b/frontend/src/pages/admin/EmailConfigPage.tsx @@ -18,7 +18,7 @@ import { toast } from 'react-toastify'; import { Button, Input, Card, Loading } from '../../components/common'; import { EmailPreviewModal } from '../../components/admin/EmailPreviewModal'; import { EmailTemplateEditor } from '../../components/admin/EmailTemplateEditor'; -import { Palette } from 'lucide-react'; +import { Palette, RefreshCw, Info } from 'lucide-react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { emailService, type EmailConfig, type EmailTemplate, type EmailTemplateTranslation } from '../../services/email.service'; import { settingsService } from '../../services/settings.service'; @@ -110,8 +110,19 @@ export const EmailConfigPage: React.FC = () => { htmlContent: '', textContent: '' }); + // 8-token email palette. The first two are the historical settings — + // upgraded installs keep their saved values. The last six are new and + // default to the literals previously hard-coded into emailProcessor.js, + // which means an admin who never opens this card sees emails render + // exactly as before. Touching any picker enables full email theming. const [emailPrimaryColor, setEmailPrimaryColor] = useState('#5C8762'); const [emailSecondaryColor, setEmailSecondaryColor] = useState('#f9f9f9'); + const [emailBodyBgColor, setEmailBodyBgColor] = useState('#f5f5f5'); + const [emailContainerBgColor, setEmailContainerBgColor] = useState('#ffffff'); + const [emailListBgColor, setEmailListBgColor] = useState('#f9f9f9'); + const [emailBodyTextColor, setEmailBodyTextColor] = useState('#333333'); + const [emailMutedTextColor, setEmailMutedTextColor] = useState('#666666'); + const [emailButtonTextColor, setEmailButtonTextColor] = useState('#ffffff'); const queryClient = useQueryClient(); // SMTP Configuration state @@ -142,6 +153,12 @@ export const EmailConfigPage: React.FC = () => { if (allSettings) { if (allSettings.email_primary_color) setEmailPrimaryColor(allSettings.email_primary_color); if (allSettings.email_secondary_color) setEmailSecondaryColor(allSettings.email_secondary_color); + if (allSettings.email_body_bg_color) setEmailBodyBgColor(allSettings.email_body_bg_color); + if (allSettings.email_container_bg_color) setEmailContainerBgColor(allSettings.email_container_bg_color); + if (allSettings.email_list_bg_color) setEmailListBgColor(allSettings.email_list_bg_color); + if (allSettings.email_body_text_color) setEmailBodyTextColor(allSettings.email_body_text_color); + if (allSettings.email_muted_text_color) setEmailMutedTextColor(allSettings.email_muted_text_color); + if (allSettings.email_button_text_color) setEmailButtonTextColor(allSettings.email_button_text_color); } }, [allSettings]); @@ -213,7 +230,7 @@ export const EmailConfigPage: React.FC = () => { }); const saveEmailColorsMutation = useMutation({ - mutationFn: (colors: { email_primary_color: string; email_secondary_color: string }) => + mutationFn: (colors: Record{t('email.brandingDescription')}
+ {/* 8 email colour pickers. Each row uses the same compact label + + info-tooltip pattern as the gallery palette in + ThemeCustomizerEnhanced — keeps the two configurators visually + consistent without sharing the React component (the email + state is local to this page and saved through a different + endpoint, so reuse would be more friction than value). */}{t('email.primaryColorHint')}
-{t('email.secondaryColorHint')}
-