courrier multi account

This commit is contained in:
alma 2025-04-27 18:10:31 +02:00
parent c787d6a1a5
commit 6516a726e9

View File

@ -208,18 +208,43 @@ export default function CourrierPage() {
const response = await fetch('/api/courrier/session');
const data = await response.json();
console.log('[DEBUG] Session API response:', {
authenticated: data.authenticated,
hasEmailCredentials: data.hasEmailCredentials,
email: data.email,
allAccountsExists: !!data.allAccounts,
allAccountsIsArray: Array.isArray(data.allAccounts),
allAccountsLength: data.allAccounts?.length || 0,
mailboxesExists: !!data.mailboxes,
mailboxesIsArray: Array.isArray(data.mailboxes),
mailboxesLength: data.mailboxes?.length || 0
});
// Log the raw API response to inspect structure
console.log('[DEBUG] Raw session API response:', JSON.stringify(data, null, 2));
// Add detailed logging to inspect the accounts and folders structure
console.log('=== SESSION API RESPONSE DETAILED INSPECTION ===');
console.log('Session authenticated:', data.authenticated);
console.log('Has email credentials:', data.hasEmailCredentials);
console.log('Primary email:', data.email);
console.log('Redis status:', data.redisStatus);
// Log mailboxes structure - what the frontend used previously
console.log('=== MAILBOXES STRUCTURE (OLD API FORMAT) ===');
console.log('Global mailboxes exists:', !!data.mailboxes);
console.log('Global mailboxes is array:', Array.isArray(data.mailboxes));
console.log('Global mailboxes:', data.mailboxes);
// Log allAccounts structure - the new per-account folders approach
console.log('=== ALL ACCOUNTS STRUCTURE (NEW API FORMAT) ===');
console.log('allAccounts exists:', !!data.allAccounts);
console.log('allAccounts is array:', Array.isArray(data.allAccounts));
console.log('allAccounts length:', data.allAccounts?.length || 0);
// Inspect each account's structure
if (data.allAccounts && Array.isArray(data.allAccounts)) {
data.allAccounts.forEach((account: any, idx: number) => {
console.log(`Account ${idx + 1}:`, {
id: account.id,
email: account.email,
display_name: account.display_name,
foldersExist: !!account.folders,
foldersIsArray: Array.isArray(account.folders),
foldersLength: account.folders?.length || 0,
folders: account.folders
});
});
}
if (!isMounted) return;
if (data.authenticated) {
@ -234,33 +259,39 @@ export default function CourrierPage() {
// Check if we have multiple accounts returned
if (data.allAccounts && Array.isArray(data.allAccounts) && data.allAccounts.length > 0) {
console.log('Multiple accounts found:', data.allAccounts.length);
console.log('[DEBUG] Multiple accounts found:', data.allAccounts.length);
// First, validate the structure of each account
data.allAccounts.forEach((account: any, index: number) => {
console.log(`[DEBUG] Account ${index+1} structure check:`, {
id: account.id,
email: account.email,
display_name: account.display_name,
hasFolders: !!account.folders,
foldersIsArray: Array.isArray(account.folders),
foldersCount: Array.isArray(account.folders) ? account.folders.length : 0,
folders: account.folders || []
});
});
// Add each account from the server
data.allAccounts.forEach((account: any, index: number) => {
console.log(`[DEBUG] Processing account: ${account.email}, id: ${account.id}, display_name: ${account.display_name}, has folders: ${account.folders ? account.folders.length : 0}`);
// Check if the account has a valid folders array
if (!account.folders || !Array.isArray(account.folders)) {
console.warn(`[WARN] Account ${account.email} has invalid folders structure:`, account.folders);
// Use the global mailboxes as a fallback if available
account.folders = data.mailboxes && Array.isArray(data.mailboxes) ?
data.mailboxes : ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'];
console.log(`[DEBUG] Using fallback folders for ${account.email}:`, account.folders);
}
// Force include some hardcoded folders if none are present
const fallbackFolders = ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'];
// Prioritize account-specific folders over global mailboxes
const folderList = (account.folders && account.folders.length > 0) ?
account.folders :
(data.mailboxes && data.mailboxes.length > 0) ?
data.mailboxes :
fallbackFolders;
console.log(`[DEBUG] Using folders for ${account.email}:`, folderList);
const accountWithFolders = {
id: account.id || `account-${index + 1}`, // Use the database ID or generate a stable ID
updatedAccounts.push({
id: account.id || `account-${index}`,
name: account.display_name || account.email,
email: account.email,
color: account.color || 'bg-blue-500',
folders: folderList
};
console.log(`[DEBUG] Adding account with id ${accountWithFolders.id} and ${accountWithFolders.folders.length} folders:`, accountWithFolders.folders);
updatedAccounts.push(accountWithFolders);
folders: account.folders
});
});
} else if (data.email) {
// Check if we have a single account from the API
@ -312,6 +343,12 @@ export default function CourrierPage() {
}
console.log('Setting accounts:', updatedAccounts);
// Debug each account's folders
updatedAccounts.forEach((acc: Account, idx: number) => {
console.log(`Account ${idx + 1}: ${acc.name} (${acc.email}) - Folders:`,
acc.folders ? acc.folders.length : 0,
acc.folders || []);
});
setAccounts(updatedAccounts);
// Auto-select the first non-All account if available
@ -522,8 +559,38 @@ export default function CourrierPage() {
router.push('/courrier/login');
};
return (
<>
// 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) {
console.log('Folder rendering debug:',
'account:', selectedAccount.id,
'folders:', selectedAccount.folders?.length || 0,
'showFolders:', showFolders
);
}
}, [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
});
}
})}
<SimplifiedLoadingFix />
<RedisCacheStatus />
@ -797,115 +864,136 @@ export default function CourrierPage() {
{accountsDropdownOpen && (
<div className="space-y-1 pl-2 accounts-dropdown">
{accounts.map(account => (
<div key={account.id} className="relative group account-item">
<Button
variant="ghost"
className="w-full justify-between px-2 py-1.5 text-sm group"
onClick={() => {
// Toggle folders for this specific account
if (selectedAccount?.id === account.id) {
setShowFolders(!showFolders);
} else {
// When selecting a new account, make sure we show its folders
setShowFolders(true);
// Reset to the inbox folder of the new account by default
if (account.folders && account.folders.length > 0) {
// Find INBOX or default to first folder
const inboxFolder = account.folders.find(f =>
f.toLowerCase() === 'inbox') || account.folders[0];
{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 (
<div key={account.id} className="relative group account-item">
<Button
variant="ghost"
className="w-full justify-between px-2 py-1.5 text-sm group"
onClick={() => {
// Toggle folders for this specific account
if (selectedAccount?.id === account.id) {
console.log('[DEBUG] Toggling folders visibility for existing selection:', account.id, showFolders ? 'hiding' : 'showing');
setShowFolders(!showFolders);
} else {
// When selecting a new account, make sure we show its folders
console.log('[DEBUG] Selecting different account', {
oldAccount: selectedAccount ? selectedAccount.id : 'none',
newAccount: account.id,
folders: account.folders?.length || 0
});
setShowFolders(true);
// Change to this account's inbox folder
handleMailboxChange(inboxFolder, account.id);
// Reset to the inbox folder of the new account by default
if (account.folders && account.folders.length > 0) {
// Find INBOX or default to first folder
const inboxFolder = account.folders.find(f =>
f.toLowerCase() === 'inbox') || account.folders[0];
console.log('[DEBUG] Switching to folder:', inboxFolder, 'for account', account.id);
// Change to this account's inbox folder
handleMailboxChange(inboxFolder, account.id);
} else {
console.log('[DEBUG] No folders found for account', account.id);
}
}
}
setSelectedAccount(account);
// Force the account to have folders if it doesn't already
if (account.id !== 'all-accounts' && (!account.folders || account.folders.length === 0)) {
// Fetch folders for this account if not already available
fetch(`/api/courrier/account-folders?accountId=${account.id}`)
.then(res => res.json())
.then(data => {
if (data.folders && Array.isArray(data.folders)) {
console.log('[DEBUG] Setting selected account to:', account.id, account.email);
setSelectedAccount(account);
// Force the account to have folders if it doesn't already
if (account.id !== 'all-accounts' && (!account.folders || account.folders.length === 0)) {
console.log('[DEBUG] Account has no folders, fetching folders for account:', account.id);
// Fetch folders for this account if not already available
fetch(`/api/courrier/account-folders?accountId=${account.id}`)
.then(res => res.json())
.then(data => {
console.log('[DEBUG] Received folders from API:', data);
if (data.folders && Array.isArray(data.folders)) {
console.log('[DEBUG] Updating account with fetched folders:', data.folders.length);
const accountWithFolders = {
...account,
folders: data.folders
};
setSelectedAccount(accountWithFolders);
// Also update the account in the accounts array
const newAccounts = accounts.map(a =>
a.id === account.id ? accountWithFolders : a
);
setAccounts(newAccounts);
}
})
.catch(err => {
console.error(`[ERROR] Error fetching folders for account ${account.id}:`, err);
// Use default folders if API fails
const accountWithFolders = {
...account,
folders: data.folders
folders: ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk']
};
setSelectedAccount(accountWithFolders);
// Also update the account in the accounts array
const newAccounts = accounts.map(a =>
a.id === account.id ? accountWithFolders : a
);
setAccounts(newAccounts);
}
})
.catch(err => {
console.error(`Error fetching folders for account ${account.id}:`, err);
// Use default folders if API fails
const accountWithFolders = {
...account,
folders: ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk']
};
setSelectedAccount(accountWithFolders);
});
}
}}
>
<div className="flex items-center gap-2">
<div className={`w-2.5 h-2.5 rounded-full ${account.color}`}></div>
<span className="font-medium text-gray-700 truncate">{account.name}</span>
</div>
{/* Show arrow for all accounts */}
<div className="flex items-center">
{selectedAccount?.id === account.id && showFolders ?
<ChevronDown className="h-3.5 w-3.5 text-gray-500" /> :
<ChevronRight className="h-3.5 w-3.5 text-gray-500" />
}
</div>
</Button>
{/* 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)) && (
<div className="pl-4 mt-1 mb-2 space-y-0.5 border-l border-gray-200 folder-container">
{account.folders && account.folders.length > 0 ? (
account.folders.map((folder, folderIndex) => (
<Button
key={folder}
variant="ghost"
className={`w-full justify-start py-1 px-2 text-xs folder-item ${
currentView === folder ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900'
}`}
onClick={(e) => {
e.stopPropagation();
// Pass the account ID along with the folder name
handleMailboxChange(folder, selectedAccount?.id);
}}
>
<div className="flex items-center justify-between w-full gap-1.5">
<div className="flex items-center gap-1.5">
{React.createElement(getFolderIcon(folder), { className: "h-3.5 w-3.5" })}
<span className="truncate">{formatFolderName(folder)}</span>
});
}
}}
>
<div className="flex items-center gap-2">
<div className={`w-2.5 h-2.5 rounded-full ${account.color}`}></div>
<span className="font-medium text-gray-700 truncate">{account.name}</span>
</div>
{/* Show arrow for all accounts */}
<div className="flex items-center">
{selectedAccount?.id === account.id && showFolders ?
<ChevronDown className="h-3.5 w-3.5 text-gray-500" /> :
<ChevronRight className="h-3.5 w-3.5 text-gray-500" />
}
</div>
</Button>
{/* 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)) && (
<div className="pl-4 mt-1 mb-2 space-y-0.5 border-l border-gray-200 folder-container">
{/* No console.log here - moved to useEffect */}
{account.folders && account.folders.length > 0 ? (
account.folders.map((folder, folderIndex) => (
<Button
key={folder}
variant="ghost"
className={`w-full justify-start py-1 px-2 text-xs folder-item ${
currentView === folder ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900'
}`}
onClick={(e) => {
e.stopPropagation();
// Pass the account ID along with the folder name
handleMailboxChange(folder, selectedAccount?.id);
}}
>
<div className="flex items-center justify-between w-full gap-1.5">
<div className="flex items-center gap-1.5">
{React.createElement(getFolderIcon(folder), { className: "h-3.5 w-3.5" })}
<span className="truncate">{formatFolderName(folder)}</span>
</div>
{folder === 'INBOX' && unreadCount > 0 && (
<span className="inline-flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-blue-100 text-blue-800 rounded">
{unreadCount}
</span>
)}
</div>
{folder === 'INBOX' && unreadCount > 0 && (
<span className="inline-flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-blue-100 text-blue-800 rounded">
{unreadCount}
</span>
)}
</div>
</Button>
))
) : (
<div className="text-xs text-gray-500 px-2 py-1">No folders found</div>
)}
</div>
)}
</div>
))}
</Button>
))
) : (
<div className="text-xs text-gray-500 px-2 py-1">No folders found</div>
)}
</div>
)}
</div>
);
})}
</div>
)}
</div>