courrier multi account
This commit is contained in:
parent
c787d6a1a5
commit
6516a726e9
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user