forked from op7418/CodePilot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFileAttachmentDisplay.tsx
More file actions
82 lines (70 loc) · 2.3 KB
/
FileAttachmentDisplay.tsx
File metadata and controls
82 lines (70 loc) · 2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
'use client';
import { useState, useCallback } from 'react';
import type { FileAttachment } from '@/types';
import { isImageFile } from '@/types';
import { ImageThumbnail } from './ImageThumbnail';
import { FileCard } from './FileCard';
import { ImageLightbox } from './ImageLightbox';
interface FileAttachmentDisplayProps {
files: FileAttachment[];
}
/**
* Build a display URL for a file attachment.
* - If base64 `data` is available (optimistic / in-memory): use data URI
* - If `filePath` is available (reloaded from DB): use the uploads API
*/
function fileUrl(f: FileAttachment): string {
if (f.data) return `data:${f.type};base64,${f.data}`;
if (f.filePath) return `/api/uploads?path=${encodeURIComponent(f.filePath)}`;
return '';
}
export function FileAttachmentDisplay({ files }: FileAttachmentDisplayProps) {
const [lightboxOpen, setLightboxOpen] = useState(false);
const [lightboxIndex, setLightboxIndex] = useState(0);
const imageFiles = files.filter((f) => isImageFile(f.type) && fileUrl(f));
const otherFiles = files.filter((f) => !isImageFile(f.type) || !fileUrl(f));
const lightboxImages = imageFiles.map((f) => ({
src: fileUrl(f),
alt: f.name,
}));
const handlePreview = useCallback((index: number) => {
setLightboxIndex(index);
setLightboxOpen(true);
}, []);
if (files.length === 0) return null;
const imageGridCols =
imageFiles.length === 1
? 'grid-cols-1 max-w-xs'
: imageFiles.length === 2
? 'grid-cols-2 max-w-sm'
: 'grid-cols-3 max-w-md';
return (
<div className="space-y-2 mb-2">
{imageFiles.length > 0 && (
<div className={`grid gap-2 ${imageGridCols}`}>
{imageFiles.map((file, i) => (
<ImageThumbnail
key={file.id}
src={fileUrl(file)}
alt={file.name}
onClick={() => handlePreview(i)}
/>
))}
</div>
)}
{otherFiles.length > 0 && (
<div className="space-y-1.5">
{otherFiles.map((file) => (
<FileCard key={file.id} name={file.name} size={file.size} />
))}
</div>
)}
<ImageLightbox
images={lightboxImages}
initialIndex={lightboxIndex}
open={lightboxOpen}
onOpenChange={setLightboxOpen}
/>
</div>
);
}