130 lines
3.6 KiB
TypeScript
130 lines
3.6 KiB
TypeScript
'use client';
|
|
|
|
import React, { useMemo, CSSProperties } from 'react';
|
|
import { renderEmailContent } from '@/lib/utils/email-utils';
|
|
import { EmailContent } from '@/types/email';
|
|
|
|
interface EmailContentDisplayProps {
|
|
content: EmailContent;
|
|
className?: string;
|
|
showQuotedText?: boolean;
|
|
type?: 'html' | 'text' | 'auto';
|
|
debug?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Unified component for displaying email content in a consistent way
|
|
* This handles both HTML and plain text content with proper styling
|
|
*/
|
|
const EmailContentDisplay: React.FC<EmailContentDisplayProps> = ({
|
|
content,
|
|
className = '',
|
|
showQuotedText = true,
|
|
type = 'auto',
|
|
debug = false
|
|
}) => {
|
|
// Ensure we have valid content to work with
|
|
const safeContent = useMemo(() => {
|
|
if (!content) {
|
|
return {
|
|
html: undefined,
|
|
text: 'No content available',
|
|
isHtml: false,
|
|
direction: 'ltr'
|
|
} as EmailContent;
|
|
}
|
|
return content;
|
|
}, [content]);
|
|
|
|
// Render the content with proper formatting
|
|
const htmlContent = useMemo(() => {
|
|
if (!safeContent) return '';
|
|
|
|
try {
|
|
// Override content type if specified
|
|
let contentToRender: EmailContent = { ...safeContent };
|
|
|
|
if (type === 'html' && !contentToRender.isHtml) {
|
|
// Force HTML rendering for text content
|
|
contentToRender = {
|
|
...contentToRender,
|
|
isHtml: true,
|
|
html: `<p>${contentToRender.text.replace(/\n/g, '<br>')}</p>`
|
|
};
|
|
} else if (type === 'text' && contentToRender.isHtml) {
|
|
// Force text rendering
|
|
contentToRender = {
|
|
...contentToRender,
|
|
isHtml: false
|
|
};
|
|
}
|
|
|
|
return renderEmailContent(contentToRender);
|
|
} catch (error) {
|
|
console.error('Error rendering content:', error);
|
|
return `<div class="error-message p-4 text-red-500">Error rendering email content: ${error instanceof Error ? error.message : 'Unknown error'}</div>`;
|
|
}
|
|
}, [safeContent, type]);
|
|
|
|
// Apply quoted text styling if needed
|
|
const containerStyle: CSSProperties = showQuotedText
|
|
? {}
|
|
: { maxHeight: '400px', overflowY: 'auto' };
|
|
|
|
return (
|
|
<div
|
|
className={`email-content-display ${className} ${showQuotedText ? 'quoted-text' : ''}`}
|
|
style={containerStyle}
|
|
>
|
|
<div
|
|
className="email-content-inner"
|
|
dangerouslySetInnerHTML={{ __html: htmlContent }}
|
|
/>
|
|
|
|
{/* Debug output if enabled */}
|
|
{debug && (
|
|
<div className="content-debug mt-4 p-2 text-xs bg-gray-100 border rounded">
|
|
<p><strong>Content Type:</strong> {safeContent.isHtml ? 'HTML' : 'Text'}</p>
|
|
<p><strong>Direction:</strong> {safeContent.direction}</p>
|
|
<p><strong>Has HTML:</strong> {!!safeContent.html}</p>
|
|
<p><strong>Text Length:</strong> {safeContent.text?.length || 0}</p>
|
|
</div>
|
|
)}
|
|
|
|
<style jsx>{`
|
|
.email-content-display {
|
|
width: 100%;
|
|
}
|
|
|
|
.email-content-display.quoted-text {
|
|
opacity: 0.85;
|
|
font-size: 0.95em;
|
|
}
|
|
|
|
.email-content-inner :global(img) {
|
|
max-width: 100%;
|
|
height: auto;
|
|
}
|
|
|
|
.email-content-inner :global(table) {
|
|
max-width: 100%;
|
|
border-collapse: collapse;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.email-content-inner :global(td),
|
|
.email-content-inner :global(th) {
|
|
padding: 0.5rem;
|
|
border: 1px solid #ddd;
|
|
}
|
|
|
|
.content-debug {
|
|
font-family: monospace;
|
|
color: #666;
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default EmailContentDisplay;
|