Untitled

 avatar
unknown
plain_text
2 months ago
5.4 kB
2
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