neroshitron/components/ui/gallery.tsx

164 lines
6.4 KiB
TypeScript
Raw Normal View History

2024-05-26 02:14:59 -04:00
import { use, useState } from 'react';
import { useEffect } from 'react';
import Masonry from 'react-masonry-css';
interface GalleryProps {
id: number;
closeMenu: () => void;
}
const Gallery = ({ id, closeMenu }: GalleryProps) => {
const [isSingle, setIsSingle] = useState<boolean>(false);
const [loaded, setLoaded] = useState({})
const [selectedImage, setSelectedImage] = useState<string | null>(null);
const [images, setImages] = useState<string[]>([]);
const [galleryId, setGalleryId] = useState(id as number);
console.log(id)
const getData = async () => {
const thumbnailResponse = await fetch('/api/galleries/'+String(galleryId)+'/images');
const thumbnailUrl = await thumbnailResponse.json() as string[];
setImages(thumbnailUrl);
}
2024-05-26 03:46:00 -04:00
const generateRandomString = function (length:number) {
let result = '';
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let charactersLength = characters.length;
for ( let i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
2024-05-26 02:14:59 -04:00
const handleDownload = (image: string) => {
const link = document.createElement('a');
link.href = image;
link.download = 'image.jpg'; // or any other filename
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
useEffect(() => {
getData();
if (images.length === 1) {
2024-05-26 03:46:00 -04:00
setIsSingle(true);
2024-05-26 02:14:59 -04:00
setSelectedImage(images[0]);
}
}, [selectedImage]);
const handleClick = (image: string) => {
setSelectedImage(image);
};
2024-05-26 03:46:00 -04:00
const open = () => {
if(selectedImage === null) return;
console.log(selectedImage)
let base64Image = selectedImage.split(';base64,').pop();
if(!base64Image) return;
let blob = new Blob([Uint8Array.from(atob(base64Image), c => c.charCodeAt(0))], {type: 'image/jpeg'}); // adjust the type as needed
let url = URL.createObjectURL(blob);
window.open(url, '_blank');
}
2024-05-26 02:14:59 -04:00
const breakpointColumnsObj = {
default: 3
};
return (
<>
<button
2024-05-26 03:46:00 -04:00
className="fixed bg-purple-800 left-10 bottom-5 animate-ping animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50"
2024-05-26 02:14:59 -04:00
onClick={()=> closeMenu()}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="mr-2 h-4 w-4 transition-transform group-hover:-translate-x-1"
>
<polyline points="15 18 9 12 15 6" />
</svg>{" "}
Back
</button>
<div className='z-10 pt-10' style={{ display: selectedImage ? 'flex' : 'block', alignItems: 'flex-start' }}>
{isSingle ? (
<div className='w-full h-full flex items-center'>
{selectedImage &&
2024-05-26 03:46:00 -04:00
<>
<button
className="fixed bg-neroshi-blue-800 left-40 bottom-5 text-center w-56 animate-ping animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50"
onClick={() => handleDownload(selectedImage)}
>
Download Current Image
</button><button
className="fixed bg-neroshi-blue-800 left-40 bottom-16 w-56 text-center animate-ping animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50"
onClick={() => open()}
>
Open Image in New Tab
</button>
2024-05-26 02:14:59 -04:00
<img
src={selectedImage}
style={{ objectFit: 'contain' }}
className="cursor-pointer animate-in w-full h-auto"
onClick={() => setSelectedImage(null)}
/>
2024-05-26 03:46:00 -04:00
</>
2024-05-26 02:14:59 -04:00
}
</div>
) : (
<>
{selectedImage &&
<>
<img
src={selectedImage}
style={{ objectFit: 'contain' }}
2024-05-26 03:46:00 -04:00
key={generateRandomString(3)}
className="cursor-pointer animate-in w-4/6 pr-20 h-auto animate-ping animate-once animate-duration-1000 animate-ease-out animate-reverse"
2024-05-26 02:14:59 -04:00
onClick={() => setSelectedImage(null)}
/>
<button
2024-05-26 03:46:00 -04:00
className="fixed bg-neroshi-blue-800 left-40 bottom-5 text-center w-56 animate-ping animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50"
2024-05-26 02:14:59 -04:00
onClick={() => handleDownload(selectedImage)}
>
Download Current Image
2024-05-26 03:46:00 -04:00
</button><button
className="fixed bg-neroshi-blue-800 left-40 bottom-16 w-56 text-center animate-ping animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50"
onClick={() => open()}
>
Open Image in New Tab
</button>
2024-05-26 02:14:59 -04:00
</>
}
<Masonry
breakpointCols={selectedImage==null ? 4 : 2}
className="my-masonry-grid"
style={{ width: selectedImage ? '50%' : '100%' }}
>
{images.filter(img => img !== selectedImage).map((image, index) => (
<img
2024-05-26 03:46:00 -04:00
key={generateRandomString(3)}
2024-05-26 02:14:59 -04:00
src={image}
onClick={() => handleClick(image)}
2024-05-26 03:46:00 -04:00
className={`animate-ping animate-once animate-duration-1000 animate-ease-out animate-reverse hover:scale-105 p-2 cursor-pointer my-2 transition-all opacity-100 duration-500 ease-in-out transform`}
2024-05-26 02:14:59 -04:00
/>
))}
</Masonry>
</>
)}
</div>
</>
);
}
export default Gallery;