courrier multi account restore compose

This commit is contained in:
alma 2025-04-29 08:54:39 +02:00
parent 4770b9858e
commit a0fcbc3b62

View File

@ -4,32 +4,24 @@ import React, { useState } from 'react';
import { import {
Inbox, Send, Trash, Archive, Star, Inbox, Send, Trash, Archive, Star,
File, RefreshCw, Plus, MailOpen, Settings, File, RefreshCw, Plus, MailOpen, Settings,
ChevronDown, ChevronRight, ChevronUp, Mail, AlertCircle, ChevronDown, ChevronRight, Mail
MoreVertical, Edit, Trash2, AlertOctagon, Folder
} from 'lucide-react'; } from 'lucide-react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { ScrollArea } from '@/components/ui/scroll-area'; import { ScrollArea } from '@/components/ui/scroll-area';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '@/components/ui/dropdown-menu';
import { toast } from '@/components/ui/use-toast';
interface EmailSidebarProps { interface EmailSidebarProps {
currentFolder: string; currentFolder: string;
currentAccount: string; currentAccount: string;
accounts: Array<{ accounts: Array<{
id: string; id: string;
name: string;
email: string; email: string;
color: string;
folders: string[]; folders: string[];
}>; }>;
onFolderChange: (folder: string, accountId: string) => void; onFolderChange: (folder: string, accountId: string) => void;
onRefresh: () => void; onRefresh: () => void;
onCompose: () => void; onCompose: () => void;
onAddAccount: () => void;
onEditAccount: (accountId: string) => void;
onDeleteAccount: (accountId: string) => void;
isLoading: boolean; isLoading: boolean;
} }
@ -40,9 +32,6 @@ export default function EmailSidebar({
onFolderChange, onFolderChange,
onRefresh, onRefresh,
onCompose, onCompose,
onAddAccount,
onEditAccount,
onDeleteAccount,
isLoading isLoading
}: EmailSidebarProps) { }: EmailSidebarProps) {
const [showAccounts, setShowAccounts] = useState(true); const [showAccounts, setShowAccounts] = useState(true);
@ -52,26 +41,42 @@ export default function EmailSidebar({
const getFolderIcon = (folder: string) => { const getFolderIcon = (folder: string) => {
const folderLower = folder.toLowerCase(); const folderLower = folder.toLowerCase();
if (folderLower.includes('inbox')) { switch (folderLower) {
return <Inbox className="h-4 w-4 text-gray-500" />; case 'inbox':
} else if (folderLower.includes('sent')) { return <Inbox className="h-4 w-4" />;
return <Send className="h-4 w-4 text-gray-500" />; case 'sent':
} else if (folderLower.includes('trash')) { case 'sent items':
return <Trash className="h-4 w-4 text-gray-500" />; return <Send className="h-4 w-4" />;
} else if (folderLower.includes('archive')) { case 'drafts':
return <Archive className="h-4 w-4 text-gray-500" />; return <File className="h-4 w-4" />;
} else if (folderLower.includes('draft')) { case 'trash':
return <Edit className="h-4 w-4 text-gray-500" />; case 'deleted':
} else if (folderLower.includes('spam') || folderLower.includes('junk')) { case 'bin':
return <AlertOctagon className="h-4 w-4 text-gray-500" />; return <Trash className="h-4 w-4" />;
} else { case 'archive':
return <Folder className="h-4 w-4 text-gray-500" />; case 'archived':
return <Archive className="h-4 w-4" />;
case 'starred':
case 'important':
return <Star className="h-4 w-4" />;
default:
return <MailOpen className="h-4 w-4" />;
} }
}; };
// Helper to format folder names // Group folders into standard and custom
const formatFolderName = (folder: string) => { const getStandardFolders = (folders: string[]) => {
return folder.charAt(0).toUpperCase() + folder.slice(1).toLowerCase(); const standardFolders = ['INBOX', 'Sent', 'Drafts', 'Trash', 'Archive', 'Junk'];
return standardFolders.filter(f =>
folders.includes(f) || folders.some(folder => folder.toLowerCase() === f.toLowerCase())
);
};
const getCustomFolders = (folders: string[]) => {
const standardFolders = ['INBOX', 'Sent', 'Drafts', 'Trash', 'Archive', 'Junk'];
return folders.filter(f =>
!standardFolders.some(sf => sf.toLowerCase() === f.toLowerCase())
);
}; };
const handleAccountClick = (accountId: string) => { const handleAccountClick = (accountId: string) => {
@ -97,26 +102,16 @@ export default function EmailSidebar({
{/* Accounts header with toggle */} {/* Accounts header with toggle */}
<div className="flex items-center justify-between px-2 py-2 text-sm font-medium text-gray-600"> <div className="flex items-center justify-between px-2 py-2 text-sm font-medium text-gray-600">
<span>Accounts</span> <span>Accounts</span>
<div className="flex items-center gap-2"> <button
<Button onClick={() => setShowAccounts(!showAccounts)}
variant="ghost" className="text-gray-400 hover:text-gray-600"
size="sm" >
className="h-7 w-7 p-0 text-gray-400 hover:text-gray-600" {showAccounts ? (
onClick={onAddAccount} <ChevronDown className="h-4 w-4" />
> ) : (
<Plus className="h-4 w-4" /> <ChevronRight className="h-4 w-4" />
</Button> )}
<button </button>
onClick={() => setShowAccounts(!showAccounts)}
className="text-gray-400 hover:text-gray-600"
>
{showAccounts ? (
<ChevronDown className="h-4 w-4" />
) : (
<ChevronRight className="h-4 w-4" />
)}
</button>
</div>
</div> </div>
{/* Accounts list */} {/* Accounts list */}
@ -125,73 +120,66 @@ export default function EmailSidebar({
{accounts.map((account) => ( {accounts.map((account) => (
<div key={account.id} className="space-y-1"> <div key={account.id} className="space-y-1">
{/* Account button */} {/* Account button */}
<div <Button
className={`flex items-center w-full px-2 py-1 rounded-md cursor-pointer ${ variant="ghost"
currentAccount === account.id ? 'bg-gray-100' : '' className={`w-full justify-between p-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 ${
expandedAccount === account.id ? 'bg-gray-100' : ''
}`} }`}
onClick={() => handleAccountClick(account.id)} onClick={() => handleAccountClick(account.id)}
> >
<div className={`w-3 h-3 rounded-full ${account.color} mr-2`}></div> <div className="flex items-center">
<span className="truncate text-gray-700 flex-1">{account.name}</span> <Mail className="h-4 w-4 mr-2" />
<span className="truncate">{account.email}</span>
{/* More options button (⋮) */} </div>
{account.id !== 'loading-account' && ( {expandedAccount === account.id ? (
<DropdownMenu> <ChevronDown className="h-4 w-4" />
<DropdownMenuTrigger asChild> ) : (
<button <ChevronRight className="h-4 w-4" />
type="button"
className="ml-1 text-gray-400 hover:text-gray-600 cursor-pointer flex items-center justify-center h-5 w-5"
onClick={e => e.stopPropagation()}
>
<span style={{ fontSize: '18px', lineHeight: 1 }}></span>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => onEditAccount(account.id)}>
Edit
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onDeleteAccount(account.id)}>
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)} )}
</Button>
{/* Expand/collapse arrow */}
{account.id !== 'loading-account' && (
<button
type="button"
className="ml-1 text-gray-400 hover:text-gray-600 cursor-pointer flex items-center justify-center h-5 w-5"
onClick={e => { e.stopPropagation(); handleAccountClick(account.id); }}
>
{expandedAccount === account.id ? <ChevronUp className="h-3 w-3" /> : <ChevronDown className="h-3 w-3" />}
</button>
)}
</div>
{/* Account folders - shown when account is expanded */} {/* Account folders - shown when account is expanded */}
{expandedAccount === account.id && account.folders && account.folders.length > 0 && ( {expandedAccount === account.id && (
<div className="pl-4"> <div className="pl-6 space-y-1">
{account.folders.map((folder) => ( {getStandardFolders(account.folders).map((folder) => (
<Button <Button
key={folder} key={folder}
variant="ghost" variant={currentFolder === folder && currentAccount === account.id ? "secondary" : "ghost"}
className={`w-full justify-start text-xs py-1 h-7 ${ className={`w-full justify-start ${
currentFolder === folder && currentAccount === account.id ? 'bg-gray-100' : '' currentFolder === folder && currentAccount === account.id ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900'
}`} }`}
onClick={() => onFolderChange(folder, account.id)} onClick={() => onFolderChange(folder, account.id)}
> >
<div className="flex items-center w-full"> <div className="flex items-center w-full">
{getFolderIcon(folder)} <span className="flex items-center">
<span className="ml-2 truncate text-gray-700">{formatFolderName(folder)}</span> {getFolderIcon(folder)}
<span className="ml-2 capitalize">{folder.toLowerCase()}</span>
</span>
{folder === 'INBOX' && ( {folder === 'INBOX' && (
<span className="ml-auto bg-blue-500 text-white text-[10px] px-1.5 rounded-full"> <span className="ml-auto bg-blue-600 text-white text-xs px-2 py-0.5 rounded-full">
{/* Unread count would go here */} {/* Unread count would go here */}
</span> </span>
)} )}
</div> </div>
</Button> </Button>
))} ))}
{/* Custom folders */}
{getCustomFolders(account.folders).map(folder => (
<Button
key={folder}
variant={currentFolder === folder && currentAccount === account.id ? "secondary" : "ghost"}
className={`w-full justify-start ${
currentFolder === folder && currentAccount === account.id ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900'
}`}
onClick={() => onFolderChange(folder, account.id)}
>
<div className="flex items-center">
{getFolderIcon(folder)}
<span className="ml-2 truncate">{folder}</span>
</div>
</Button>
))}
</div> </div>
)} )}
</div> </div>