courrier preview
This commit is contained in:
parent
0d4fc59904
commit
e8989f2016
@ -155,194 +155,407 @@ export const useEmailState = () => {
|
|||||||
dispatch({ type: 'SET_LOADING', payload: true });
|
dispatch({ type: 'SET_LOADING', payload: true });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get normalized parameters using helper function with proper account ID handling
|
// CRITICAL FIX: Add more robust validation to prevent "toString of undefined" error
|
||||||
const accountId = state.selectedAccount ? state.selectedAccount.id : undefined;
|
if (!state.currentFolder) {
|
||||||
const { normalizedFolder, effectiveAccountId, prefixedFolder } =
|
logEmailOp('ERROR', 'Current folder is undefined, cannot load emails');
|
||||||
normalizeFolderAndAccount(state.currentFolder, accountId);
|
dispatch({
|
||||||
|
type: 'SET_ERROR',
|
||||||
logEmailOp('LOAD_EMAILS', `Loading emails for ${prefixedFolder} (account: ${effectiveAccountId}, isLoadMore: ${isLoadMore}, page: ${page})`);
|
payload: 'Invalid folder configuration'
|
||||||
|
});
|
||||||
// Construct query parameters
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
const queryParams = new URLSearchParams({
|
return;
|
||||||
folder: normalizedFolder,
|
|
||||||
page: page.toString(),
|
|
||||||
perPage: perPage.toString(),
|
|
||||||
accountId: effectiveAccountId
|
|
||||||
});
|
|
||||||
|
|
||||||
// Debug log existing emails count
|
|
||||||
if (isLoadMore) {
|
|
||||||
console.log(`[DEBUG-PAGINATION] Loading more emails. Current page: ${page}, existing emails: ${state.emails.length}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to get cached emails first
|
// Get normalized parameters using helper function with proper account ID handling
|
||||||
logEmailOp('CACHE_CHECK', `Checking cache for ${prefixedFolder}, page: ${page}`);
|
const accountId = state.selectedAccount ? state.selectedAccount.id : undefined;
|
||||||
const cachedEmails = await getCachedEmailsWithTimeout(
|
|
||||||
session.user.id,
|
|
||||||
prefixedFolder,
|
|
||||||
page,
|
|
||||||
perPage,
|
|
||||||
100,
|
|
||||||
effectiveAccountId
|
|
||||||
);
|
|
||||||
|
|
||||||
if (cachedEmails) {
|
// Additional validation for accountId
|
||||||
logEmailOp('CACHE_HIT', `Using cached data for ${prefixedFolder}, page: ${page}, emails: ${cachedEmails.emails?.length || 0}, isLoadMore: ${isLoadMore}`);
|
if (accountId === undefined && state.currentFolder.includes(':')) {
|
||||||
|
// Try to extract accountId from folder string as fallback
|
||||||
// Ensure cached data has emails array property
|
const extractedAccountId = state.currentFolder.split(':')[0];
|
||||||
if (Array.isArray(cachedEmails.emails)) {
|
if (extractedAccountId) {
|
||||||
// CRITICAL FIX: Double check we're using the right action type based on isLoadMore param
|
console.log(`[DEBUG-LOAD_EMAILS] Using extracted accountId ${extractedAccountId} from folder path as fallback`);
|
||||||
console.log(`[DEBUG-CACHE_HIT] Dispatching ${isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS'} with ${cachedEmails.emails.length} emails`);
|
const { normalizedFolder, effectiveAccountId, prefixedFolder } =
|
||||||
|
normalizeFolderAndAccount(state.currentFolder, extractedAccountId);
|
||||||
|
|
||||||
|
logEmailOp('LOAD_EMAILS', `Loading emails for ${prefixedFolder} (account: ${effectiveAccountId}, isLoadMore: ${isLoadMore}, page: ${page})`);
|
||||||
|
|
||||||
// Dispatch appropriate action based on if we're loading more - DO NOT OVERRIDE isLoadMore!
|
// Continue with the extracted account ID...
|
||||||
dispatch({
|
// Construct query parameters
|
||||||
type: isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS',
|
const queryParams = new URLSearchParams({
|
||||||
payload: cachedEmails.emails
|
folder: normalizedFolder,
|
||||||
|
page: page.toString(),
|
||||||
|
perPage: perPage.toString(),
|
||||||
|
accountId: effectiveAccountId
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set pagination info from cache if available
|
// Debug log existing emails count
|
||||||
if (cachedEmails.totalEmails) {
|
if (isLoadMore) {
|
||||||
dispatch({ type: 'SET_TOTAL_EMAILS', payload: cachedEmails.totalEmails });
|
console.log(`[DEBUG-PAGINATION] Loading more emails. Current page: ${page}, existing emails: ${state.emails.length}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedEmails.totalPages) {
|
// Try to get cached emails first
|
||||||
dispatch({ type: 'SET_TOTAL_PAGES', payload: cachedEmails.totalPages });
|
logEmailOp('CACHE_CHECK', `Checking cache for ${prefixedFolder}, page: ${page}`);
|
||||||
|
const cachedEmails = await getCachedEmailsWithTimeout(
|
||||||
|
session.user.id,
|
||||||
|
prefixedFolder,
|
||||||
|
page,
|
||||||
|
perPage,
|
||||||
|
100,
|
||||||
|
effectiveAccountId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (cachedEmails) {
|
||||||
|
logEmailOp('CACHE_HIT', `Using cached data for ${prefixedFolder}, page: ${page}, emails: ${cachedEmails.emails?.length || 0}, isLoadMore: ${isLoadMore}`);
|
||||||
|
|
||||||
|
// Ensure cached data has emails array property
|
||||||
|
if (Array.isArray(cachedEmails.emails)) {
|
||||||
|
// CRITICAL FIX: Double check we're using the right action type based on isLoadMore param
|
||||||
|
console.log(`[DEBUG-CACHE_HIT] Dispatching ${isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS'} with ${cachedEmails.emails.length} emails`);
|
||||||
|
|
||||||
|
// Dispatch appropriate action based on if we're loading more - DO NOT OVERRIDE isLoadMore!
|
||||||
|
dispatch({
|
||||||
|
type: isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS',
|
||||||
|
payload: cachedEmails.emails
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set pagination info from cache if available
|
||||||
|
if (cachedEmails.totalEmails) {
|
||||||
|
dispatch({ type: 'SET_TOTAL_EMAILS', payload: cachedEmails.totalEmails });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedEmails.totalPages) {
|
||||||
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: cachedEmails.totalPages });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update available mailboxes if provided
|
||||||
|
if (cachedEmails.mailboxes && cachedEmails.mailboxes.length > 0) {
|
||||||
|
dispatch({ type: 'SET_MAILBOXES', payload: cachedEmails.mailboxes });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRITICAL FIX: If this was a loadMore operation, check the result after the dispatch
|
||||||
|
if (isLoadMore) {
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log(`[DEBUG-CACHE_HIT_APPEND] After ${isLoadMore ? 'APPEND' : 'SET'}, email count is now: ${state.emails.length}`);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch emails from API if no cache hit
|
||||||
|
logEmailOp('API_FETCH', `Fetching emails from API: ${queryParams.toString()}, isLoadMore: ${isLoadMore}`);
|
||||||
|
console.log(`[DEBUG-API_FETCH] Fetching from /api/courrier?${queryParams.toString()}`);
|
||||||
|
const response = await fetch(`/api/courrier?${queryParams.toString()}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
// CRITICAL FIX: Try to recover from fetch errors by retrying with different pagination
|
||||||
|
if (isLoadMore && page > 1) {
|
||||||
|
logEmailOp('ERROR_RECOVERY', `Failed to fetch emails for page ${page}, attempting to recover by decrementing page`);
|
||||||
|
console.log(`[DEBUG-ERROR] API returned ${response.status} for page ${page}`);
|
||||||
|
// If we're loading more and there's an error, just decrement the page to avoid getting stuck
|
||||||
|
dispatch({ type: 'SET_PAGE', payload: page - 1 });
|
||||||
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
|
// Also reset total pages to try again
|
||||||
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: page });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorData = await response.json();
|
||||||
|
throw new Error(errorData.error || 'Failed to fetch emails');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log(`[DEBUG-API_RESPONSE] Got response with ${data.emails?.length || 0} emails, totalPages: ${data.totalPages}, totalEmails: ${data.totalEmails}, isLoadMore: ${isLoadMore}`);
|
||||||
|
|
||||||
|
// CRITICAL FIX: Enhanced empty results handling
|
||||||
|
if (!data.emails || data.emails.length === 0) {
|
||||||
|
console.log(`[DEBUG-EMPTY] No emails in response for page ${page}`);
|
||||||
|
// If we're at a page > 1 and got no results, the paging is off, so try again with page 1
|
||||||
|
if (page > 1 && !isLoadMore) {
|
||||||
|
logEmailOp('EMPTY_RESULTS', `No emails returned for page ${page}, resetting to page 1`);
|
||||||
|
dispatch({ type: 'SET_PAGE', payload: 1 });
|
||||||
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're already at page 1, just update the state with no emails
|
||||||
|
if (!isLoadMore) {
|
||||||
|
logEmailOp('EMPTY_RESULTS', `No emails found in ${state.currentFolder}`);
|
||||||
|
dispatch({ type: 'SET_EMAILS', payload: [] });
|
||||||
|
dispatch({ type: 'SET_TOTAL_EMAILS', payload: 0 });
|
||||||
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: 0 });
|
||||||
|
} else {
|
||||||
|
// For load more, just set loading to false but keep existing emails
|
||||||
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all emails have proper account ID and folder format
|
||||||
|
if (Array.isArray(data.emails)) {
|
||||||
|
// Log email dates for debugging
|
||||||
|
if (data.emails.length > 0) {
|
||||||
|
logEmailOp('EMAIL_DATES', `First few email dates before processing:`,
|
||||||
|
data.emails.slice(0, 5).map((e: any) => ({
|
||||||
|
id: e.id.substring(0, 8),
|
||||||
|
subject: e.subject?.substring(0, 20),
|
||||||
|
date: e.date,
|
||||||
|
dateObj: new Date(e.date),
|
||||||
|
timestamp: new Date(e.date).getTime()
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.emails.forEach((email: Email) => {
|
||||||
|
// If email doesn't have an accountId, set it to the effective one
|
||||||
|
if (!email.accountId) {
|
||||||
|
email.accountId = effectiveAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure folder has the proper prefix format
|
||||||
|
if (email.folder && !email.folder.includes(':')) {
|
||||||
|
email.folder = `${email.accountId}:${email.folder}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure date is a valid Date object (handle strings or timestamps)
|
||||||
|
if (email.date && !(email.date instanceof Date)) {
|
||||||
|
try {
|
||||||
|
// Convert to a proper Date object if it's a string or number
|
||||||
|
const dateObj = new Date(email.date);
|
||||||
|
// Verify it's a valid date
|
||||||
|
if (!isNaN(dateObj.getTime())) {
|
||||||
|
email.date = dateObj;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// If conversion fails, log and use current date as fallback
|
||||||
|
console.error(`Invalid date format for email ${email.id}: ${email.date}`);
|
||||||
|
email.date = new Date();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRITICAL FIX: Log what we're about to do
|
||||||
|
console.log(`[DEBUG-DISPATCH] About to dispatch ${isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS'} with ${data.emails?.length || 0} emails`);
|
||||||
|
|
||||||
|
// Update state with fetched data
|
||||||
|
dispatch({
|
||||||
|
type: isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS',
|
||||||
|
payload: Array.isArray(data.emails) ? data.emails : []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Double-check that we've updated the email list correctly after dispatch
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log(`[DEBUG-AFTER-DISPATCH] Email count is now: ${state.emails.length}, should include the ${data.emails?.length || 0} new emails we just loaded`);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
if (data.totalEmails) {
|
||||||
|
dispatch({ type: 'SET_TOTAL_EMAILS', payload: data.totalEmails });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.totalPages) {
|
||||||
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: data.totalPages });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update available mailboxes if provided
|
// Update available mailboxes if provided
|
||||||
if (cachedEmails.mailboxes && cachedEmails.mailboxes.length > 0) {
|
if (data.mailboxes && data.mailboxes.length > 0) {
|
||||||
dispatch({ type: 'SET_MAILBOXES', payload: cachedEmails.mailboxes });
|
dispatch({ type: 'SET_MAILBOXES', payload: data.mailboxes });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// CRITICAL FIX: If this was a loadMore operation, check the result after the dispatch
|
|
||||||
if (isLoadMore) {
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log(`[DEBUG-CACHE_HIT_APPEND] After ${isLoadMore ? 'APPEND' : 'SET'}, email count is now: ${state.emails.length}`);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch emails from API if no cache hit
|
|
||||||
logEmailOp('API_FETCH', `Fetching emails from API: ${queryParams.toString()}, isLoadMore: ${isLoadMore}`);
|
|
||||||
console.log(`[DEBUG-API_FETCH] Fetching from /api/courrier?${queryParams.toString()}`);
|
|
||||||
const response = await fetch(`/api/courrier?${queryParams.toString()}`);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
// CRITICAL FIX: Try to recover from fetch errors by retrying with different pagination
|
|
||||||
if (isLoadMore && page > 1) {
|
|
||||||
logEmailOp('ERROR_RECOVERY', `Failed to fetch emails for page ${page}, attempting to recover by decrementing page`);
|
|
||||||
console.log(`[DEBUG-ERROR] API returned ${response.status} for page ${page}`);
|
|
||||||
// If we're loading more and there's an error, just decrement the page to avoid getting stuck
|
|
||||||
dispatch({ type: 'SET_PAGE', payload: page - 1 });
|
|
||||||
dispatch({ type: 'SET_LOADING', payload: false });
|
|
||||||
// Also reset total pages to try again
|
|
||||||
dispatch({ type: 'SET_TOTAL_PAGES', payload: page });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorData = await response.json();
|
|
||||||
throw new Error(errorData.error || 'Failed to fetch emails');
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
console.log(`[DEBUG-API_RESPONSE] Got response with ${data.emails?.length || 0} emails, totalPages: ${data.totalPages}, totalEmails: ${data.totalEmails}, isLoadMore: ${isLoadMore}`);
|
|
||||||
|
|
||||||
// CRITICAL FIX: Enhanced empty results handling
|
|
||||||
if (!data.emails || data.emails.length === 0) {
|
|
||||||
console.log(`[DEBUG-EMPTY] No emails in response for page ${page}`);
|
|
||||||
// If we're at a page > 1 and got no results, the paging is off, so try again with page 1
|
|
||||||
if (page > 1 && !isLoadMore) {
|
|
||||||
logEmailOp('EMPTY_RESULTS', `No emails returned for page ${page}, resetting to page 1`);
|
|
||||||
dispatch({ type: 'SET_PAGE', payload: 1 });
|
|
||||||
dispatch({ type: 'SET_LOADING', payload: false });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're already at page 1, just update the state with no emails
|
|
||||||
if (!isLoadMore) {
|
|
||||||
logEmailOp('EMPTY_RESULTS', `No emails found in ${state.currentFolder}`);
|
|
||||||
dispatch({ type: 'SET_EMAILS', payload: [] });
|
|
||||||
dispatch({ type: 'SET_TOTAL_EMAILS', payload: 0 });
|
|
||||||
dispatch({ type: 'SET_TOTAL_PAGES', payload: 0 });
|
|
||||||
} else {
|
} else {
|
||||||
// For load more, just set loading to false but keep existing emails
|
// If we can't extract a valid accountId, throw an error
|
||||||
dispatch({ type: 'SET_LOADING', payload: false });
|
throw new Error("Cannot determine account ID for loading emails");
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
}
|
// Normal flow with valid accountId
|
||||||
|
const { normalizedFolder, effectiveAccountId, prefixedFolder } =
|
||||||
// Ensure all emails have proper account ID and folder format
|
normalizeFolderAndAccount(state.currentFolder, accountId);
|
||||||
if (Array.isArray(data.emails)) {
|
|
||||||
// Log email dates for debugging
|
logEmailOp('LOAD_EMAILS', `Loading emails for ${prefixedFolder} (account: ${effectiveAccountId}, isLoadMore: ${isLoadMore}, page: ${page})`);
|
||||||
if (data.emails.length > 0) {
|
|
||||||
logEmailOp('EMAIL_DATES', `First few email dates before processing:`,
|
// Construct query parameters
|
||||||
data.emails.slice(0, 5).map((e: any) => ({
|
const queryParams = new URLSearchParams({
|
||||||
id: e.id.substring(0, 8),
|
folder: normalizedFolder,
|
||||||
subject: e.subject?.substring(0, 20),
|
page: page.toString(),
|
||||||
date: e.date,
|
perPage: perPage.toString(),
|
||||||
dateObj: new Date(e.date),
|
accountId: effectiveAccountId
|
||||||
timestamp: new Date(e.date).getTime()
|
});
|
||||||
}))
|
|
||||||
);
|
// Debug log existing emails count
|
||||||
|
if (isLoadMore) {
|
||||||
|
console.log(`[DEBUG-PAGINATION] Loading more emails. Current page: ${page}, existing emails: ${state.emails.length}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.emails.forEach((email: Email) => {
|
// Try to get cached emails first
|
||||||
// If email doesn't have an accountId, set it to the effective one
|
logEmailOp('CACHE_CHECK', `Checking cache for ${prefixedFolder}, page: ${page}`);
|
||||||
if (!email.accountId) {
|
const cachedEmails = await getCachedEmailsWithTimeout(
|
||||||
email.accountId = effectiveAccountId;
|
session.user.id,
|
||||||
}
|
prefixedFolder,
|
||||||
|
page,
|
||||||
|
perPage,
|
||||||
|
100,
|
||||||
|
effectiveAccountId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (cachedEmails) {
|
||||||
|
logEmailOp('CACHE_HIT', `Using cached data for ${prefixedFolder}, page: ${page}, emails: ${cachedEmails.emails?.length || 0}, isLoadMore: ${isLoadMore}`);
|
||||||
|
|
||||||
// Ensure folder has the proper prefix format
|
// Ensure cached data has emails array property
|
||||||
if (email.folder && !email.folder.includes(':')) {
|
if (Array.isArray(cachedEmails.emails)) {
|
||||||
email.folder = `${email.accountId}:${email.folder}`;
|
// CRITICAL FIX: Double check we're using the right action type based on isLoadMore param
|
||||||
}
|
console.log(`[DEBUG-CACHE_HIT] Dispatching ${isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS'} with ${cachedEmails.emails.length} emails`);
|
||||||
|
|
||||||
// Ensure date is a valid Date object (handle strings or timestamps)
|
// Dispatch appropriate action based on if we're loading more - DO NOT OVERRIDE isLoadMore!
|
||||||
if (email.date && !(email.date instanceof Date)) {
|
dispatch({
|
||||||
try {
|
type: isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS',
|
||||||
// Convert to a proper Date object if it's a string or number
|
payload: cachedEmails.emails
|
||||||
const dateObj = new Date(email.date);
|
});
|
||||||
// Verify it's a valid date
|
|
||||||
if (!isNaN(dateObj.getTime())) {
|
// Set pagination info from cache if available
|
||||||
email.date = dateObj;
|
if (cachedEmails.totalEmails) {
|
||||||
}
|
dispatch({ type: 'SET_TOTAL_EMAILS', payload: cachedEmails.totalEmails });
|
||||||
} catch (err) {
|
}
|
||||||
// If conversion fails, log and use current date as fallback
|
|
||||||
console.error(`Invalid date format for email ${email.id}: ${email.date}`);
|
if (cachedEmails.totalPages) {
|
||||||
email.date = new Date();
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: cachedEmails.totalPages });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update available mailboxes if provided
|
||||||
|
if (cachedEmails.mailboxes && cachedEmails.mailboxes.length > 0) {
|
||||||
|
dispatch({ type: 'SET_MAILBOXES', payload: cachedEmails.mailboxes });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CRITICAL FIX: If this was a loadMore operation, check the result after the dispatch
|
||||||
|
if (isLoadMore) {
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log(`[DEBUG-CACHE_HIT_APPEND] After ${isLoadMore ? 'APPEND' : 'SET'}, email count is now: ${state.emails.length}`);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch emails from API if no cache hit
|
||||||
|
logEmailOp('API_FETCH', `Fetching emails from API: ${queryParams.toString()}, isLoadMore: ${isLoadMore}`);
|
||||||
|
console.log(`[DEBUG-API_FETCH] Fetching from /api/courrier?${queryParams.toString()}`);
|
||||||
|
const response = await fetch(`/api/courrier?${queryParams.toString()}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
// CRITICAL FIX: Try to recover from fetch errors by retrying with different pagination
|
||||||
|
if (isLoadMore && page > 1) {
|
||||||
|
logEmailOp('ERROR_RECOVERY', `Failed to fetch emails for page ${page}, attempting to recover by decrementing page`);
|
||||||
|
console.log(`[DEBUG-ERROR] API returned ${response.status} for page ${page}`);
|
||||||
|
// If we're loading more and there's an error, just decrement the page to avoid getting stuck
|
||||||
|
dispatch({ type: 'SET_PAGE', payload: page - 1 });
|
||||||
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
|
// Also reset total pages to try again
|
||||||
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: page });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorData = await response.json();
|
||||||
|
throw new Error(errorData.error || 'Failed to fetch emails');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log(`[DEBUG-API_RESPONSE] Got response with ${data.emails?.length || 0} emails, totalPages: ${data.totalPages}, totalEmails: ${data.totalEmails}, isLoadMore: ${isLoadMore}`);
|
||||||
|
|
||||||
|
// CRITICAL FIX: Enhanced empty results handling
|
||||||
|
if (!data.emails || data.emails.length === 0) {
|
||||||
|
console.log(`[DEBUG-EMPTY] No emails in response for page ${page}`);
|
||||||
|
// If we're at a page > 1 and got no results, the paging is off, so try again with page 1
|
||||||
|
if (page > 1 && !isLoadMore) {
|
||||||
|
logEmailOp('EMPTY_RESULTS', `No emails returned for page ${page}, resetting to page 1`);
|
||||||
|
dispatch({ type: 'SET_PAGE', payload: 1 });
|
||||||
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're already at page 1, just update the state with no emails
|
||||||
|
if (!isLoadMore) {
|
||||||
|
logEmailOp('EMPTY_RESULTS', `No emails found in ${state.currentFolder}`);
|
||||||
|
dispatch({ type: 'SET_EMAILS', payload: [] });
|
||||||
|
dispatch({ type: 'SET_TOTAL_EMAILS', payload: 0 });
|
||||||
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: 0 });
|
||||||
|
} else {
|
||||||
|
// For load more, just set loading to false but keep existing emails
|
||||||
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all emails have proper account ID and folder format
|
||||||
|
if (Array.isArray(data.emails)) {
|
||||||
|
// Log email dates for debugging
|
||||||
|
if (data.emails.length > 0) {
|
||||||
|
logEmailOp('EMAIL_DATES', `First few email dates before processing:`,
|
||||||
|
data.emails.slice(0, 5).map((e: any) => ({
|
||||||
|
id: e.id.substring(0, 8),
|
||||||
|
subject: e.subject?.substring(0, 20),
|
||||||
|
date: e.date,
|
||||||
|
dateObj: new Date(e.date),
|
||||||
|
timestamp: new Date(e.date).getTime()
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.emails.forEach((email: Email) => {
|
||||||
|
// If email doesn't have an accountId, set it to the effective one
|
||||||
|
if (!email.accountId) {
|
||||||
|
email.accountId = effectiveAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure folder has the proper prefix format
|
||||||
|
if (email.folder && !email.folder.includes(':')) {
|
||||||
|
email.folder = `${email.accountId}:${email.folder}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure date is a valid Date object (handle strings or timestamps)
|
||||||
|
if (email.date && !(email.date instanceof Date)) {
|
||||||
|
try {
|
||||||
|
// Convert to a proper Date object if it's a string or number
|
||||||
|
const dateObj = new Date(email.date);
|
||||||
|
// Verify it's a valid date
|
||||||
|
if (!isNaN(dateObj.getTime())) {
|
||||||
|
email.date = dateObj;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// If conversion fails, log and use current date as fallback
|
||||||
|
console.error(`Invalid date format for email ${email.id}: ${email.date}`);
|
||||||
|
email.date = new Date();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRITICAL FIX: Log what we're about to do
|
||||||
|
console.log(`[DEBUG-DISPATCH] About to dispatch ${isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS'} with ${data.emails?.length || 0} emails`);
|
||||||
|
|
||||||
|
// Update state with fetched data
|
||||||
|
dispatch({
|
||||||
|
type: isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS',
|
||||||
|
payload: Array.isArray(data.emails) ? data.emails : []
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
// Double-check that we've updated the email list correctly after dispatch
|
||||||
// CRITICAL FIX: Log what we're about to do
|
setTimeout(() => {
|
||||||
console.log(`[DEBUG-DISPATCH] About to dispatch ${isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS'} with ${data.emails?.length || 0} emails`);
|
console.log(`[DEBUG-AFTER-DISPATCH] Email count is now: ${state.emails.length}, should include the ${data.emails?.length || 0} new emails we just loaded`);
|
||||||
|
}, 0);
|
||||||
// Update state with fetched data
|
|
||||||
dispatch({
|
if (data.totalEmails) {
|
||||||
type: isLoadMore ? 'APPEND_EMAILS' : 'SET_EMAILS',
|
dispatch({ type: 'SET_TOTAL_EMAILS', payload: data.totalEmails });
|
||||||
payload: Array.isArray(data.emails) ? data.emails : []
|
}
|
||||||
});
|
|
||||||
|
if (data.totalPages) {
|
||||||
// Double-check that we've updated the email list correctly after dispatch
|
dispatch({ type: 'SET_TOTAL_PAGES', payload: data.totalPages });
|
||||||
setTimeout(() => {
|
}
|
||||||
console.log(`[DEBUG-AFTER-DISPATCH] Email count is now: ${state.emails.length}, should include the ${data.emails?.length || 0} new emails we just loaded`);
|
|
||||||
}, 0);
|
// Update available mailboxes if provided
|
||||||
|
if (data.mailboxes && data.mailboxes.length > 0) {
|
||||||
if (data.totalEmails) {
|
dispatch({ type: 'SET_MAILBOXES', payload: data.mailboxes });
|
||||||
dispatch({ type: 'SET_TOTAL_EMAILS', payload: data.totalEmails });
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (data.totalPages) {
|
|
||||||
dispatch({ type: 'SET_TOTAL_PAGES', payload: data.totalPages });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update available mailboxes if provided
|
|
||||||
if (data.mailboxes && data.mailboxes.length > 0) {
|
|
||||||
dispatch({ type: 'SET_MAILBOXES', payload: data.mailboxes });
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logEmailOp('ERROR', `Failed to load emails: ${err instanceof Error ? err.message : String(err)}`);
|
logEmailOp('ERROR', `Failed to load emails: ${err instanceof Error ? err.message : String(err)}`);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user