NeahNew/components/email/EmailContent.tsx
2025-05-03 14:17:46 +02:00

135 lines
3.9 KiB
TypeScript

'use client';
import React, { useState } from 'react';
import { Loader2, Paperclip, Download } from 'lucide-react';
import { sanitizeHtml } from '@/lib/utils/dom-purify-config';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
interface EmailAddress {
name: string;
address: string;
}
interface Email {
id: string;
subject: string;
from: EmailAddress[];
to: EmailAddress[];
cc?: EmailAddress[];
bcc?: EmailAddress[];
date: Date | string;
content?: string;
html?: string;
text?: string;
hasAttachments?: boolean;
attachments?: Array<{
filename: string;
contentType: string;
size: number;
path?: string;
content?: string;
}>;
}
interface EmailContentProps {
email: Email;
}
export default function EmailContent({ email }: EmailContentProps) {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// Render attachments if they exist
const renderAttachments = () => {
if (!email?.attachments || email.attachments.length === 0) {
return null;
}
return (
<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">
{email.attachments.map((attachment, index) => (
<div key={index} className="flex items-center space-x-2 p-2 border rounded hover:bg-gray-50">
<Paperclip className="h-4 w-4 text-gray-400" />
<span className="text-sm text-gray-600 truncate flex-1">
{attachment.filename}
</span>
<Download className="h-4 w-4 text-gray-400 hover:text-gray-600 cursor-pointer" />
</div>
))}
</div>
</div>
);
};
if (isLoading) {
return (
<div className="flex justify-center items-center h-full p-8">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
);
}
if (error) {
return (
<Alert variant="destructive" className="m-4">
<AlertTitle>Error</AlertTitle>
<AlertDescription>{error}</AlertDescription>
</Alert>
);
}
// Format the date for display
const formatDate = (dateObj: Date) => {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
const date = new Date(dateObj);
const formattedTime = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
if (date >= today) {
return formattedTime;
} else if (date >= yesterday) {
return `Yesterday, ${formattedTime}`;
} else {
return date.toLocaleDateString([], { month: 'short', day: 'numeric' });
}
};
return (
<div className="email-content-display p-6">
<div className="flex items-center gap-4 mb-6">
<Avatar className="h-10 w-10 bg-gray-100">
<AvatarFallback className="text-gray-600 font-medium">
{email.from?.[0]?.name?.[0] || email.from?.[0]?.address?.[0] || '?'}
</AvatarFallback>
</Avatar>
<div>
<p className="font-medium text-gray-900">
{email.from?.[0]?.name || email.from?.[0]?.address || 'Unknown'}
</p>
<p className="text-sm text-gray-500">
to {email.to?.[0]?.address || 'you'}
</p>
</div>
<div className="ml-auto text-sm text-gray-500">
{formatDate(new Date(email.date))}
</div>
</div>
{email.content ? (
<div className="email-content-display">
<div dangerouslySetInnerHTML={{ __html: sanitizeHtml(email.content) }} />
</div>
) : (
<p className="text-gray-500">No content available</p>
)}
{renderAttachments()}
</div>
);
}