mail page ui correction maj 3
This commit is contained in:
parent
019abfab96
commit
508157549b
@ -390,6 +390,20 @@ function decodeMimeContent(content: string): string {
|
|||||||
return cleanHtml(content);
|
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() {
|
export default function MailPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@ -425,6 +439,7 @@ export default function MailPage() {
|
|||||||
const [deleteType, setDeleteType] = useState<'email' | 'emails' | 'account'>('email');
|
const [deleteType, setDeleteType] = useState<'email' | 'emails' | 'account'>('email');
|
||||||
const [itemToDelete, setItemToDelete] = useState<number | null>(null);
|
const [itemToDelete, setItemToDelete] = useState<number | null>(null);
|
||||||
const [showCc, setShowCc] = useState(false);
|
const [showCc, setShowCc] = useState(false);
|
||||||
|
const [contentLoading, setContentLoading] = useState(false);
|
||||||
|
|
||||||
// Check for stored credentials
|
// Check for stored credentials
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -489,7 +504,8 @@ export default function MailPage() {
|
|||||||
date: new Date(email.date),
|
date: new Date(email.date),
|
||||||
read: email.read || false,
|
read: email.read || false,
|
||||||
starred: email.starred || false,
|
starred: email.starred || false,
|
||||||
category: email.category || 'inbox'
|
category: email.category || 'inbox',
|
||||||
|
body: decodeMimeContent(email.body)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setEmails(processedEmails);
|
setEmails(processedEmails);
|
||||||
@ -539,12 +555,15 @@ export default function MailPage() {
|
|||||||
|
|
||||||
// Add email action handlers
|
// Add email action handlers
|
||||||
const handleEmailSelect = (emailId: number) => {
|
const handleEmailSelect = (emailId: number) => {
|
||||||
setSelectedEmails(prev => {
|
const email = emails.find(e => e.id === emailId);
|
||||||
if (prev.includes(emailId)) {
|
if (email) {
|
||||||
return prev.filter(id => id !== emailId);
|
setSelectedEmail(email);
|
||||||
}
|
// Mark as read
|
||||||
return [...prev, emailId];
|
const updatedEmails = emails.map(e =>
|
||||||
});
|
e.id === emailId ? { ...e, read: true } : e
|
||||||
|
);
|
||||||
|
setEmails(updatedEmails);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEmailCheckbox = (e: React.ChangeEvent<HTMLInputElement>, emailId: number) => {
|
const handleEmailCheckbox = (e: React.ChangeEvent<HTMLInputElement>, emailId: number) => {
|
||||||
@ -576,25 +595,26 @@ export default function MailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleReply = async (type: 'reply' | 'replyAll' | 'forward') => {
|
const handleReply = async (type: 'reply' | 'replyAll' | 'forward') => {
|
||||||
const selectedEmailData = selectedEmail;
|
const selectedEmailData = getSelectedEmail();
|
||||||
if (!selectedEmailData) return;
|
if (!selectedEmailData) return;
|
||||||
|
|
||||||
setShowCompose(true);
|
setShowCompose(true);
|
||||||
const subject = `${type === 'forward' ? 'Fwd: ' : 'Re: '}${selectedEmailData.subject}`;
|
const subject = `${type === 'forward' ? 'Fwd: ' : 'Re: '}${selectedEmailData.subject}`;
|
||||||
let to = '';
|
let to = '';
|
||||||
let content = '';
|
let content = '';
|
||||||
|
const decodedBody = decodeMimeContent(selectedEmailData.body);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'reply':
|
case 'reply':
|
||||||
to = selectedEmailData.from;
|
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;
|
break;
|
||||||
case 'replyAll':
|
case 'replyAll':
|
||||||
to = selectedEmailData.from;
|
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;
|
break;
|
||||||
case 'forward':
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,8 +993,22 @@ export default function MailPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="prose max-w-none">
|
<div className="prose max-w-none">
|
||||||
{selectedEmail.body}
|
{decodeMimeContent(selectedEmail.body)}
|
||||||
</div>
|
</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>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col items-center justify-center h-full">
|
<div className="flex flex-col items-center justify-center h-full">
|
||||||
@ -989,24 +1023,68 @@ export default function MailPage() {
|
|||||||
<AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
|
<AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader>
|
<AlertDialogHeader>
|
||||||
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
|
<AlertDialogTitle>
|
||||||
|
{deleteType === 'email' ? 'Delete Email' :
|
||||||
|
deleteType === 'emails' ? 'Delete Selected Emails' :
|
||||||
|
'Delete Account'}
|
||||||
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
{deleteType === 'email' && "This email will be moved to trash."}
|
This action cannot be undone.
|
||||||
{deleteType === 'emails' && `${selectedEmails.length} emails will be moved to trash.`}
|
|
||||||
{deleteType === 'account' && "This account will be permanently removed. This action cannot be undone."}
|
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel onClick={() => setShowDeleteConfirm(false)}>Cancel</AlertDialogCancel>
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction onClick={handleDeleteConfirm}>Delete</AlertDialogAction>
|
||||||
className={deleteType === 'account' ? 'bg-red-600 hover:bg-red-700' : ''}
|
|
||||||
onClick={handleDeleteConfirm}
|
|
||||||
>
|
|
||||||
{deleteType === 'account' ? 'Delete Account' : 'Move to Trash'}
|
|
||||||
</AlertDialogAction>
|
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user