Untitled
unknown
plain_text
8 months ago
7.9 kB
7
Indexable
// components/gallery.tsx
export function Gallery({ sections }: GalleryProps) {
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [isDownloading, setIsDownloading] = useState(false);
const [isFullImageLoaded, setIsFullImageLoaded] = useState(false);
const [selectedTab, setSelectedTab] = useState("preview");
const [commentCounts, setCommentCounts] = useState<Record<string, number>>({});
const handleDownload = async (imageSrc: string) => {
try {
setIsDownloading(true);
const fileName = imageSrc.split('/').pop() || 'image';
const response = await fetch(imageSrc);
if (!response.ok) throw new Error('Download failed');
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
} catch (error) {
console.error('Download error:', error);
toast.error('Download fehlgeschlagen');
} finally {
setIsDownloading(false);
}
};
return (
<div className="space-y-12">
{sections.map((section, sectionIndex) => (
<div key={sectionIndex} className="space-y-4">
<div className="space-y-2">
<h2 className="text-2xl font-bold">{section.title}</h2>
{section.description && (
<p className="text-muted-foreground">{section.description}</p>
)}
</div>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{section.images.map((image, imageIndex) => {
const aspectRatio = image.width / image.height;
const isPortrait = aspectRatio < 0.8;
const isLandscape = aspectRatio > 1.2;
const photoId = `${section.title}-${imageIndex}`;
const commentCount = commentCounts[photoId] || 0;
return (
<div
key={imageIndex}
className={`
relative overflow-hidden rounded-lg bg-muted/30 transition-opacity duration-300
${isPortrait ? 'row-span-2' : ''}
`}
style={{
aspectRatio: isPortrait ? '2/3' : isLandscape ? '16/9' : '1/1',
}}
>
<img
src={image.thumbnailSrc}
alt={image.alt}
className="h-full w-full object-cover"
loading="lazy"
/>
<Dialog onOpenChange={(open) => {
setIsDialogOpen(open);
if (open) {
setSelectedTab("preview");
setIsFullImageLoaded(false);
}
}}>
<DialogTrigger asChild>
<div className="absolute inset-0 flex items-center justify-center gap-2 bg-black/60 opacity-0 hover:opacity-100 transition-opacity duration-200 cursor-pointer">
<Button
variant="secondary"
size="icon"
className="h-9 w-9 z-10"
onClick={(e) => {
e.stopPropagation();
handleDownload(image.src);
}}
>
<Download className="h-4 w-4" />
</Button>
</div>
</DialogTrigger>
<DialogContent className="w-[90%] h-[90vh] max-w-7xl p-4 sm:p-6">
<DialogHeader className="mb-4">
<DialogTitle>Bildvorschau</DialogTitle>
<DialogDescription>
Ansehen und herunterladen des Bildes in voller Auflösung
</DialogDescription>
</DialogHeader>
<div className="flex-1 h-[calc(90vh-8rem)]">
<ImageDialog
image={image}
fullSizeImageSrc={image.src}
thumbnailSrc={image.thumbnailSrc}
photoId={photoId}
commentCount={commentCount}
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
isFullImageLoaded={isFullImageLoaded}
setIsFullImageLoaded={setIsFullImageLoaded}
handleDownload={handleDownload}
isDownloading={isDownloading}
onCommentAdded={(photoId) => {
setCommentCounts(prev => ({
...prev,
[photoId]: (prev[photoId] || 0) + 1
}));
}}
/>
</div>
</DialogContent>
</Dialog>
{commentCount > 0 && (
<Dialog onOpenChange={(open) => {
setIsDialogOpen(open);
if (open) setSelectedTab("comments");
}}>
<DialogTrigger asChild>
<div className="absolute bottom-2 right-2 z-10">
<div className="bg-black/70 backdrop-blur-sm rounded-full px-2 py-1 flex items-center gap-1 text-white text-sm cursor-pointer hover:bg-black/80 transition-colors">
<MessageCircle className="h-4 w-4" />
<span>{commentCount}</span>
</div>
</div>
</DialogTrigger>
<DialogContent className="w-[90%] h-[90vh] max-w-7xl p-4 sm:p-6">
<DialogHeader className="mb-4">
<DialogTitle>Bildvorschau</DialogTitle>
<DialogDescription>
Ansehen und herunterladen des Bildes in voller Auflösung
</DialogDescription>
</DialogHeader>
<div className="flex-1 h-[calc(90vh-8rem)]">
<ImageDialog
image={image}
fullSizeImageSrc={image.src}
thumbnailSrc={image.thumbnailSrc}
photoId={photoId}
commentCount={commentCount}
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
isFullImageLoaded={isFullImageLoaded}
setIsFullImageLoaded={setIsFullImageLoaded}
handleDownload={handleDownload}
isDownloading={isDownloading}
onCommentAdded={(photoId) => {
setCommentCounts(prev => ({
...prev,
[photoId]: (prev[photoId] || 0) + 1
}));
}}
/>
</div>
</DialogContent>
</Dialog>
)}
</div>
);
})}
</div>
</div>
))}
</div>
);
}Editor is loading...
Leave a Comment