Untitled

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