attachments courrier
This commit is contained in:
parent
807200d9e4
commit
f769d15bb1
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
ChevronLeft, Reply, ReplyAll, Forward, Star, MoreHorizontal
|
ChevronLeft, Reply, ReplyAll, Forward, Star, MoreHorizontal, Eye, Download
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
||||||
@ -191,6 +191,7 @@ export default function EmailDetailView({
|
|||||||
|
|
||||||
const handleDownload = async (e: React.MouseEvent) => {
|
const handleDownload = async (e: React.MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
try {
|
try {
|
||||||
// Fetch the attachment
|
// Fetch the attachment
|
||||||
const response = await fetch(downloadUrl);
|
const response = await fetch(downloadUrl);
|
||||||
@ -219,30 +220,77 @@ export default function EmailDetailView({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className="flex items-center gap-2 p-2 border border-gray-200 rounded-md hover:bg-gray-50 transition-colors cursor-pointer"
|
className="flex items-center gap-2 p-3 border border-gray-200 rounded-md hover:bg-gray-50 transition-colors"
|
||||||
onClick={handleDownload}
|
|
||||||
title={`Click to download ${attachment.filename}`}
|
|
||||||
>
|
>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm font-medium text-gray-700 truncate">{attachment.filename}</p>
|
<p className="text-sm font-medium text-gray-700 truncate">{attachment.filename}</p>
|
||||||
<p className="text-xs text-gray-500">{(attachment.size / 1024).toFixed(1)} KB</p>
|
<p className="text-xs text-gray-500">{(attachment.size / 1024).toFixed(1)} KB</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
{canPreview && (
|
||||||
<button
|
<button
|
||||||
className="ml-2 p-1 text-gray-400 hover:text-blue-600 transition-colors"
|
className="p-1.5 text-gray-400 hover:text-blue-600 transition-colors rounded"
|
||||||
onClick={(e) => {
|
onClick={handlePreview}
|
||||||
e.stopPropagation();
|
title="Preview attachment"
|
||||||
handleDownload(e);
|
>
|
||||||
}}
|
<Eye className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
className="p-1.5 text-gray-400 hover:text-blue-600 transition-colors rounded"
|
||||||
|
onClick={handleDownload}
|
||||||
title="Download attachment"
|
title="Download attachment"
|
||||||
>
|
>
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<Download className="w-4 h-4" />
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Star, Mail, MailOpen } from 'lucide-react';
|
import { Star, Mail, MailOpen, Paperclip } from 'lucide-react';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { Email } from '@/hooks/use-courrier';
|
import { Email } from '@/hooks/use-courrier';
|
||||||
@ -188,9 +188,14 @@ export default function EmailListItem({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 className="text-sm text-gray-900 truncate">
|
<div className="flex items-center gap-2">
|
||||||
|
<h3 className="text-sm text-gray-900 truncate flex-1">
|
||||||
{email.subject || '(No subject)'}
|
{email.subject || '(No subject)'}
|
||||||
</h3>
|
</h3>
|
||||||
|
{email.hasAttachments && (
|
||||||
|
<Paperclip className="h-3.5 w-3.5 text-gray-400 flex-shrink-0" title="Has attachments" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="text-xs text-gray-500 truncate">
|
<div className="text-xs text-gray-500 truncate">
|
||||||
{getPreviewText(email.content)}
|
{getPreviewText(email.content)}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user