diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 71b19116..b7645cf5 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -98,53 +98,23 @@ export default function CourrierPage() { const [sidebarOpen, setSidebarOpen] = useState(true); const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); const [accountsDropdownOpen, setAccountsDropdownOpen] = useState(true); - const [foldersOpen, setFoldersOpen] = useState(true); const [currentView, setCurrentView] = useState('INBOX'); const [unreadCount, setUnreadCount] = useState(0); const [loading, setLoading] = useState(false); - const [userEmail, setUserEmail] = useState(''); // Mock accounts for the sidebar const [accounts, setAccounts] = useState([ - { id: 1, name: 'Mail', email: userEmail || 'Loading...', color: 'bg-blue-500', folders: mailboxes } + { id: 0, name: 'All', email: '', color: 'bg-gray-500' }, + { id: 1, name: 'Mail', email: 'user@example.com', color: 'bg-blue-500', folders: mailboxes } ]); const [selectedAccount, setSelectedAccount] = useState(null); - // Fetch user email from credentials when component mounts - useEffect(() => { - async function fetchUserEmail() { - try { - const response = await fetch('/api/courrier/credentials'); - if (response.ok) { - const data = await response.json(); - if (data.credentials?.email) { - setUserEmail(data.credentials.email); - - // Update account with the email address - setAccounts(prev => { - const updated = [...prev]; - if (updated[0]) { - updated[0].email = data.credentials.email; - updated[0].name = data.credentials.email; - } - return updated; - }); - } - } - } catch (error) { - console.error('Error fetching user email:', error); - } - } - - fetchUserEmail(); - }, []); - // Update account folders when mailboxes change useEffect(() => { setAccounts(prev => { const updated = [...prev]; - if (updated[0]) { - updated[0].folders = mailboxes; + if (updated[1]) { + updated[1].folders = mailboxes; } return updated; }); @@ -341,68 +311,56 @@ export default function CourrierPage() { - {/* Show folders for email accounts without the "Folders" header */} - {account.folders && account.folders.length > 0 && foldersOpen && ( + {/* Show folders for email accounts (not for "All" account) without the "Folders" header */} + {account.id !== 0 && (
- {account.folders.map((folder) => ( - + )) + ) : ( +
+
+ {/* Create placeholder folder items with shimmer effect */} + {Array.from({ length: 5 }).map((_, index) => ( +
+
+
+
+ ))}
- - ))} -
- )} - - {account.folders && account.folders.length === 0 && ( -
-
- {/* Create placeholder folder items with shimmer effect */} - {Array.from({ length: 5 }).map((_, index) => ( -
-
-
-
- ))} -
+
+ )}
)} diff --git a/components/email/ComposeEmail.tsx b/components/email/ComposeEmail.tsx index a7041f5f..1c77745c 100644 --- a/components/email/ComposeEmail.tsx +++ b/components/email/ComposeEmail.tsx @@ -10,7 +10,6 @@ import { Textarea } from '@/components/ui/textarea'; import { Card, CardContent, CardHeader, CardTitle, CardFooter } from '@/components/ui/card'; import DOMPurify from 'isomorphic-dompurify'; import { Label } from '@/components/ui/label'; -import dynamic from 'next/dynamic'; // Import sub-components import ComposeEmailHeader from './ComposeEmailHeader'; @@ -109,18 +108,26 @@ function EmailMessageToQuotedContentAdapter({ email: EmailMessage, type: 'reply' | 'reply-all' | 'forward' }) { - if (!email) return null; + // Get the email content + const content = email.content || email.html || email.text || ''; + + // Get the sender + const sender = email.from && email.from.length > 0 + ? { + name: email.from[0].name, + email: email.from[0].address + } + : { email: 'unknown@example.com' }; + + // Map the type to what QuotedEmailContent expects + const mappedType = type === 'reply-all' ? 'reply' : type; return ( ); } @@ -139,7 +146,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) { const [cc, setCc] = useState(''); const [bcc, setBcc] = useState(''); const [subject, setSubject] = useState(''); - const [emailContent, setEmailContent] = useState('
'); + const [emailContent, setEmailContent] = useState(''); const [showCc, setShowCc] = useState(false); const [showBcc, setShowBcc] = useState(false); const [sending, setSending] = useState(false); @@ -149,53 +156,132 @@ export default function ComposeEmail(props: ComposeEmailAllProps) { type: string; }>>([]); - // Initialize the form with the provided email data + // Initialize the form when replying to or forwarding an email useEffect(() => { - try { - // Only process if there's an initial email and it's a reply/forward - if (initialEmail && type !== 'new') { - // For replies: set the recipient to the sender of the original email + if (initialEmail && type !== 'new') { + try { + // Set recipients based on type if (type === 'reply' || type === 'reply-all') { - // Set recipients and subject using the formatReplyEmail utility - const formattedEmail = formatReplyEmail(initialEmail, type as 'reply' | 'reply-all'); - - // Set recipients + // Reply goes to the original sender setTo(formatEmailAddresses(initialEmail.from || [])); - // For reply-all: add original recipients to CC + // For reply-all, include all original recipients in CC if (type === 'reply-all') { const allRecipients = [ ...(initialEmail.to || []), ...(initialEmail.cc || []) ]; - - if (allRecipients.length > 0) { - setCc(formatEmailAddresses(allRecipients)); - setShowCc(true); - } + // Filter out the current user if they were a recipient + // This would need some user context to properly implement + setCc(formatEmailAddresses(allRecipients)); } - // Set subject with "Re:" prefix if needed - setSubject(formattedEmail.subject); + // Set subject with Re: prefix + const subjectBase = initialEmail.subject || '(No subject)'; + const subject = subjectBase.match(/^Re:/i) ? subjectBase : `Re: ${subjectBase}`; + setSubject(subject); - // Initialize with empty content - we'll use QuotedEmailContent in the render - setEmailContent('
'); - } - - // For forwards: set forwarded subject + // Format the reply content with the quoted message included directly + const content = initialEmail.content || initialEmail.html || initialEmail.text || ''; + const sender = initialEmail.from && initialEmail.from.length > 0 + ? initialEmail.from[0].name || initialEmail.from[0].address + : 'Unknown sender'; + const date = initialEmail.date ? + (typeof initialEmail.date === 'string' ? new Date(initialEmail.date) : initialEmail.date) : + new Date(); + + // Format date for display + const formattedDate = date.toLocaleString('en-US', { + weekday: 'short', + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + + // Create reply content with quote + const replyContent = ` +

+

+

+

+
On ${formattedDate}, ${sender} wrote:
+
+
+ ${content} +
+
+ `; + + setEmailContent(replyContent); + + // Show CC field if there are CC recipients + if (initialEmail.cc && initialEmail.cc.length > 0) { + setShowCc(true); + } + } else if (type === 'forward') { - // Format the email for forwarding - const formattedEmail = formatForwardedEmail(initialEmail); + // Set subject with Fwd: prefix + const subjectBase = initialEmail.subject || '(No subject)'; + const subject = subjectBase.match(/^(Fwd|FW|Forward):/i) ? subjectBase : `Fwd: ${subjectBase}`; + setSubject(subject); - // Set subject with "Fwd:" prefix - setSubject(formattedEmail.subject); + // Format the forward content with the original email included directly + const content = initialEmail.content || initialEmail.html || initialEmail.text || ''; + const fromString = formatEmailAddresses(initialEmail.from || []); + const toString = formatEmailAddresses(initialEmail.to || []); + const date = initialEmail.date ? + (typeof initialEmail.date === 'string' ? new Date(initialEmail.date) : initialEmail.date) : + new Date(); - // Initialize with empty content - we'll use QuotedEmailContent in the render - setEmailContent('
'); + // Format date for display + const formattedDate = date.toLocaleString('en-US', { + weekday: 'short', + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + + // Create forwarded content + const forwardContent = ` +

+

+

+

+
+
+
+
---------- Forwarded message ---------
+
From: ${fromString}
+
Date: ${formattedDate}
+
Subject: ${initialEmail.subject || ''}
+
To: ${toString}
+
+ +
+
+ `; + + setEmailContent(forwardContent); + + // If the original email has attachments, we should include them + if (initialEmail.attachments && initialEmail.attachments.length > 0) { + const formattedAttachments = initialEmail.attachments.map(att => ({ + name: att.filename || 'attachment', + type: att.contentType || 'application/octet-stream', + content: att.content || '' + })); + setAttachments(formattedAttachments); + } } + } catch (error) { + console.error('Error initializing compose form:', error); } - } catch (error) { - console.error('Error initializing compose form:', error); } }, [initialEmail, type]); @@ -364,26 +450,18 @@ export default function ComposeEmail(props: ComposeEmailAllProps) { /> - {/* Email Content Section */} -
- - {/* Add QuotedEmailContent for replies and forwards */} - {initialEmail && (type === 'reply' || type === 'reply-all' || type === 'forward') && ( -
- -
- )} + {/* Message Body */} +
+ +
+ +
{/* Attachments */} @@ -735,12 +813,18 @@ function LegacyAdapter({ />
- {/* Email Content Section */} -
- + {/* Message Body */} +
+ +
+ +
{/* Attachments */}