courrier preview

This commit is contained in:
alma 2025-04-30 23:18:20 +02:00
parent f9e0b323ce
commit 3584f72bf5

View File

@ -12,10 +12,7 @@ import { Label } from '@/components/ui/label';
// Import sub-components
import ComposeEmailHeader from './ComposeEmailHeader';
import ComposeEmailForm from './ComposeEmailForm';
import ComposeEmailFooter from './ComposeEmailFooter';
import RichEmailEditor from './RichEmailEditor';
import QuotedEmailContent from './QuotedEmailContent';
// Import from the centralized utils
import {
@ -33,9 +30,6 @@ import { EmailMessage, EmailAddress } from '@/types/email';
*
* All code that needs to compose emails should import this component from:
* @/components/email/ComposeEmail
*
* It uses the centralized email formatter from @/lib/utils/email-formatter.ts
* for consistent handling of email content and text direction.
*/
// Define interface for the modern props
@ -57,12 +51,6 @@ interface ComposeEmailProps {
}) => Promise<void>;
}
// Add a helper to fix table widths in HTML
function fixTableWidths(html: string): string {
if (!html) return html;
return html.replace(/<table(?![^>]*width)/g, '<table width="100%"');
}
export default function ComposeEmail(props: ComposeEmailProps) {
const { initialEmail, type = 'new', onClose, onSend } = props;
@ -72,6 +60,7 @@ export default function ComposeEmail(props: ComposeEmailProps) {
const [bcc, setBcc] = useState<string>('');
const [subject, setSubject] = useState<string>('');
const [emailContent, setEmailContent] = useState<string>('');
const [quotedContent, setQuotedContent] = useState<string>('');
const [showCc, setShowCc] = useState<boolean>(false);
const [showBcc, setShowBcc] = useState<boolean>(false);
const [sending, setSending] = useState<boolean>(false);
@ -81,6 +70,8 @@ export default function ComposeEmail(props: ComposeEmailProps) {
type: string;
}>>([]);
const editorRef = useRef<HTMLDivElement>(null);
// Initialize the form when replying to or forwarding an email
useEffect(() => {
if (initialEmail && type !== 'new') {
@ -100,8 +91,11 @@ export default function ComposeEmail(props: ComposeEmailProps) {
// Set subject
setSubject(formatted.subject);
// Set the email content (use HTML if available)
setEmailContent(formatted.content.html || formatted.content.text);
// Set the quoted content (original email)
setQuotedContent(formatted.content.html || formatted.content.text);
// Start with empty content for the reply
setEmailContent('');
}
else if (type === 'forward') {
// Get formatted data for forward
@ -110,8 +104,11 @@ export default function ComposeEmail(props: ComposeEmailProps) {
// Set subject
setSubject(formatted.subject);
// Set the email content (use HTML if available)
setEmailContent(formatted.content.html || formatted.content.text);
// Set the quoted content (original email)
setQuotedContent(formatted.content.html || formatted.content.text);
// Start with empty content for the forward
setEmailContent('');
// If the original email has attachments, we should include them
if (initialEmail.attachments && initialEmail.attachments.length > 0) {
@ -154,12 +151,17 @@ export default function ComposeEmail(props: ComposeEmailProps) {
setSending(true);
try {
// Combine the new content with the quoted content
const fullContent = type !== 'new'
? `${emailContent}<div class="quoted-content">${quotedContent}</div>`
: emailContent;
await onSend({
to,
cc: cc || undefined,
bcc: bcc || undefined,
subject,
body: emailContent,
body: fullContent,
attachments
});
@ -173,34 +175,26 @@ export default function ComposeEmail(props: ComposeEmailProps) {
}
};
// Additional effect to ensure we scroll to the top and focus the editor
// Focus and scroll to top when opened
useEffect(() => {
// Focus the editor and ensure it's scrolled to the top
const editorContainer = document.querySelector('.ql-editor') as HTMLElement;
if (editorContainer) {
// Set timeout to ensure DOM is fully rendered
setTimeout(() => {
// Focus the editor
editorContainer.focus();
setTimeout(() => {
if (editorRef.current) {
editorRef.current.focus();
// Make sure all scroll containers are at the top
editorContainer.scrollTop = 0;
// Find all possible scrollable parent containers
const scrollContainers = [
document.querySelector('.ql-container') as HTMLElement,
document.querySelector('.rich-email-editor-container') as HTMLElement,
document.querySelector('.h-full.flex.flex-col.p-6') as HTMLElement
// Scroll to top
const scrollElements = [
editorRef.current,
document.querySelector('.overflow-y-auto'),
document.querySelector('.compose-email-body')
];
// Scroll all containers to top
scrollContainers.forEach(container => {
if (container) {
container.scrollTop = 0;
scrollElements.forEach(el => {
if (el instanceof HTMLElement) {
el.scrollTop = 0;
}
});
}, 100);
}
}
}, 100);
}, []);
return (
@ -209,7 +203,7 @@ export default function ComposeEmail(props: ComposeEmailProps) {
type={type}
onClose={onClose}
/>
<div className="flex-1 overflow-y-auto p-4">
<div className="flex-1 overflow-y-auto p-4 compose-email-body">
<div className="h-full flex flex-col p-4 space-y-2 overflow-y-auto">
{/* To Field */}
<div className="flex-none">
@ -281,17 +275,30 @@ export default function ComposeEmail(props: ComposeEmailProps) {
/>
</div>
{/* Message Body */}
{/* Message Body - Simplified Editor */}
<div className="flex-1 min-h-[200px] flex flex-col overflow-hidden">
<Label htmlFor="message" className="flex-none block text-sm font-medium text-gray-700 mb-2">Message</Label>
<div className="flex-1 border border-gray-300 rounded-md overflow-hidden">
<RichEmailEditor
initialContent={emailContent}
onChange={setEmailContent}
minHeight="200px"
maxHeight="none"
preserveFormatting={true}
/>
<div className="email-editor-container flex flex-col h-full">
{/* Simple editor for new content */}
<div
ref={editorRef}
className="simple-editor p-3 min-h-[100px] outline-none"
contentEditable={true}
dangerouslySetInnerHTML={{ __html: emailContent }}
onInput={(e) => setEmailContent(e.currentTarget.innerHTML)}
/>
{/* Quoted content from original email */}
{quotedContent && (
<div className="quoted-email-content p-3 border-t border-gray-200 bg-gray-50">
<div
className="email-quoted-content"
dangerouslySetInnerHTML={{ __html: quotedContent }}
/>
</div>
)}
</div>
</div>
</div>
@ -376,6 +383,56 @@ export default function ComposeEmail(props: ComposeEmailProps) {
</Button>
</div>
</div>
{/* Styles for email display */}
<style jsx global>{`
.simple-editor {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
width: 100%;
flex: 1;
}
.email-quoted-content {
color: #505050;
font-size: 13px;
line-height: 1.5;
border-left: 2px solid #ddd;
padding-left: 10px;
margin-top: 5px;
}
.email-quoted-content blockquote {
margin: 5px 0;
padding-left: 10px;
border-left: 2px solid #ddd;
}
.email-quoted-content img {
max-width: 100%;
height: auto;
}
.email-quoted-content table {
border-collapse: collapse;
width: 100%;
max-width: 100%;
margin-bottom: 1rem;
}
.email-quoted-content th,
.email-quoted-content td {
padding: 5px;
border: 1px solid #ddd;
}
.email-quoted-content th {
background-color: #f8f9fa;
font-weight: 600;
text-align: left;
}
`}</style>
</div>
);
}