2025-03-30 16:42:51 -03:00
|
|
|
import React, { useState } from 'react';
|
2025-03-30 19:28:28 -03:00
|
|
|
import { AccountSwitcher } from './account-switcher';
|
2025-03-30 16:42:51 -03:00
|
|
|
import { MailList } from './mail-list';
|
2025-03-30 19:28:28 -03:00
|
|
|
import { MailDisplay } from './mail-display';
|
2025-04-02 02:43:36 -03:00
|
|
|
import { Nav } from './nav';
|
2025-03-30 19:28:28 -03:00
|
|
|
import { mails, accounts } from '../data';
|
2025-03-30 16:42:51 -03:00
|
|
|
|
2025-03-30 19:28:28 -03:00
|
|
|
export function Mail() {
|
2025-03-30 16:42:51 -03:00
|
|
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
2025-04-02 02:43:36 -03:00
|
|
|
const [selectedMailId, setSelectedMailId] = useState<string | null>(mails[0].id);
|
2025-03-30 16:42:51 -03:00
|
|
|
const [activeTab, setActiveTab] = useState('all');
|
|
|
|
|
2025-03-30 19:28:28 -03:00
|
|
|
const filteredMails = activeTab === 'all'
|
|
|
|
? mails
|
|
|
|
: mails.filter(mail => !mail.read);
|
|
|
|
|
2025-04-02 02:43:36 -03:00
|
|
|
// Icons
|
|
|
|
const ArchiveIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<rect width="20" height="5" x="2" y="3" rx="1" />
|
|
|
|
<path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" />
|
|
|
|
<path d="M10 12h4" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const TrashIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="M3 6h18" />
|
|
|
|
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
|
|
|
|
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const DeleteIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="M20 6H4" />
|
|
|
|
<path d="M10 11v6" />
|
|
|
|
<path d="M14 11v6" />
|
|
|
|
<path d="M3 6h2l1.5 14a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2L21 6h2" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const ClockIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<circle cx="12" cy="12" r="10" />
|
|
|
|
<polyline points="12 6 12 12 16 14" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const ArrowLeftIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="m12 19-7-7 7-7" />
|
|
|
|
<path d="M19 12H5" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const ArrowRightIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="M5 12h14" />
|
|
|
|
<path d="m12 5 7 7-7 7" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const MoreIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<circle cx="12" cy="12" r="1" />
|
|
|
|
<circle cx="19" cy="12" r="1" />
|
|
|
|
<circle cx="5" cy="12" r="1" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const SearchIcon = () => (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<circle cx="11" cy="11" r="8" />
|
|
|
|
<path d="m21 21-4.3-4.3" />
|
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
const navItems = [
|
|
|
|
{
|
|
|
|
title: "Inbox",
|
|
|
|
label: "128",
|
|
|
|
icon: (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<polyline points="22 12 16 12 14 15 10 15 8 12 2 12" />
|
|
|
|
<path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
variant: "default" as const,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: "Drafts",
|
|
|
|
label: "9",
|
|
|
|
icon: (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
|
|
|
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
variant: "ghost" as const,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: "Sent",
|
|
|
|
icon: (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="m22 2-7 20-4-9-9-4Z" />
|
|
|
|
<path d="M22 2 11 13" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
variant: "ghost" as const,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: "Junk",
|
|
|
|
label: "23",
|
|
|
|
icon: (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<rect width="20" height="5" x="2" y="3" rx="1" />
|
|
|
|
<path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" />
|
|
|
|
<path d="M10 12h4" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
variant: "ghost" as const,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: "Trash",
|
|
|
|
icon: (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="M3 6h18" />
|
|
|
|
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
|
|
|
|
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
variant: "ghost" as const,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: "Archive",
|
|
|
|
icon: (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<rect width="20" height="5" x="2" y="3" rx="1" />
|
|
|
|
<path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8" />
|
|
|
|
<path d="M10 12h4" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
variant: "ghost" as const,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2025-03-30 16:42:51 -03:00
|
|
|
return (
|
2025-04-02 02:43:36 -03:00
|
|
|
<div className="flex h-screen bg-white">
|
|
|
|
{/* Sidebar */}
|
|
|
|
<div className={`${isCollapsed ? 'w-16' : 'w-64'} border-r flex flex-col transition-all duration-200 bg-white`}>
|
2025-03-30 19:28:28 -03:00
|
|
|
<div className="p-4 border-b">
|
|
|
|
<AccountSwitcher isCollapsed={isCollapsed} accounts={accounts} />
|
|
|
|
</div>
|
2025-04-02 02:43:36 -03:00
|
|
|
<div className="flex-1 overflow-auto py-2">
|
|
|
|
<Nav links={navItems} isCollapsed={isCollapsed} />
|
|
|
|
</div>
|
|
|
|
<div className="p-4 border-t">
|
|
|
|
<button
|
|
|
|
onClick={() => setIsCollapsed(!isCollapsed)}
|
|
|
|
className="w-full flex items-center justify-center text-sm text-gray-500 hover:text-gray-900"
|
|
|
|
>
|
|
|
|
{isCollapsed ? (
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="m9 18 6-6-6-6" />
|
|
|
|
</svg>
|
|
|
|
) : (
|
|
|
|
<div className="flex items-center">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
<path d="m15 18-6-6 6-6" />
|
|
|
|
</svg>
|
|
|
|
<span className="ml-2">Collapse</span>
|
|
|
|
</div>
|
|
|
|
)}
|
2025-03-30 19:28:28 -03:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-04-02 02:43:36 -03:00
|
|
|
{/* Mail list */}
|
|
|
|
<div className="w-80 border-r flex flex-col">
|
|
|
|
<div className="p-4 border-b flex flex-col gap-4">
|
2025-03-30 19:28:28 -03:00
|
|
|
<div className="flex justify-between items-center">
|
2025-04-02 02:43:36 -03:00
|
|
|
<h2 className="text-xl font-semibold">Inbox</h2>
|
|
|
|
<div className="flex space-x-1">
|
|
|
|
<button className={`px-3 py-1.5 text-sm rounded-md ${activeTab === 'all' ? 'bg-gray-100 text-gray-900' : 'text-gray-500'}`} onClick={() => setActiveTab('all')}>
|
2025-03-30 19:28:28 -03:00
|
|
|
All mail
|
|
|
|
</button>
|
2025-04-02 02:43:36 -03:00
|
|
|
<button className={`px-3 py-1.5 text-sm rounded-md ${activeTab === 'unread' ? 'bg-gray-100 text-gray-900' : 'text-gray-500'}`} onClick={() => setActiveTab('unread')}>
|
2025-03-30 19:28:28 -03:00
|
|
|
Unread
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-04-02 02:43:36 -03:00
|
|
|
|
|
|
|
<div className="flex relative">
|
|
|
|
<SearchIcon className="absolute left-3 top-2.5 h-4 w-4 text-gray-500" />
|
2025-03-30 19:28:28 -03:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
placeholder="Search"
|
2025-04-02 02:43:36 -03:00
|
|
|
className="w-full py-2 pl-9 pr-4 border rounded-md text-sm bg-transparent"
|
2025-03-30 19:28:28 -03:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-04-02 02:43:36 -03:00
|
|
|
|
|
|
|
<div className="flex gap-1 border-b p-2">
|
|
|
|
<button className="p-1 rounded-md hover:bg-gray-100">
|
|
|
|
<ArchiveIcon />
|
|
|
|
</button>
|
|
|
|
<button className="p-1 rounded-md hover:bg-gray-100">
|
|
|
|
<TrashIcon />
|
|
|
|
</button>
|
|
|
|
<button className="p-1 rounded-md hover:bg-gray-100">
|
|
|
|
<DeleteIcon />
|
|
|
|
</button>
|
|
|
|
<span className="flex-1"></span>
|
|
|
|
<button className="p-1 rounded-md hover:bg-gray-100">
|
|
|
|
<ClockIcon />
|
|
|
|
</button>
|
|
|
|
<button className="p-1 rounded-md hover:bg-gray-100">
|
|
|
|
<ArrowLeftIcon />
|
|
|
|
</button>
|
|
|
|
<button className="p-1 rounded-md hover:bg-gray-100">
|
|
|
|
<ArrowRightIcon />
|
|
|
|
</button>
|
|
|
|
<button className="p-1 rounded-md hover:bg-gray-100">
|
|
|
|
<MoreIcon />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
2025-03-30 19:28:28 -03:00
|
|
|
<div className="flex-1 overflow-auto">
|
|
|
|
<MailList
|
|
|
|
items={filteredMails}
|
|
|
|
selectedId={selectedMailId}
|
|
|
|
onSelect={setSelectedMailId}
|
2025-03-30 16:42:51 -03:00
|
|
|
/>
|
2025-03-30 19:28:28 -03:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-04-02 02:43:36 -03:00
|
|
|
{/* Mail content */}
|
2025-03-30 19:28:28 -03:00
|
|
|
<div className="flex-1">
|
|
|
|
<MailDisplay mail={mails.find(mail => mail.id === selectedMailId) || null} />
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-03-30 16:42:51 -03:00
|
|
|
);
|
|
|
|
}
|