120 lines
3.7 KiB
TypeScript
120 lines
3.7 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
import { Loader2, Paperclip, FileDown, Download } from 'lucide-react';
|
|
import { sanitizeHtml } from '@/lib/utils/email-formatter';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Email } from '@/hooks/use-courrier';
|
|
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
|
|
|
interface EmailContentProps {
|
|
email: Email;
|
|
}
|
|
|
|
export default function EmailContent({ email }: EmailContentProps) {
|
|
const [content, setContent] = useState<React.ReactNode>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!email) return;
|
|
|
|
const renderContent = async () => {
|
|
setIsLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
if (!email.content || email.content.length === 0) {
|
|
setContent(<div className="text-gray-500">Email content is empty</div>);
|
|
return;
|
|
}
|
|
|
|
// Use the sanitizer from the centralized formatter
|
|
const sanitizedHtml = sanitizeHtml(email.content);
|
|
|
|
setContent(
|
|
<div
|
|
className="email-content prose max-w-none"
|
|
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
|
|
dir="auto"
|
|
/>
|
|
);
|
|
} catch (err) {
|
|
console.error('Error rendering email content:', err);
|
|
setError('Error rendering email content. Please try again.');
|
|
setContent(null);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
renderContent();
|
|
}, [email]);
|
|
|
|
// 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">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-blue-500"></div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<Alert variant="destructive" className="m-4">
|
|
<AlertTitle>Error</AlertTitle>
|
|
<AlertDescription>{error}</AlertDescription>
|
|
</Alert>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ScrollArea className="flex-1">
|
|
<div className="p-6">
|
|
<div className="flex items-center gap-4 mb-6">
|
|
<div className="h-10 w-10 bg-gray-100 rounded-full flex items-center justify-center">
|
|
<span className="text-gray-600 font-medium">
|
|
{email.from?.[0]?.name?.[0] || email.from?.[0]?.address?.[0] || '?'}
|
|
</span>
|
|
</div>
|
|
<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>
|
|
|
|
{content}
|
|
{renderAttachments()}
|
|
</div>
|
|
</ScrollArea>
|
|
);
|
|
}
|