From 9eaa77b525f481823acfe425be4664081fe8f015 Mon Sep 17 00:00:00 2001 From: alma Date: Sun, 27 Apr 2025 18:13:10 +0200 Subject: [PATCH] courrier multi account --- app/courrier/page.tsx | 862 +++++++++++++++++++++--------------------- 1 file changed, 436 insertions(+), 426 deletions(-) diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 71d002f5..8f105caa 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -9,7 +9,7 @@ import { Inbox, Send, Star, Trash, Plus, ChevronLeft, ChevronRight, Search, ChevronDown, Folder, ChevronUp, Reply, Forward, ReplyAll, MoreHorizontal, FolderOpen, X, Paperclip, MessageSquare, Copy, EyeOff, - AlertOctagon, Archive, RefreshCw + AlertOctagon, Archive, RefreshCw, Menu } from 'lucide-react'; import { Dialog, DialogContent } from '@/components/ui/dialog'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; @@ -159,6 +159,18 @@ export default function CourrierPage() { } }, [selectedAccount]); + // Add useEffect for debugging + useEffect(() => { + if (typeof window !== 'undefined') { + console.log('[DEBUG] Rendering UI with:', { + accountsCount: accounts.length, + selectedAccountId: selectedAccount?.id, + showFolders, + currentFolder + }); + } + }, [accounts, selectedAccount, showFolders, currentFolder]); + // Calculate unread count (this would be replaced with actual data in production) useEffect(() => { // Example: counting unread emails in the inbox @@ -559,16 +571,6 @@ export default function CourrierPage() { router.push('/courrier/login'); }; - // Add this log right before the return statement in the CourrierPage component - // Debug accounts and selectedAccount before rendering - useEffect(() => { - console.log('=== RENDER STATE INSPECTION ==='); - console.log('Current accounts state:', accounts); - console.log('Selected account:', selectedAccount); - console.log('Current folder:', currentFolder); - console.log('Show folders:', showFolders); - }, [accounts, selectedAccount, currentFolder, showFolders]); - // Extra debugging for folder rendering useEffect(() => { if (selectedAccount && showFolders) { @@ -580,17 +582,8 @@ export default function CourrierPage() { } }, [selectedAccount, showFolders]); - // Add useEffect for debugging near the other useEffect hooks - useEffect(() => { - if (typeof window !== 'undefined') { - console.log('[DEBUG] Rendering UI with:', { - accountsCount: accounts.length, - selectedAccountId: selectedAccount?.id, - showFolders, - currentFolder - }); - } - })} + return ( + <> @@ -663,387 +656,388 @@ export default function CourrierPage() { - {/* Form for adding a new account */} - {showAddAccountForm && ( -
-

Add IMAP Account

