From b0564388146e8d872940f35904c2f00310a06a6a Mon Sep 17 00:00:00 2001 From: alma Date: Sat, 26 Apr 2025 23:06:39 +0200 Subject: [PATCH] courrier refactor --- app/courrier/page.tsx | 6 +- components/email/BulkActionsToolbar.tsx | 109 ++++++++---------------- components/email/EmailContent.tsx | 38 +++------ components/email/EmailHeader.tsx | 12 +-- components/email/EmailList.tsx | 35 ++++---- components/email/EmailListHeader.tsx | 56 ++++++------ components/email/EmailListItem.tsx | 91 ++++++++++---------- components/email/EmailSidebar.tsx | 92 ++++++++++++-------- 8 files changed, 203 insertions(+), 236 deletions(-) diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 0f5a4ba8..fb5fcf22 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -305,11 +305,11 @@ export default function CourrierPage() { {selectedEmail && ( -
+
-

{selectedEmail.subject || '(No subject)'}

-
+

{selectedEmail.subject || '(No subject)'}

+
From: {selectedEmail.from?.[0]?.name || selectedEmail.from?.[0]?.address || 'Unknown'}
diff --git a/components/email/BulkActionsToolbar.tsx b/components/email/BulkActionsToolbar.tsx index 1a9b3701..fee07e56 100644 --- a/components/email/BulkActionsToolbar.tsx +++ b/components/email/BulkActionsToolbar.tsx @@ -1,14 +1,8 @@ 'use client'; import React from 'react'; -import { Trash, Mail, MailOpen, Archive } from 'lucide-react'; +import { Trash2, EyeOff, Archive } from 'lucide-react'; import { Button } from '@/components/ui/button'; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger -} from '@/components/ui/tooltip'; interface BulkActionsToolbarProps { selectedCount: number; @@ -20,74 +14,41 @@ export default function BulkActionsToolbar({ onBulkAction }: BulkActionsToolbarProps) { return ( -
-
- {selectedCount} {selectedCount === 1 ? 'message' : 'messages'} selected +
+
+ + {selectedCount} selected + +
+
+ + +
- - - - - - - Mark as read - - - - - - - - - Mark as unread - - - - - - - - - Archive - - - - - - - - - Delete - -
); } \ No newline at end of file diff --git a/components/email/EmailContent.tsx b/components/email/EmailContent.tsx index 907ebd9a..1d5beee8 100644 --- a/components/email/EmailContent.tsx +++ b/components/email/EmailContent.tsx @@ -34,7 +34,7 @@ export default function EmailContent({ email }: EmailContentProps) { setContent(
@@ -58,30 +58,16 @@ export default function EmailContent({ email }: EmailContentProps) { } return ( -
-

- - Attachments ({email.attachments.length}) -

-
+
+

Attachments

+
{email.attachments.map((attachment, index) => ( - +
+ + + {attachment.filename} + +
))}
@@ -91,7 +77,7 @@ export default function EmailContent({ email }: EmailContentProps) { if (isLoading) { return (
- +
); } @@ -106,7 +92,7 @@ export default function EmailContent({ email }: EmailContentProps) { } return ( -
+
{content} {renderAttachments()}
diff --git a/components/email/EmailHeader.tsx b/components/email/EmailHeader.tsx index 05b5907a..1b5875e5 100644 --- a/components/email/EmailHeader.tsx +++ b/components/email/EmailHeader.tsx @@ -40,7 +40,7 @@ export default function EmailHeader({ }; return ( -
+
{/* Courrier Title */}
@@ -52,13 +52,13 @@ export default function EmailHeader({
- + setSearchQuery(e.target.value)} - className="pl-8 pr-8 h-9" + className="pl-8 pr-8 h-9 bg-gray-50" /> {searchQuery && ( )} @@ -80,7 +80,7 @@ export default function EmailHeader({ type="submit" size="icon" variant="ghost" - className="h-8 w-8" + className="h-8 w-8 text-gray-600 hover:text-gray-900" onClick={handleSearch} > @@ -95,7 +95,7 @@ export default function EmailHeader({ - diff --git a/components/email/EmailList.tsx b/components/email/EmailList.tsx index 44457b2a..51441b5e 100644 --- a/components/email/EmailList.tsx +++ b/components/email/EmailList.tsx @@ -1,7 +1,7 @@ 'use client'; import React, { useState } from 'react'; -import { Loader2 } from 'lucide-react'; +import { Loader2, Mail } from 'lucide-react'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Email } from '@/hooks/use-courrier'; import EmailListItem from './EmailListItem'; @@ -57,8 +57,8 @@ export default function EmailList({ // Render loading state if (isLoading && emails.length === 0) { return ( -
- +
+
); } @@ -66,12 +66,12 @@ export default function EmailList({ // Render empty state if (emails.length === 0) { return ( -
-

No emails found

-

+

+ +

{currentFolder === 'INBOX' ? "Your inbox is empty. You're all caught up!" - : `The ${currentFolder} folder is empty.`} + : `No emails in this folder`}

); @@ -84,11 +84,13 @@ export default function EmailList({ const someSelected = selectedEmailIds.length > 0 && selectedEmailIds.length < emails.length; return ( -
+
{selectedEmailIds.length > 0 && ( @@ -98,8 +100,11 @@ export default function EmailList({ /> )} - -
+
+
{emails.map((email) => ( onSelectEmail(email.id)} - onToggleSelect={(e) => { + onToggleSelect={(e: React.MouseEvent) => { e.stopPropagation(); onToggleSelect(email.id); }} - onToggleStarred={(e) => { + onToggleStarred={(e: React.MouseEvent) => { e.stopPropagation(); onToggleStarred(email.id); }} @@ -119,12 +124,12 @@ export default function EmailList({ ))} {isLoading && emails.length > 0 && ( -
- +
+
)}
- +
); } \ No newline at end of file diff --git a/components/email/EmailListHeader.tsx b/components/email/EmailListHeader.tsx index 40afad05..8bf348b9 100644 --- a/components/email/EmailListHeader.tsx +++ b/components/email/EmailListHeader.tsx @@ -1,7 +1,7 @@ 'use client'; import React from 'react'; -import { ChevronDown } from 'lucide-react'; +import { ChevronDown, Inbox } from 'lucide-react'; import { Checkbox } from '@/components/ui/checkbox'; import { Button } from '@/components/ui/button'; import { @@ -15,45 +15,37 @@ interface EmailListHeaderProps { allSelected: boolean; someSelected: boolean; onToggleSelectAll: () => void; + currentFolder?: string; + totalEmails?: number; } export default function EmailListHeader({ allSelected, someSelected, onToggleSelectAll, + currentFolder = 'Inbox', + totalEmails = 0 }: EmailListHeaderProps) { return ( -
-
- { - if (input) { - (input as unknown as HTMLInputElement).indeterminate = someSelected && !allSelected; - } - }} - onClick={onToggleSelectAll} - /> - - - - - - - - {allSelected ? 'Unselect all' : 'Select all'} - - - Unselect all - - - -
- -
- Select messages to perform actions +
+
+
+ { + if (input) { + (input as unknown as HTMLInputElement).indeterminate = someSelected && !allSelected; + } + }} + onCheckedChange={onToggleSelectAll} + className="mt-0.5" + /> +

{currentFolder.toLowerCase()}

+
+ + + {totalEmails} emails +
); diff --git a/components/email/EmailListItem.tsx b/components/email/EmailListItem.tsx index 7b1467f2..f6937f38 100644 --- a/components/email/EmailListItem.tsx +++ b/components/email/EmailListItem.tsx @@ -95,64 +95,69 @@ export default function EmailListItem({ return `hsl(${h}, 70%, 80%)`; }; + // Get preview text from email content + const getPreviewText = () => { + if (email.preview) return email.preview; + + let content = email.content || ''; + + // Strip HTML tags if present + content = content.replace(/<[^>]+>/g, ' '); + + // Clean up whitespace + content = content.replace(/\s+/g, ' ').trim(); + + // Limit to ~70 chars + if (content.length > 70) { + return content.substring(0, 70) + '...'; + } + + return content || 'No preview available'; + }; + return (
-
- -
- -
-
- - - {getSenderInitial()} - +
-
-
- {getSenderName()} +
+
+ + {getSenderName()} +
-
- {formatDate(email.date)} +
+ + {formatDate(email.date)} + +
-
-
- {email.subject || '(No subject)'} -
- {email.hasAttachments && ( - 📎 - )} -
+

+ {email.subject || '(No subject)'} +

-
- {email.preview || 'No preview available'} +
+ {getPreviewText()}
- - {!email.read && ( -
-
-
- )}
); } \ No newline at end of file diff --git a/components/email/EmailSidebar.tsx b/components/email/EmailSidebar.tsx index 8252a164..93a68c36 100644 --- a/components/email/EmailSidebar.tsx +++ b/components/email/EmailSidebar.tsx @@ -65,23 +65,23 @@ export default function EmailSidebar({ ); return ( -