From 098820f339fc7ff0aea54921a780d7be31e9db6e Mon Sep 17 00:00:00 2001 From: Brendan Graham Date: Fri, 1 May 2026 14:04:56 +1000 Subject: [PATCH] feat: add holiday theme selector for email signatures Add dropdown to select festive themes (Christmas, Halloween, Easter, Valentine's Day, New Year) that add emoji decorations around the name in email signatures. Co-Authored-By: Claude Opus 4.5 --- src/Form/Form.js | 43 ++++++++++++++++++-- src/RepliesAndForwards/RepliesAndForwards.js | 6 +++ src/Signature/Signature.js | 6 +++ src/SignatureContainer/SignatureContainer.js | 2 + src/constants/index.js | 9 ++++ src/util/index.js | 9 +++- 6 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/Form/Form.js b/src/Form/Form.js index dadd532..22e2561 100644 --- a/src/Form/Form.js +++ b/src/Form/Form.js @@ -24,6 +24,11 @@ export const Form = () => { twitter: { label: 'Twitter' }, qualifications: { label: 'Qualifications' }, addGPTW: { label: 'Add GPTW', type: 'checkbox' }, + holidayTheme: { + label: 'Holiday Theme', + type: 'select', + options: 'holidayThemes', + }, }; let formInputs = { @@ -35,6 +40,7 @@ export const Form = () => { email: { text: '', order: 7 }, twitter: { text: '', order: 8 }, addGPTW: { text: '', order: 9 }, + holidayTheme: { text: '', order: 10 }, }; var profile = useSelector((state) => { @@ -45,7 +51,13 @@ export const Form = () => { dispatch(updateProfile({ name, value })); }; - const inputHtml = (inputName, inputVal, placeholder, type = 'text') => { + const inputHtml = ( + inputName, + inputVal, + placeholder, + type = 'text', + options = null + ) => { if (type === 'checkbox') { return ( { /> ); } + if (type === 'select' && options) { + const optionsData = constants[options]; + return ( +
+ +
+ ); + } return ( { .map((obj) => ({ key: obj[0], ...omit(obj[1], 'order') })) .map((inputObj) => { const inputName = inputObj.key; - const { label, type = 'text', required = false } = labels[inputName]; + const { + label, + type = 'text', + required = false, + options, + } = labels[inputName]; return (
@@ -98,7 +134,8 @@ export const Form = () => { inputName, values[inputName], placeholders[inputName], - type + type, + options )}
diff --git a/src/RepliesAndForwards/RepliesAndForwards.js b/src/RepliesAndForwards/RepliesAndForwards.js index 28642a0..332ef54 100644 --- a/src/RepliesAndForwards/RepliesAndForwards.js +++ b/src/RepliesAndForwards/RepliesAndForwards.js @@ -3,6 +3,7 @@ import React from 'react'; import constants from '../constants'; import { parseMobile } from '../util'; const brandInfo = constants.brandInfo; +const holidayThemes = constants.holidayThemes; const RepliesAndForwards = (props) => { const { @@ -15,7 +16,10 @@ const RepliesAndForwards = (props) => { brandName, brandLink, brandLinkName, + holidayTheme, } = props; + + const theme = holidayThemes[holidayTheme] || holidayThemes.none; const styleObj = { color: 'black', fontFamily: 'Helvetica, Arial, sans-serif', @@ -29,8 +33,10 @@ const RepliesAndForwards = (props) => {

+ {theme.prefix} {name} {pronounOptional}| {brandName} {titleOptional} + {theme.suffix}
M  diff --git a/src/Signature/Signature.js b/src/Signature/Signature.js index 8437791..6170f5e 100644 --- a/src/Signature/Signature.js +++ b/src/Signature/Signature.js @@ -3,6 +3,7 @@ import constants from '../constants'; import { parseMobile } from '../util'; const brandInfo = constants.brandInfo; +const holidayThemes = constants.holidayThemes; const Signature = (props) => { const { @@ -17,8 +18,11 @@ const Signature = (props) => { brandLink, brandLinkName, addGPTW, + holidayTheme, } = props; + const theme = holidayThemes[holidayTheme] || holidayThemes.none; + const titleElement = title ? ( <>
@@ -60,8 +64,10 @@ const Signature = (props) => {
 

+ {theme.prefix} {name} {pronounOptional} + {theme.suffix} {titleElement} {qualificationsElemenent} diff --git a/src/SignatureContainer/SignatureContainer.js b/src/SignatureContainer/SignatureContainer.js index 2ae3886..ffc0348 100644 --- a/src/SignatureContainer/SignatureContainer.js +++ b/src/SignatureContainer/SignatureContainer.js @@ -39,6 +39,7 @@ const SignatureContainer = (props) => { brandLinkName, brandAnimatedLogo, addGPTW, + holidayTheme, } = profile; const placeholders = constants.placeholders; @@ -64,6 +65,7 @@ const SignatureContainer = (props) => { ), addGPTW, brandGPTWLogo, + holidayTheme: holidayTheme || 'none', ...assignPlaceholders( { brandLogo, brandName, brandLink, brandLinkName, brandAnimatedLogo }, brandInfo diff --git a/src/constants/index.js b/src/constants/index.js index 282647e..2c8812c 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -29,6 +29,15 @@ const constants = { default: { countryCode: '+61', }, + + holidayThemes: { + none: { label: 'None', prefix: '', suffix: '' }, + christmas: { label: 'Christmas', prefix: '🎄 ', suffix: ' ❄️' }, + halloween: { label: 'Halloween', prefix: '🎃 ', suffix: ' 👻' }, + easter: { label: 'Easter', prefix: '🐰 ', suffix: ' 🥚' }, + valentines: { label: "Valentine's Day", prefix: '❤️ ', suffix: ' 💕' }, + newYear: { label: 'New Year', prefix: '🎉 ', suffix: ' ✨' }, + }, }; export default constants; diff --git a/src/util/index.js b/src/util/index.js index 7e7f821..337d004 100644 --- a/src/util/index.js +++ b/src/util/index.js @@ -8,6 +8,7 @@ import { } from 'react-phone-number-input'; const brandInfo = constants.brandInfo; +const holidayThemes = constants.holidayThemes; const multiSplice = (toAddIndexes, val, array) => toAddIndexes.forEach((index) => array.splice(index, 0, val)); @@ -73,14 +74,16 @@ export const copySignatureText = (props) => { isSupport, supportHotline, supportEmail, + holidayTheme, } = props; + const theme = holidayThemes[holidayTheme] || holidayThemes.none; const pronounOptional = pronoun ? ` (${pronoun})` : ''; const mobileText = parseMobile(mobile).replace(/ /g, ' '); const textArr = [ '--', '', - `${name ? name : null}${pronounOptional}`, + `${theme.prefix}${name ? name : null}${pronounOptional}${theme.suffix}`, brandInfo.brandName, title ? title : null, qualifications ? `${qualifications}` : null, @@ -114,14 +117,16 @@ export const copyRepliesAndForwardsText = (props) => { isSupport, supportHotline, supportEmail, + holidayTheme, } = props; + const theme = holidayThemes[holidayTheme] || holidayThemes.none; const mobileText = parseMobile(mobile).replace(/ /g, ' '); const titleOptional = title ? ` | ${title}` : ''; const pronounOptional = pronoun ? ` (${pronoun})` : ''; const textArr = [ '--', - `${name}${pronounOptional} | ${brandInfo.brandName}${titleOptional}`, + `${theme.prefix}${name}${pronounOptional} | ${brandInfo.brandName}${titleOptional}${theme.suffix}`, `M ${mobileText} | E ${email}${twitter ? ` | T ${twitter}` : ''} | W ${ brandInfo.brandLinkName }`,