import { useState } from 'react'; export type MailFolder = string; export interface Email { id: string; accountId?: string; folder?: string; subject: string; from: string; to: string; date: string; flags: { seen: boolean; flagged: boolean; answered: boolean; draft: boolean; }; body?: string; bodyHtml?: string; } export interface EmailData { to: string; cc?: string; bcc?: string; subject: string; body: string; attachments?: Array<{ name: string; content: string; type: string; }>; } // Hook for managing email operations export const useCourrier = () => { // State for email data const [emails, setEmails] = useState([]); const [selectedEmail, setSelectedEmail] = useState(null); const [selectedEmailIds, setSelectedEmailIds] = useState([]); const [currentFolder, setCurrentFolder] = useState('INBOX'); const [mailboxes, setMailboxes] = useState([]); // State for UI const [isLoading, setIsLoading] = useState(false); const [isSending, setIsSending] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const [error, setError] = useState(null); const [searchQuery, setSearchQuery] = useState(''); const [page, setPage] = useState(1); const [perPage, setPerPage] = useState(20); const [totalPages, setTotalPages] = useState(0); /** * Change the current folder and load emails from that folder */ const changeFolder = async (folder: string, accountId?: string) => { console.log(`Changing folder to ${folder} for account ${accountId || 'default'}`); try { // Reset selected email setSelectedEmail(null); setSelectedEmailIds([]); // Record the new folder setCurrentFolder(folder); // Reset search query when changing folders setSearchQuery(''); // Reset to page 1 setPage(1); // Clear existing emails before loading new ones to prevent UI flicker setEmails([]); // Show loading state setIsLoading(true); // Load emails for the new folder with a deliberate delay to allow state to update await new Promise(resolve => setTimeout(resolve, 100)); await loadEmails(folder, 1, 20, accountId); } catch (error) { console.error(`Error changing to folder ${folder}:`, error); setError(`Failed to load emails from ${folder}: ${error instanceof Error ? error.message : 'Unknown error'}`); } finally { setIsLoading(false); } }; /** * Load emails for the current folder */ const loadEmails = async ( folderOverride?: string, pageOverride?: number, perPageOverride?: number, accountIdOverride?: string ) => { const folderToUse = folderOverride || currentFolder; // Enhanced folder and account handling let normalizedFolder = folderToUse; let normalizedAccountId = accountIdOverride; // Extract account ID from folder if it has a prefix and no explicit account ID was provided if (folderToUse.includes(':')) { const [folderAccountId, baseFolderName] = folderToUse.split(':'); console.log(`Folder has prefix: accountId=${folderAccountId}, baseName=${baseFolderName}`); // If no explicit account ID was provided, use the one from the folder name if (!normalizedAccountId) { normalizedAccountId = folderAccountId; console.log(`Using account ID from folder prefix: ${normalizedAccountId}`); } // If both exist but don't match, log a warning else if (normalizedAccountId !== folderAccountId) { console.warn(`⚠️ Mismatch between folder account prefix (${folderAccountId}) and provided accountId (${normalizedAccountId})`); console.warn(`Using provided accountId (${normalizedAccountId}) but this may cause unexpected behavior`); } } const pageToUse = pageOverride || page; const perPageToUse = perPageOverride || perPage; console.log(`Loading emails: folder=${folderToUse}, page=${pageToUse}, accountId=${normalizedAccountId || 'default'}`); try { setIsLoading(true); setError(''); // Construct the API URL with a unique timestamp to prevent caching let url = `/api/courrier/emails?folder=${encodeURIComponent(folderToUse)}&page=${pageToUse}&perPage=${perPageToUse}`; // Add accountId parameter if specified if (normalizedAccountId) { url += `&accountId=${encodeURIComponent(normalizedAccountId)}`; } // Add cache-busting timestamp url += `&_t=${Date.now()}`; console.log(`Fetching emails from API: ${url}`); const response = await fetch(url); if (!response.ok) { let errorText; try { const errorData = await response.json(); errorText = errorData.error || `Server error: ${response.status}`; } catch { errorText = `HTTP error: ${response.status}`; } console.error(`API error: ${errorText}`); throw new Error(errorText); } const data = await response.json(); console.log(`Received ${data.emails?.length || 0} emails from API`); if (pageToUse === 1 || !pageOverride) { // Replace emails when loading first page console.log(`Setting ${data.emails?.length || 0} emails (replacing existing)`); setEmails(data.emails || []); } else { // Append emails when loading subsequent pages console.log(`Appending ${data.emails?.length || 0} emails to existing list`); setEmails(prev => [...prev, ...(data.emails || [])]); } // Update pagination info setTotalPages(data.totalPages || 0); if (data.mailboxes && data.mailboxes.length > 0) { console.log(`Received ${data.mailboxes.length} mailboxes from API`); setMailboxes(data.mailboxes); } return data; } catch (error) { console.error('Error loading emails:', error); setError(`Failed to load emails: ${error instanceof Error ? error.message : 'Unknown error'}`); // Set empty emails array on error to prevent UI issues if (pageToUse === 1) { setEmails([]); } return null; } finally { setIsLoading(false); } }; return { // State emails, selectedEmail, selectedEmailIds, currentFolder, mailboxes, isLoading, isSending, isDeleting, error, searchQuery, page, perPage, totalPages, // Actions setEmails, setSelectedEmail, setSelectedEmailIds, setCurrentFolder, setMailboxes, setIsLoading, setIsSending, setIsDeleting, setError, setSearchQuery, setPage, setPerPage, setTotalPages, // Methods changeFolder, loadEmails }; };