Neah/components/email/EmailSidebar.tsx

205 lines
7.5 KiB
TypeScript

'use client';
import React, { useState } from 'react';
import {
Inbox, Send, Trash, Archive, Star,
File, RefreshCw, Plus, MailOpen, Settings,
ChevronDown, ChevronRight, Mail
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Badge } from '@/components/ui/badge';
interface EmailSidebarProps {
currentFolder: string;
currentAccount: string;
accounts: Array<{
id: string;
email: string;
folders: string[];
}>;
onFolderChange: (folder: string, accountId: string) => void;
onRefresh: () => void;
onCompose: () => void;
isLoading: boolean;
}
export default function EmailSidebar({
currentFolder,
currentAccount,
accounts,
onFolderChange,
onRefresh,
onCompose,
isLoading
}: EmailSidebarProps) {
const [showAccounts, setShowAccounts] = useState(true);
const [expandedAccount, setExpandedAccount] = useState<string | null>(currentAccount);
// Get the appropriate icon for a folder
const getFolderIcon = (folder: string) => {
const folderLower = folder.toLowerCase();
switch (folderLower) {
case 'inbox':
return <Inbox className="h-4 w-4" />;
case 'sent':
case 'sent items':
return <Send className="h-4 w-4" />;
case 'drafts':
return <File className="h-4 w-4" />;
case 'trash':
case 'deleted':
case 'bin':
return <Trash className="h-4 w-4" />;
case 'archive':
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" />;
}
};
// Group folders into standard and custom
const getStandardFolders = (folders: string[]) => {
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) => {
setExpandedAccount(expandedAccount === accountId ? null : accountId);
};
return (
<aside className="w-64 border-r h-full flex flex-col bg-white/95 backdrop-blur-sm">
{/* Compose button area */}
<div className="p-4">
<Button
className="w-full bg-blue-600 text-white rounded-lg hover:bg-blue-700 flex items-center justify-center py-2"
onClick={onCompose}
>
<Plus className="h-4 w-4 mr-2" />
Compose
</Button>
</div>
{/* Accounts and folders navigation */}
<ScrollArea className="flex-1">
<div className="p-2 space-y-1">
{/* Accounts header with toggle */}
<div className="flex items-center justify-between px-2 py-2 text-sm font-medium text-gray-600">
<span>Accounts</span>
<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>
{/* Accounts list */}
{showAccounts && (
<div className="space-y-1">
{accounts.map((account) => (
<div key={account.id} className="space-y-1">
{/* Account button */}
<Button
variant="ghost"
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)}
>
<div className="flex items-center">
<Mail className="h-4 w-4 mr-2" />
<span className="truncate">{account.email}</span>
</div>
{expandedAccount === account.id ? (
<ChevronDown className="h-4 w-4" />
) : (
<ChevronRight className="h-4 w-4" />
)}
</Button>
{/* Account folders - shown when account is expanded */}
{expandedAccount === account.id && (
<div className="pl-6 space-y-1">
{getStandardFolders(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 w-full">
<span className="flex items-center">
{getFolderIcon(folder)}
<span className="ml-2 capitalize">{folder.toLowerCase()}</span>
</span>
{folder === 'INBOX' && (
<span className="ml-auto bg-blue-600 text-white text-xs px-2 py-0.5 rounded-full">
{/* Unread count would go here */}
</span>
)}
</div>
</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>
</ScrollArea>
{/* Settings button (bottom) */}
<div className="p-2 border-t border-gray-100">
<Button
variant="ghost"
size="sm"
className="w-full justify-start text-gray-600 hover:text-gray-900"
>
<Settings className="h-4 w-4 mr-2" />
<span>Email settings</span>
</Button>
</div>
</aside>
);
}