Untitled
unknown
plain_text
8 months ago
5.4 kB
3
Indexable
"use client"
import { useState } from "react"
import { Download, Expand } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { PhotoComments } from "@/components/photo-comments"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
interface GalleryProps {
images: {
src: string
alt: string
width: number
height: number
}[]
}
export function Gallery({ images: unsortedImages }: GalleryProps) {
const [selectedImage, setSelectedImage] = useState<number | null>(null)
const [isDownloading, setIsDownloading] = useState(false)
// Sort images by filename
const images = [...unsortedImages].sort((a, b) => {
const fileNameA = a.src.split('/').pop() || ''
const fileNameB = b.src.split('/').pop() || ''
return fileNameA.localeCompare(fileNameB)
})
const handleDownload = async (imageSrc: string) => {
try {
setIsDownloading(true)
const response = await fetch(imageSrc)
const blob = await response.blob()
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = imageSrc.split('/').pop() || 'image'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
} finally {
setIsDownloading(false)
}
}
// Create thumbnail URL by adding query parameters
const getThumbnailUrl = (src: string) => {
return `${src}?w=300&q=75`
}
return (
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 auto-rows-auto">
{images.map((image, index) => {
const aspectRatio = image.width / image.height
const isPortrait = aspectRatio < 0.8
const isLandscape = aspectRatio > 1.2
return (
<div
key={index}
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={getThumbnailUrl(image.src)}
alt={image.alt}
className="h-full w-full object-cover"
loading="lazy"
/>
<div
className="absolute inset-0 flex items-center justify-center gap-2 bg-black/60 opacity-0 hover:opacity-100 transition-opacity duration-200"
>
<Dialog>
<DialogTrigger asChild>
<Button
variant="secondary"
size="icon"
className="h-9 w-9"
onClick={() => setSelectedImage(index)}
>
<Expand className="h-4 w-4" />
</Button>
</DialogTrigger>
<DialogContent className="max-w-7xl">
<DialogHeader>
<DialogTitle>Bildvorschau</DialogTitle>
<DialogDescription>Ansehen und herunterladen des Bildes in voller Auflösung</DialogDescription>
</DialogHeader>
<Tabs defaultValue="preview">
<div className="flex items-center justify-between mb-4">
<TabsList>
<TabsTrigger value="preview">Vorschau</TabsTrigger>
<TabsTrigger value="comments">Kommentare</TabsTrigger>
</TabsList>
<Button
onClick={() => handleDownload(image.src)}
disabled={isDownloading}
>
<Download className="mr-2 h-4 w-4" />
Bild herunterladen
</Button>
</div>
<TabsContent value="preview">
<div className="flex items-center justify-center overflow-hidden rounded-lg bg-background">
<img
src={image.src}
alt={image.alt}
className="max-h-[80vh] w-auto"
style={{
maxWidth: '100%',
objectFit: 'contain'
}}
/>
</div>
</TabsContent>
<TabsContent value="comments">
<PhotoComments photoId={`photo-${index}`} />
</TabsContent>
</Tabs>
</DialogContent>
</Dialog>
<Button
variant="secondary"
size="icon"
className="h-9 w-9"
onClick={() => handleDownload(image.src)}
disabled={isDownloading}
>
<Download className="h-4 w-4" />
</Button>
</div>
</div>
)
})}
</div>
)
}Editor is loading...
Leave a Comment