import React from 'react';
import {
ChevronLeft, Reply, ReplyAll, Forward, Star, MoreHorizontal, Eye, Download
} from 'lucide-react';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Email } from '@/hooks/use-courrier';
interface EmailDetailViewProps {
email: Email & {
html?: string;
text?: string;
starred?: boolean; // Add starred property to interface
};
onBack: () => void;
onReply: () => void;
onReplyAll: () => void;
onForward: () => void;
onToggleStar: () => void;
}
export default function EmailDetailView({
email,
onBack,
onReply,
onReplyAll,
onForward,
onToggleStar
}: EmailDetailViewProps) {
// Format date for display
const formatDate = (dateString: string | Date) => {
// Convert to Date object if string
const date = typeof dateString === 'string' ? new Date(dateString) : dateString;
const now = new Date();
if (date.toDateString() === now.toDateString()) {
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
} else {
return date.toLocaleDateString([], { month: 'short', day: 'numeric' });
}
};
// Render email content based on the email body
const renderEmailContent = () => {
try {
console.log('EmailDetailView renderEmailContent', {
hasContent: !!email.content,
contentType: typeof email.content,
hasHtml: !!email.html,
hasText: !!email.text
});
// Determine what content to use and how to handle it
let contentToUse = '';
if (email.content) {
// If content is a string, use it directly
if (typeof email.content === 'string') {
contentToUse = email.content;
}
// If content is an object with html/text properties
else if (typeof email.content === 'object') {
contentToUse = email.content.html || email.content.text || '';
}
}
// Fall back to html or text properties if content is not available
else if (email.html) {
contentToUse = email.html;
}
else if (email.text) {
// Convert plain text to HTML with line breaks
contentToUse = email.text
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/\n/g, '
');
}
// Return content or fallback message
return contentToUse ?
:
No content available
;
} catch (e) {
console.error('Error rendering email:', e);
return Failed to render email content
;
}
};
return (
{/* Email actions header */}
{/* Scrollable content area - enhanced for better scrolling */}
{/* Email header info */}
{(email.from?.[0]?.name || '').charAt(0) || (email.from?.[0]?.address || '').charAt(0) || '?'}
{email.from?.[0]?.name || ''} <{email.from?.[0]?.address || ''}>
to {email.to?.[0]?.address || ''}
{email.cc && email.cc.length > 0 && (
cc {email.cc.map(c => c.address).join(', ')}
)}
{formatDate(email.date)}
{/* Email content with improved scrolling */}
{renderEmailContent()}
{/* Attachments (if any) */}
{email.hasAttachments && email.attachments && email.attachments.length > 0 && (
Attachments
{email.attachments.map((attachment, idx) => {
// Build download URL
const downloadUrl = `/api/courrier/${email.id}/attachment/${idx}?folder=${encodeURIComponent(email.folder || 'INBOX')}${email.accountId ? `&accountId=${encodeURIComponent(email.accountId)}` : ''}`;
const handleDownload = async (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
try {
// Fetch the attachment
const response = await fetch(downloadUrl);
if (!response.ok) {
throw new Error(`Failed to download attachment: ${response.statusText}`);
}
// Get the blob
const blob = await response.blob();
// Create a temporary URL and trigger download
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = attachment.filename || `attachment-${idx}`;
document.body.appendChild(a);
a.click();
// Cleanup
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
} catch (error) {
console.error('Error downloading attachment:', error);
alert(`Failed to download attachment: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
};
const handlePreview = async (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
try {
// Fetch the attachment
const response = await fetch(downloadUrl);
if (!response.ok) {
throw new Error(`Failed to preview attachment: ${response.statusText}`);
}
// Get the blob
const blob = await response.blob();
// Check if it's an image or PDF that can be previewed
const contentType = attachment.contentType || response.headers.get('content-type') || '';
const isImage = contentType.startsWith('image/');
const isPDF = contentType === 'application/pdf';
const isText = contentType.startsWith('text/');
if (isImage || isPDF || isText) {
// Create a temporary URL and open in new tab
const url = window.URL.createObjectURL(blob);
window.open(url, '_blank');
// Cleanup after a delay (browser will keep it open)
setTimeout(() => window.URL.revokeObjectURL(url), 1000);
} else {
// For other file types, trigger download
handleDownload(e);
}
} catch (error) {
console.error('Error previewing attachment:', error);
alert(`Failed to preview attachment: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
};
// Determine if file can be previewed
const contentType = attachment.contentType || '';
const isImage = contentType.startsWith('image/');
const isPDF = contentType === 'application/pdf';
const isText = contentType.startsWith('text/');
const canPreview = isImage || isPDF || isText;
return (
{attachment.filename}
{(attachment.size / 1024).toFixed(1)} KB
{canPreview && (
)}
);
})}
)}
{/* Add CSS for better email content display */}
);
}