/**
* Email Template Helper Functions
*
* Reusable functions for generating dynamic email sections
*/
import { ApprovalChainItem } from './types';
/**
* Get rich text styles for email-safe HTML rendering
* Styles common HTML elements from rich text editors
*/
export function getRichTextStyles(): string {
return `
`;
}
/**
* Wrap rich text content with proper styling
* Use this for descriptions and comments from rich text editors
*/
export function wrapRichText(htmlContent: string): string {
return `
${htmlContent}
`;
}
/**
* Get inline styles for email container table
* This ensures width is preserved when emails are forwarded
* Email clients often strip CSS classes, so inline styles are critical
*/
export function getEmailContainerStyles(): string {
return 'width: 95%; max-width: 1200px; min-width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);';
}
/**
* Generate all email styles (responsive + rich text)
* Desktop-first design (optimized for browser) with mobile responsive breakpoints
*/
export function getResponsiveStyles(): string {
return `
${getRichTextStyles()}
`;
}
/**
* Email header configuration types
*/
export interface EmailHeaderConfig {
title: string;
subtitle?: string;
gradientFrom: string;
gradientTo: string;
logoUrl?: string;
logoAlt?: string;
logoWidth?: number;
logoHeight?: number;
productName?: string; // e.g., "RE Flow"
}
/**
* Generate professional email header with Royal Enfield branding
* Black background with logo, product name, and gold accent line
* Fully responsive for mobile devices
*/
export function getEmailHeader(config: EmailHeaderConfig): string {
const logoWidth = config.logoWidth || 220;
const logoHeight = config.logoHeight || 65;
const logoSection = config.logoUrl ? `
` : '';
const productNameSection = config.productName ? `
${config.productName}
` : '';
const dividerLine = `
`;
const subtitleSection = config.subtitle ? `
` : '';
return `
`;
}
/**
* Royal Enfield Brand Colors (Official)
*/
export const BrandColors = {
red: '#DB281B', // Royal Enfield Red (Official)
black: '#1a1a1a', // Royal Enfield Black
gold: '#DEB219', // Royal Enfield Gold
darkRed: '#A51F16', // Darker red for accents
darkGold: '#C89F16', // Darker gold for accents
white: '#ffffff' // White for text
};
/**
* Predefined header styles using Royal Enfield brand colors
*/
export const HeaderStyles = {
// Primary - Red & Black (Main brand colors)
primary: {
gradientFrom: BrandColors.red,
gradientTo: BrandColors.darkRed
},
// Information/Neutral - Black & Gold accent
info: {
gradientFrom: BrandColors.black,
gradientTo: '#2d2d2d'
},
// Success - Black with gold accent
success: {
gradientFrom: BrandColors.black,
gradientTo: '#2d2d2d'
},
// Error/Critical - Red (Brand red)
error: {
gradientFrom: BrandColors.red,
gradientTo: BrandColors.darkRed
},
// Warning - Gold
warning: {
gradientFrom: BrandColors.gold,
gradientTo: BrandColors.darkGold
},
// Neutral - Black
neutral: {
gradientFrom: BrandColors.black,
gradientTo: '#2d2d2d'
},
// Info Secondary - Dark grey
infoSecondary: {
gradientFrom: '#424242',
gradientTo: '#1a1a1a'
},
// Complete - Black with gold
complete: {
gradientFrom: BrandColors.black,
gradientTo: '#2d2d2d'
}
};
/**
* Generate priority alert section
*/
export function getPrioritySection(priority: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'): string {
if (priority === 'HIGH' || priority === 'CRITICAL') {
return `
High Priority
This request has been marked as ${priority} priority and requires prompt attention.
`;
}
return '';
}
/**
* Generate approval chain visualization
*/
export function getApprovalChain(approvers: ApprovalChainItem[]): string {
return approvers.map(approver => {
let icon = '';
let textColor = '#333333';
let status = '';
switch (approver.status) {
case 'approved':
icon = `✓`;
status = approver.date ? `Approved on ${approver.date}` : 'Approved';
break;
case 'current':
icon = `${approver.levelNumber}`;
textColor = '#667eea';
status = 'Pending (Your Turn)';
break;
case 'pending':
icon = `${approver.levelNumber}`;
status = 'Pending';
break;
case 'awaiting':
icon = `${approver.levelNumber}`;
textColor = '#999999';
status = 'Awaiting';
break;
}
return `
${icon}
${approver.name} - ${status}
`;
}).join('');
}
/**
* Generate next steps section for approval confirmation
*/
export function getNextStepsSection(isFinalApproval: boolean, nextApproverName?: string): string {
if (isFinalApproval) {
return `
Next Steps
All approvals are complete! Please review the request and add any conclusion remarks before closing it.
`;
} else if (nextApproverName) {
return `
Next Steps
The request has been forwarded to ${nextApproverName} for the next level of approval.
You'll be notified when the request progresses.
`;
}
return '';
}
/**
* Generate permissions section for participant added
*/
export function getPermissionsContent(role: 'Approver' | 'Spectator'): string {
if (role === 'Approver') {
return `
- Review request details and documents
- Approve or reject the request
- Add comments and work notes
- View approval workflow and history
- Receive real-time notifications
`;
} else {
return `
- View request details and documents
- Add comments and work notes
- View approval workflow progress
- Receive status update notifications
- Cannot approve or reject the request
`;
}
}
/**
* Generate conclusion section for closed requests (supports rich text)
*/
export function getConclusionSection(conclusionRemark?: string): string {
if (conclusionRemark) {
return `
Conclusion Remarks:
${wrapRichText(conclusionRemark)}
`;
}
return '';
}
/**
* Generate role description for participant added
*/
export function getRoleDescription(role: 'Approver' | 'Spectator'): string {
if (role === 'Approver') {
return 'You can now review and take action on this request.';
} else {
return 'You can now view this request and participate in discussions.';
}
}
/**
* Generate action required section for workflow resumed
*/
export function getActionRequiredSection(isApprover: boolean): string {
if (isApprover) {
return `
Action Required
This request requires your immediate attention. Please review and take action to keep the workflow moving forward.
`;
}
return '';
}
/**
* Common email footer with optional branding
*/
export interface EmailFooterConfig {
companyName: string;
companyWebsite?: string;
supportEmail?: string;
additionalLinks?: Array<{ text: string; url: string }>;
}
export function getEmailFooter(config: EmailFooterConfig | string): string {
// Backward compatibility - if string is passed, use it as companyName
const footerConfig: EmailFooterConfig = typeof config === 'string'
? { companyName: config }
: config;
const supportSection = footerConfig.supportEmail ? `
Need help? Contact us at ${footerConfig.supportEmail}
` : '';
const linksSection = footerConfig.additionalLinks && footerConfig.additionalLinks.length > 0 ? `
${footerConfig.additionalLinks.map(link =>
`${link.text}`
).join(' | ')}
` : '';
const companyLink = footerConfig.companyWebsite
? `${footerConfig.companyName}`
: footerConfig.companyName;
return `
|
This is an automated notification. Please do not reply to this email.
${supportSection}
${linksSection}
© 2025 ${companyLink}. All rights reserved.
|
`;
}