mail page ui correction maj 3

This commit is contained in:
alma 2025-04-16 11:38:12 +02:00
parent 019abfab96
commit 508157549b

View File

@ -390,6 +390,20 @@ function decodeMimeContent(content: string): string {
return cleanHtml(content);
}
// Add this helper function
const renderEmailContent = (email: Email) => {
const decodedContent = decodeMimeContent(email.body);
if (email.body.includes('Content-Type: text/html')) {
return <div dangerouslySetInnerHTML={{ __html: decodedContent }} />;
}
return <div className="whitespace-pre-wrap">{decodedContent}</div>;
};
// Add this helper function
const decodeEmailContent = (content: string, charset: string = 'utf-8') => {
return convertCharset(content, charset);
};
export default function MailPage() {
const router = useRouter();
const [loading, setLoading] = useState(true);
@ -425,6 +439,7 @@ export default function MailPage() {
const [deleteType, setDeleteType] = useState<'email' | 'emails' | 'account'>('email');
const [itemToDelete, setItemToDelete] = useState<number | null>(null);
const [showCc, setShowCc] = useState(false);
const [contentLoading, setContentLoading] = useState(false);
// Check for stored credentials
useEffect(() => {
@ -489,7 +504,8 @@ export default function MailPage() {
date: new Date(email.date),
read: email.read || false,
starred: email.starred || false,
category: email.category || 'inbox'
category: email.category || 'inbox',
body: decodeMimeContent(email.body)
}));
setEmails(processedEmails);
@ -539,12 +555,15 @@ export default function MailPage() {
// Add email action handlers
const handleEmailSelect = (emailId: number) => {
setSelectedEmails(prev => {
if (prev.includes(emailId)) {
return prev.filter(id => id !== emailId);
}
return [...prev, emailId];
});
const email = emails.find(e => e.id === emailId);
if (email) {
setSelectedEmail(email);
// Mark as read
const updatedEmails = emails.map(e =>
e.id === emailId ? { ...e, read: true } : e
);
setEmails(updatedEmails);
}
};
const handleEmailCheckbox = (e: React.ChangeEvent<HTMLInputElement>, emailId: number) => {
@ -576,25 +595,26 @@ export default function MailPage() {
};
const handleReply = async (type: 'reply' | 'replyAll' | 'forward') => {
const selectedEmailData = selectedEmail;
const selectedEmailData = getSelectedEmail();
if (!selectedEmailData) return;
setShowCompose(true);
const subject = `${type === 'forward' ? 'Fwd: ' : 'Re: '}${selectedEmailData.subject}`;
let to = '';
let content = '';
const decodedBody = decodeMimeContent(selectedEmailData.body);
switch (type) {
case 'reply':
to = selectedEmailData.from;
content = `\n\nOn ${new Date(selectedEmailData.date).toLocaleString()}, ${selectedEmailData.fromName} wrote:\n> ${selectedEmailData.body.split('\n').join('\n> ')}`;
content = `\n\nOn ${new Date(selectedEmailData.date).toLocaleString()}, ${selectedEmailData.fromName} wrote:\n> ${decodedBody.split('\n').join('\n> ')}`;
break;
case 'replyAll':
to = selectedEmailData.from;
content = `\n\nOn ${new Date(selectedEmailData.date).toLocaleString()}, ${selectedEmailData.fromName} wrote:\n> ${selectedEmailData.body.split('\n').join('\n> ')}`;
content = `\n\nOn ${new Date(selectedEmailData.date).toLocaleString()}, ${selectedEmailData.fromName} wrote:\n> ${decodedBody.split('\n').join('\n> ')}`;
break;
case 'forward':
content = `\n\n---------- Forwarded message ----------\nFrom: ${selectedEmailData.fromName} <${selectedEmailData.from}>\nDate: ${new Date(selectedEmailData.date).toLocaleString()}\nSubject: ${selectedEmailData.subject}\n\n${selectedEmailData.body}`;
content = `\n\n---------- Forwarded message ----------\nFrom: ${selectedEmailData.fromName} <${selectedEmailData.from}>\nDate: ${new Date(selectedEmailData.date).toLocaleString()}\nSubject: ${selectedEmailData.subject}\n\n${decodedBody}`;
break;
}
@ -973,8 +993,22 @@ export default function MailPage() {
</div>
<div className="prose max-w-none">
{selectedEmail.body}
{decodeMimeContent(selectedEmail.body)}
</div>
{selectedEmail && parseFullEmail(selectedEmail.body).attachments.length > 0 && (
<div className="mt-6 border-t border-gray-200 pt-6">
<h3 className="text-sm font-semibold text-gray-900 mb-4">Attachments</h3>
<div className="grid grid-cols-2 gap-4">
{parseFullEmail(selectedEmail.body).attachments.map((attachment, index) => (
<div key={index} className="flex items-center p-3 border rounded-lg">
<Paperclip className="h-5 w-5 text-gray-400 mr-2" />
<span className="text-sm text-gray-600 truncate">{attachment.filename}</span>
</div>
))}
</div>
</div>
)}
</div>
) : (
<div className="flex flex-col items-center justify-center h-full">
@ -989,24 +1023,68 @@ export default function MailPage() {
<AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
<AlertDialogTitle>
{deleteType === 'email' ? 'Delete Email' :
deleteType === 'emails' ? 'Delete Selected Emails' :
'Delete Account'}
</AlertDialogTitle>
<AlertDialogDescription>
{deleteType === 'email' && "This email will be moved to trash."}
{deleteType === 'emails' && `${selectedEmails.length} emails will be moved to trash.`}
{deleteType === 'account' && "This account will be permanently removed. This action cannot be undone."}
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => setShowDeleteConfirm(false)}>Cancel</AlertDialogCancel>
<AlertDialogAction
className={deleteType === 'account' ? 'bg-red-600 hover:bg-red-700' : ''}
onClick={handleDeleteConfirm}
>
{deleteType === 'account' ? 'Delete Account' : 'Move to Trash'}
</AlertDialogAction>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={handleDeleteConfirm}>Delete</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
{/* Compose Modal */}
{showCompose && (
<div className="fixed inset-0 bg-black/50 z-50">
<div className="absolute inset-4 sm:inset-6 md:inset-8 bg-white rounded-lg shadow-xl flex flex-col">
<div className="flex items-center justify-between p-4 border-b">
<h2 className="text-lg font-semibold">New Message</h2>
<Button variant="ghost" size="icon" onClick={() => setShowCompose(false)}>
<X className="h-4 w-4" />
</Button>
</div>
<div className="p-4 flex-1 overflow-auto space-y-4">
<div>
<Label htmlFor="to">To</Label>
<Input
id="to"
value={composeTo}
onChange={(e) => setComposeTo(e.target.value)}
/>
</div>
<div>
<Label htmlFor="subject">Subject</Label>
<Input
id="subject"
value={composeSubject}
onChange={(e) => setComposeSubject(e.target.value)}
/>
</div>
<div className="flex-1">
<Label htmlFor="body">Message</Label>
<Textarea
id="body"
value={composeBody}
onChange={(e) => setComposeBody(e.target.value)}
className="min-h-[200px]"
/>
</div>
</div>
<div className="p-4 border-t flex justify-end gap-2">
<Button variant="outline" onClick={() => setShowCompose(false)}>
Cancel
</Button>
<Button>Send</Button>
</div>
</div>
</div>
)}
</div>
);
}