Untitled

 avatar
unknown
plain_text
2 months ago
5.1 kB
1
Indexable
"use client"

import { useState } from "react"
import Image from "next/image"
import { motion } from "framer-motion"
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 }: GalleryProps) {
  const [selectedImage, setSelectedImage] = useState<number | null>(null)

  const handleDownload = async (imageSrc: string) => {
    try {
      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);
    } catch (error) {
      console.error('Download failed:', error);
    }
  };

  return (
    <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
      {images.map((image, index) => (
        <motion.div
          key={index}
          initial={{ opacity: 0, scale: 0.9 }}
          animate={{ opacity: 1, scale: 1 }}
          transition={{ delay: index * 0.1 }}
          className="group relative aspect-square overflow-hidden rounded-lg bg-muted/30"
        >
          <Image
            src={image.src}
            alt={image.alt}
            fill
            className="object-cover transition-transform duration-500 will-change-transform group-hover:scale-105"
            sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
            priority={index < 4}
          />
          <motion.div
            initial={false}
            animate={{ opacity: 0 }}
            whileHover={{ opacity: 1 }}
            transition={{ duration: 0.2 }}
            className="absolute inset-0 flex items-center justify-center gap-2 bg-black/60"
          >
            <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(images[selectedImage ?? index].src)}
                    >
                      <Download className="mr-2 h-4 w-4" />
                      Bild herunterladen
                    </Button>
                  </div>
                  <TabsContent value="preview" className="relative">
                    <div 
                      style={{
                        position: 'relative',
                        width: '100%',
                        height: '70vh',
                        maxHeight: '800px'
                      }}
                    >
                      <img
                        src={images[selectedImage ?? index].src}
                        alt={images[selectedImage ?? index].alt}
                        style={{
                          width: '100%',
                          height: '100%',
                          objectFit: 'contain'
                        }}
                      />
                    </div>
                  </TabsContent>
                  <TabsContent value="comments">
                    <PhotoComments photoId={`photo-${selectedImage ?? index}`} />
                  </TabsContent>
                </Tabs>
              </DialogContent>
            </Dialog>
            <Button 
              variant="secondary" 
              size="icon" 
              className="h-9 w-9"
              onClick={() => handleDownload(image.src)}
            >
              <Download className="h-4 w-4" />
            </Button>
          </motion.div>
        </motion.div>
      ))}
    </div>
  )
}
Editor is loading...
Leave a Comment