- From: {selectedEmail.from?.[0]?.name || selectedEmail.from?.[0]?.address || 'Unknown'}
+ {/* Email list */}
+
+
+ {/* Email content */}
+
+ {selectedEmail ? (
+ <>
+ {/* Email actions header */}
+
+
+
+
+
+ {selectedEmail.subject || '(No subject)'}
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+ {/* Email content area */}
+ >
+ ) : (
+
+
+
Select an email to view its contents
)}
diff --git a/components/email/EmailContent.tsx b/components/email/EmailContent.tsx
index 1d5beee8..a34da7f8 100644
--- a/components/email/EmailContent.tsx
+++ b/components/email/EmailContent.tsx
@@ -1,11 +1,12 @@
'use client';
import React, { useState, useEffect } from 'react';
-import { Loader2, Paperclip, FileDown } from 'lucide-react';
+import { Loader2, Paperclip, FileDown, Download } from 'lucide-react';
import { sanitizeHtml } from '@/lib/utils/email-formatter';
import { Button } from '@/components/ui/button';
import { Email } from '@/hooks/use-courrier';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
+import { ScrollArea } from '@/components/ui/scroll-area';
interface EmailContentProps {
email: Email;
@@ -62,11 +63,12 @@ export default function EmailContent({ email }: EmailContentProps) {
Attachments
{email.attachments.map((attachment, index) => (
-
+
-
+
{attachment.filename}
+
))}
@@ -92,9 +94,27 @@ export default function EmailContent({ email }: EmailContentProps) {
}
return (
-
- {content}
- {renderAttachments()}
-
+
+
+
+
+
+ {email.from?.[0]?.name?.[0] || email.from?.[0]?.address?.[0] || '?'}
+
+
+
+
+ {email.from?.[0]?.name || email.from?.[0]?.address || 'Unknown'}
+
+
+ to {email.to?.[0]?.address || 'you'}
+
+
+
+
+ {content}
+ {renderAttachments()}
+
+
);
}
\ No newline at end of file
diff --git a/components/email/EmailList.tsx b/components/email/EmailList.tsx
index 51441b5e..eac71c6a 100644
--- a/components/email/EmailList.tsx
+++ b/components/email/EmailList.tsx
@@ -1,12 +1,12 @@
'use client';
import React, { useState } from 'react';
-import { Loader2, Mail } from 'lucide-react';
-import { ScrollArea } from '@/components/ui/scroll-area';
+import { Loader2, Mail, Search, X } from 'lucide-react';
import { Email } from '@/hooks/use-courrier';
import EmailListItem from './EmailListItem';
import EmailListHeader from './EmailListHeader';
import BulkActionsToolbar from './BulkActionsToolbar';
+import { Input } from '@/components/ui/input';
interface EmailListProps {
emails: Email[];
@@ -22,6 +22,7 @@ interface EmailListProps {
onBulkAction: (action: 'delete' | 'mark-read' | 'mark-unread' | 'archive') => void;
onToggleStarred: (emailId: string) => void;
onLoadMore: () => void;
+ onSearch?: (query: string) => void;
}
export default function EmailList({
@@ -37,9 +38,11 @@ export default function EmailList({
onToggleSelectAll,
onBulkAction,
onToggleStarred,
- onLoadMore
+ onLoadMore,
+ onSearch
}: EmailListProps) {
const [scrollPosition, setScrollPosition] = useState(0);
+ const [searchQuery, setSearchQuery] = useState('');
// Handle scroll to detect when user reaches the bottom
const handleScroll = (event: React.UIEvent
) => {
@@ -54,6 +57,17 @@ export default function EmailList({
}
};
+ // Handle search
+ const handleSearch = (e: React.FormEvent) => {
+ e.preventDefault();
+ onSearch?.(searchQuery);
+ };
+
+ const clearSearch = () => {
+ setSearchQuery('');
+ onSearch?.('');
+ };
+
// Render loading state
if (isLoading && emails.length === 0) {
return (
@@ -66,12 +80,14 @@ export default function EmailList({
// Render empty state
if (emails.length === 0) {
return (
-
+
- {currentFolder === 'INBOX'
- ? "Your inbox is empty. You're all caught up!"
- : `No emails in this folder`}
+ {searchQuery
+ ? 'No emails match your search'
+ : currentFolder === 'INBOX'
+ ? "Your inbox is empty. You're all caught up!"
+ : 'No emails in this folder'}
);
@@ -84,14 +100,40 @@ export default function EmailList({
const someSelected = selectedEmailIds.length > 0 && selectedEmailIds.length < emails.length;
return (
-
-
+
+ {/* Search header */}
+
{selectedEmailIds.length > 0 && (
-
-
- {
- if (input) {
- (input as unknown as HTMLInputElement).indeterminate = someSelected && !allSelected;
- }
- }}
- onCheckedChange={onToggleSelectAll}
- className="mt-0.5"
- />
- {currentFolder.toLowerCase()}
-
-
-
- {totalEmails} emails
-
+
+
+ {
+ if (input) {
+ (input as unknown as HTMLInputElement).indeterminate = someSelected && !allSelected;
+ }
+ }}
+ onCheckedChange={onToggleSelectAll}
+ className="mt-0.5"
+ />
+ {currentFolder.toLowerCase()}
+
+
+ {totalEmails} {totalEmails === 1 ? 'email' : 'emails'}
+
);
}
\ No newline at end of file
diff --git a/components/email/EmailSidebar.tsx b/components/email/EmailSidebar.tsx
index 93a68c36..86cdc41b 100644
--- a/components/email/EmailSidebar.tsx
+++ b/components/email/EmailSidebar.tsx
@@ -3,7 +3,7 @@
import React from 'react';
import {
Inbox, Send, Trash, Archive, Star,
- File, RefreshCw, Plus, MailOpen
+ File, RefreshCw, Plus, MailOpen, Settings
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
@@ -65,94 +65,78 @@ export default function EmailSidebar({
);
return (
-