114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
import { Loader2, Paperclip, FileDown } 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';
|
|
|
|
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 prose-sm max-w-none dark:prose-invert"
|
|
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="border-t mt-4 pt-4">
|
|
<h3 className="text-sm font-medium mb-2 flex items-center gap-1">
|
|
<Paperclip className="h-4 w-4" />
|
|
Attachments ({email.attachments.length})
|
|
</h3>
|
|
<div className="flex flex-wrap gap-2">
|
|
{email.attachments.map((attachment, index) => (
|
|
<Button
|
|
key={index}
|
|
variant="outline"
|
|
size="sm"
|
|
className="flex items-center gap-1 text-xs"
|
|
asChild
|
|
>
|
|
<a
|
|
href={`/api/courrier/${email.id}/attachment/${encodeURIComponent(attachment.filename)}`}
|
|
download={attachment.filename}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>
|
|
<FileDown className="h-3 w-3 mr-1" />
|
|
{attachment.filename} ({(attachment.size / 1024).toFixed(0)}KB)
|
|
</a>
|
|
</Button>
|
|
))}
|
|
</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>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="p-4">
|
|
{content}
|
|
{renderAttachments()}
|
|
</div>
|
|
);
|
|
}
|