-
{ - e.preventDefault(); - setLoading(true); - - const formData = new FormData(e.currentTarget); - - // Pull values from form with proper type handling - const formValues = { - email: formData.get('email')?.toString() || '', - password: formData.get('password')?.toString() || '', - host: formData.get('host')?.toString() || '', - port: parseInt(formData.get('port')?.toString() || '993'), - secure: formData.get('secure') === 'on', - display_name: formData.get('display_name')?.toString() || '', - smtp_host: formData.get('smtp_host')?.toString() || '', - smtp_port: formData.get('smtp_port')?.toString() ? - parseInt(formData.get('smtp_port')?.toString() || '587') : undefined, - smtp_secure: formData.get('smtp_secure') === 'on' - }; - - // If display_name is empty, use email - if (!formValues.display_name) { - formValues.display_name = formValues.email; - } - - try { - // First test the connection - const testResponse = await fetch('/api/courrier/test-connection', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - email: formValues.email, - password: formValues.password, - host: formValues.host, - port: formValues.port, - secure: formValues.secure - }) - }); + {/* Form for adding a new account */} + {showAddAccountForm && ( +
+

Add IMAP Account

+ { + e.preventDefault(); + setLoading(true); - const testResult = await testResponse.json(); + const formData = new FormData(e.currentTarget); - if (!testResponse.ok) { - throw new Error(testResult.error || 'Connection test failed'); - } - - console.log('Connection test successful:', testResult); - - // If connection test is successful, save the account - const saveResponse = await fetch('/api/courrier/account', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(formValues) - }); - - const saveResult = await saveResponse.json(); - - if (!saveResponse.ok) { - throw new Error(saveResult.error || 'Failed to add account'); - } - - // Update accounts list - const newAccountObj = { - id: `account-${Date.now()}`, // generate unique string ID - name: formValues.display_name, - email: formValues.email, - color: `bg-blue-500`, // Default color class - folders: testResult.details.sampleFolders || ['INBOX', 'Sent', 'Drafts', 'Trash'] // Use discovered folders or defaults + // Pull values from form with proper type handling + const formValues = { + email: formData.get('email')?.toString() || '', + password: formData.get('password')?.toString() || '', + host: formData.get('host')?.toString() || '', + port: parseInt(formData.get('port')?.toString() || '993'), + secure: formData.get('secure') === 'on', + display_name: formData.get('display_name')?.toString() || '', + smtp_host: formData.get('smtp_host')?.toString() || '', + smtp_port: formData.get('smtp_port')?.toString() ? + parseInt(formData.get('smtp_port')?.toString() || '587') : undefined, + smtp_secure: formData.get('smtp_secure') === 'on' }; - setAccounts(prev => [...prev, newAccountObj]); - setShowAddAccountForm(false); - toast({ - title: "Account added successfully", - description: `Your email account ${formValues.email} has been added.`, - duration: 5000 - }); - } catch (error) { - console.error('Error adding account:', error); - toast({ - title: "Failed to add account", - description: error instanceof Error ? error.message : 'Unknown error', - variant: "destructive", - duration: 5000 - }); - } finally { - setLoading(false); - } - }}> -
- - - IMAP Settings - SMTP Settings - - - - - - - -
- -
- - -
-
-
- - - -
- -
- - -
-
-
-
+ // If display_name is empty, use email + if (!formValues.display_name) { + formValues.display_name = formValues.email; + } -
- - -
-
- -
- )} - - {accountsDropdownOpen && ( -
- {accounts.map(account => { - // Log outside of the JSX to avoid linter issues - if (process.env.NODE_ENV !== 'production') { - console.log('Rendering account:', account.id, account.name, 'has folders:', account.folders?.length || 0); - } - return ( -
- + try { + // First test the connection + const testResponse = await fetch('/api/courrier/test-connection', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + email: formValues.email, + password: formValues.password, + host: formValues.host, + port: formValues.port, + secure: formValues.secure + }) + }); - {/* Show folders for this account if it's selected and folders are shown */} - {((selectedAccount?.id === account.id && showFolders) || - (!selectedAccount && account.id !== 'all-accounts' && account.folders)) && ( -
- {/* No console.log here - moved to useEffect */} - {account.folders && account.folders.length > 0 ? ( - account.folders.map((folder, folderIndex) => ( - - )) - ) : ( -
No folders found
- )} -
+ const testResult = await testResponse.json(); + + if (!testResponse.ok) { + throw new Error(testResult.error || 'Connection test failed'); + } + + console.log('Connection test successful:', testResult); + + // If connection test is successful, save the account + const saveResponse = await fetch('/api/courrier/account', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formValues) + }); + + const saveResult = await saveResponse.json(); + + if (!saveResponse.ok) { + throw new Error(saveResult.error || 'Failed to add account'); + } + + // Update accounts list + const newAccountObj = { + id: `account-${Date.now()}`, // generate unique string ID + name: formValues.display_name, + email: formValues.email, + color: `bg-blue-500`, // Default color class + folders: testResult.details.sampleFolders || ['INBOX', 'Sent', 'Drafts', 'Trash'] // Use discovered folders or defaults + }; + + setAccounts(prev => [...prev, newAccountObj]); + setShowAddAccountForm(false); + toast({ + title: "Account added successfully", + description: `Your email account ${formValues.email} has been added.`, + duration: 5000 + }); + } catch (error) { + console.error('Error adding account:', error); + toast({ + title: "Failed to add account", + description: error instanceof Error ? error.message : 'Unknown error', + variant: "destructive", + duration: 5000 + }); + } finally { + setLoading(false); + } + }}> +
+ + + IMAP Settings + SMTP Settings + + + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
+ + +
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
+ Note: SMTP settings are only needed for sending emails +
+
+
+ +
+ + +
+
+ +
+ )} + + {/* Accounts List */} + {accountsDropdownOpen && ( +
+ {accounts.map((account) => ( + + ))} +
+ )} +
+ + {/* Folders Section - conditionally show folders when an account is selected */} + {showFolders && selectedAccount && selectedAccount.folders && ( +
+
+ +
+ + {selectedAccount.folders.map((folder) => ( + + ))}
)} -
- - {/* Categories Section */} -
-

Categories

-
- -
-
- - {/* Email List and Content View */} -
- {/* Email List */} - + + {/* Main Content Area - conditionally show email list or detail view */} +
+ {/* Header bar with search */} +
+ + +
+ + searchEmails(e.target.value)} + placeholder="Search emails..." + className="pl-8 h-9 bg-gray-50 border-gray-200" + /> +
+ +
+ {selectedEmailIds.length > 0 && ( +
+ + + +
+ )} + + {session?.user && ( + + + {session.user.name?.substring(0, 2) || session.user.email?.substring(0, 2) || 'U'} + + + )} +
+
- {/* Email Content View */} -
- {selectedEmail ? ( - + {isLoading ? ( +
+
+ +

Loading emails...

+
+
+ ) : error ? ( +
+
+ + + Error + + {error} + {(error?.includes('Not authenticated') || error?.includes('No email credentials found')) && ( + + )} + + +
+
+ ) : selectedEmail ? ( + handleEmailSelect('')} onReply={handleReply} onReplyAll={handleReplyAll} @@ -1051,19 +1045,36 @@ export default function CourrierPage() { onToggleStar={() => toggleStarred(selectedEmail.id)} /> ) : ( -
- -

Select an email to read

-

- Choose an email from the list or compose a new message to get started. -

- +
+ {/* Email List */} +
+ {emails.length === 0 ? ( +
+
+ +

No emails found

+

+ {searchQuery + ? `No results found for "${searchQuery}"` + : `Your ${currentFolder.toLowerCase()} is empty`} +

+
+
+ ) : ( + + )} +
)}
@@ -1072,32 +1083,31 @@ export default function CourrierPage() {
- {/* Login needed alert */} - setShowLoginNeeded(false)} - /> - - {/* Compose Modal */} - {showComposeModal && ( - setShowComposeModal(false)} - onSend={async (emailData: EmailData) => { - await sendEmail(emailData); - }} - /> - )} - - {/* Delete Confirmation Dialog */} - setShowDeleteConfirm(false)} /> + + + + + + setShowComposeModal(false)} + isSending={isSending} + /> + + ); } \ No newline at end of file