From 8b0773cfb9ba230e03bedcaf7aa54247b21dc2a5 Mon Sep 17 00:00:00 2001 From: alma Date: Tue, 15 Apr 2025 23:36:57 +0200 Subject: [PATCH] mail page imap connection mime 5 bis rest 16 login page 3 --- app/mail/page.tsx | 209 ++++++++++++++++++---------------------------- 1 file changed, 79 insertions(+), 130 deletions(-) diff --git a/app/mail/page.tsx b/app/mail/page.tsx index 22627c1..c67bd44 100644 --- a/app/mail/page.tsx +++ b/app/mail/page.tsx @@ -1,25 +1,13 @@ 'use client'; -import { useState, useEffect } from 'react'; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Textarea } from "@/components/ui/textarea"; -import { Checkbox } from "@/components/ui/checkbox"; -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, -} from "@/components/ui/alert-dialog"; -import { Avatar, AvatarFallback } from "@/components/ui/avatar"; -import { Label } from "@/components/ui/label"; -import { MoreVertical, Settings, Plus as PlusIcon, Trash2, Edit, Mail, Inbox, Send, Star, Trash, Plus, ChevronLeft, ChevronRight, Search, ChevronDown, Folder, ChevronUp, Reply, Forward, ReplyAll, MoreHorizontal, FolderOpen, X, Paperclip, MessageSquare } from 'lucide-react'; +import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { Label } from '@/components/ui/label'; +import { Avatar, AvatarFallback } from '@/components/ui/avatar'; +import { MoreVertical, Settings, Plus as PlusIcon, Trash2, Edit, Mail, Inbox, Send, Star, Trash, Plus, ChevronLeft, ChevronRight, Search, ChevronDown, Folder, ChevronUp, Reply, Forward, ReplyAll, MoreHorizontal, FolderOpen, X, Paperclip, MessageSquare } from 'lucide-react'; interface Account { id: number; @@ -30,17 +18,15 @@ interface Account { interface Email { id: string; - accountId: string; from: string; fromName?: string; to: string; subject: string; body: string; - preview: string; - category: string; - date: Date; + date: string; read: boolean; starred: boolean; + category?: string; } // Improved MIME Decoder Implementation for Infomaniak @@ -337,7 +323,7 @@ function cleanHtml(html: string): string { .replace(/=C3=AB/g, 'ë') .replace(/=C3=B4/g, 'ô') .replace(/=C3=B9/g, 'ù') - .replace(/=C3=BB/g, 'û') + .replace(/=C3=xBB/g, 'û') .replace(/=C3=80/g, 'À') .replace(/=C3=89/g, 'É') .replace(/=C3=87/g, 'Ç') @@ -389,9 +375,32 @@ function decodeMimeContent(content: string): string { export default function MailPage() { const router = useRouter(); const [loading, setLoading] = useState(true); + const [accounts, setAccounts] = useState([ + { id: 1, name: 'Mail', email: 'alma@governance-labs.org', color: 'bg-blue-500' }, + { id: 2, name: 'Work', email: 'work@governance-labs.org', color: 'bg-green-500' } + ]); + const [selectedAccount, setSelectedAccount] = useState(null); + const [currentView, setCurrentView] = useState('inbox'); + const [showCompose, setShowCompose] = useState(false); + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + const [selectedEmails, setSelectedEmails] = useState([]); + const [showBulkActions, setShowBulkActions] = useState(false); + const [showBcc, setShowBcc] = useState(false); + const [emails, setEmails] = useState([]); + const [error, setError] = useState(null); + const [composeSubject, setComposeSubject] = useState(''); + const [composeTo, setComposeTo] = useState(''); + const [composeCc, setComposeCc] = useState(''); + const [composeBcc, setComposeBcc] = useState(''); + const [composeBody, setComposeBody] = useState(''); + const [selectedEmail, setSelectedEmail] = useState(null); + const [sidebarOpen, setSidebarOpen] = useState(true); + const [foldersOpen, setFoldersOpen] = useState(true); + const [showSettings, setShowSettings] = useState(false); + const [searchQuery, setSearchQuery] = useState(''); + // Check for stored credentials useEffect(() => { - // Check for stored credentials const storedCredentials = localStorage.getItem('imapCredentials'); if (!storedCredentials) { router.push('/mail/login'); @@ -400,6 +409,7 @@ export default function MailPage() { } }, [router]); + // Show loading state if credentials are not loaded if (loading) { return (
@@ -411,36 +421,6 @@ export default function MailPage() { ); } - // Single IMAP account for now - const [accounts, setAccounts] = useState([ - { id: 1, name: 'Mail', email: 'alma@governance-labs.org', color: 'bg-blue-500' }, - { id: 2, name: 'Work', email: 'work@governance-labs.org', color: 'bg-green-500' } - ]); - - // State declarations - const [selectedAccount, setSelectedAccount] = useState(1); - const [currentView, setCurrentView] = useState('inbox'); - const [selectedEmail, setSelectedEmail] = useState(null); - const [sidebarOpen, setSidebarOpen] = useState(true); - const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); - const [composeOpen, setComposeOpen] = useState(false); - const [accountsDropdownOpen, setAccountsDropdownOpen] = useState(false); - const [foldersDropdownOpen, setFoldersDropdownOpen] = useState(false); - const [showAccountActions, setShowAccountActions] = useState(null); - const [showEmailActions, setShowEmailActions] = useState(false); - const [selectedEmails, setSelectedEmails] = useState([]); - const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); - const [deleteType, setDeleteType] = useState<'email' | 'emails' | 'account'>('email'); - const [itemToDelete, setItemToDelete] = useState(null); - const [showBulkActions, setShowBulkActions] = useState(false); - const [showCc, setShowCc] = useState(false); - const [showBcc, setShowBcc] = useState(false); - const [emails, setEmails] = useState([]); - const [error, setError] = useState(null); - const [composeSubject, setComposeSubject] = useState(''); - const [composeRecipient, setComposeRecipient] = useState(''); - const [composeContent, setComposeContent] = useState(''); - // Fetch emails from IMAP API const loadEmails = async () => { setLoading(true); @@ -512,22 +492,22 @@ export default function MailPage() { ...accounts ]; - // Filter emails based on current view + // Filter emails based on selected account and current view const filteredEmails = emails.filter(email => { - if (selectedAccount === 0) return true; - // Use the email address to match instead of accountId - const selectedAccountEmail = accounts.find(acc => acc.id === selectedAccount)?.email; - return email.from === selectedAccountEmail || email.to === selectedAccountEmail; + if (selectedAccount) { + return email.to === selectedAccount.email; + } + return true; }).filter(email => { switch (currentView) { - case "inbox": - return email.category === "inbox"; - case "starred": + case 'inbox': + return true; + case 'starred': return email.starred; - case "sent": - return email.category === "sent"; - case "trash": - return email.category === "trash"; + case 'sent': + return email.category === 'sent'; + case 'trash': + return email.category === 'trash'; default: return true; } @@ -552,8 +532,13 @@ export default function MailPage() { }; // Update email click handler to work without mark-read endpoint - const handleEmailSelect = (email: Email) => { - setSelectedEmail(selectedEmail?.id === email.id ? null : email); + const handleEmailSelect = (emailId: string) => { + setSelectedEmails(prev => { + if (prev.includes(emailId)) { + return prev.filter(id => id !== emailId); + } + return [...prev, emailId]; + }); }; // Toggle starred status @@ -578,45 +563,23 @@ export default function MailPage() { }; // Handle bulk selection - const toggleEmailSelection = (emailId: string, e: React.MouseEvent) => { - e.stopPropagation(); - setSelectedEmails(prev => - prev.includes(emailId) - ? prev.filter(id => id !== emailId) - : [...prev, emailId] - ); - setShowBulkActions(true); - }; - - // Handle select all const toggleSelectAll = () => { if (selectedEmails.length === filteredEmails.length) { setSelectedEmails([]); - setShowBulkActions(false); } else { setSelectedEmails(filteredEmails.map(email => email.id)); - setShowBulkActions(true); } }; // Handle bulk delete const handleBulkDelete = () => { - setDeleteType('emails'); setShowDeleteConfirm(true); }; // Handle delete confirmation const handleDeleteConfirm = async () => { try { - if (deleteType === 'email' && itemToDelete) { - await fetch('/api/mail/delete', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ emailIds: [itemToDelete.toString()] }) - }); - setEmails(emails.filter(email => email.id !== itemToDelete.toString())); - setSelectedEmail(null); - } else if (deleteType === 'emails') { + if (selectedEmails.length > 0) { await fetch('/api/mail/delete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -667,7 +630,7 @@ export default function MailPage() { const selectedEmailData = getSelectedEmail(); if (!selectedEmailData) return; - setComposeOpen(true); + setShowCompose(true); const subject = `${type === 'forward' ? 'Fwd: ' : 'Re: '}${selectedEmailData.subject}`; let to = ''; let content = ''; @@ -687,21 +650,10 @@ export default function MailPage() { } setComposeSubject(subject); - setComposeRecipient(to); - setComposeContent(content); + setComposeTo(to); + setComposeBody(content); }; - if (loading) { - return ( -
-
- -

Loading your emails...

-
-
- ); - } - if (error) { return (
@@ -724,7 +676,7 @@ export default function MailPage() {
{/* Sidebar */}
+ ${foldersOpen ? 'fixed inset-y-0 left-0 z-40' : 'hidden'} md:block`}> {/* Courrier Title */}
@@ -737,7 +689,7 @@ export default function MailPage() {
- {accountsDropdownOpen && ( + {foldersOpen && (
{/* All Accounts Option */} {/* Account Actions Dropdown */} - {showAccountActions === account.id && ( + {showSettings && (
{/* Folders Dropdown */} - {foldersDropdownOpen && sidebarOpen && ( + {foldersOpen && sidebarOpen && (
    {folders.map(folder => (
  • @@ -937,9 +886,11 @@ export default function MailPage() {
    {filteredEmails.length > 0 && ( - )}

    @@ -1010,7 +961,7 @@ export default function MailPage() { className={`flex items-center p-4 hover:bg-gray-50 transition-colors duration-150 cursor-pointer ${ selectedEmail?.id === email.id ? 'bg-blue-50' : '' } ${!email.read ? 'bg-blue-50/20' : ''}`} - onClick={() => handleEmailSelect(email)} + onClick={() => handleEmailSelect(email.id)} >
    @@ -1031,7 +982,7 @@ export default function MailPage() { {email.subject}

    - {formatDate(email.date.toISOString())} + {formatDate(email.date)}
    @@ -1110,8 +1061,6 @@ export default function MailPage() { size="icon" className="text-gray-400 hover:text-gray-900" onClick={() => { - setDeleteType('email'); - setItemToDelete(parseInt(selectedEmail.id)); setShowDeleteConfirm(true); }} > @@ -1135,7 +1084,7 @@ export default function MailPage() {

    - {formatDate(selectedEmail.date.toISOString())} + {formatDate(selectedEmail.date)}