mirror of
https://github.com/D4M13N-D3V/neroshitron.git
synced 2025-03-14 10:05:04 +00:00
202 lines
7.5 KiB
TypeScript
202 lines
7.5 KiB
TypeScript
"use client";
|
|
import { createClient } from "@/utils/supabase/client";
|
|
import { redirect } from "next/navigation";
|
|
import GalleryThumbnail from "@/components/ui/gallery_thumbnail";
|
|
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
import { User } from "@supabase/supabase-js";
|
|
import Gallery from "@/components/ui/gallery";
|
|
|
|
function PageComponent() {
|
|
|
|
const supabase = createClient();
|
|
|
|
const [showNSFW, setShowNSFW] = useState<boolean>(true);
|
|
const [randomIds, setRandomIds] = useState<string[]>([]); // replace any with your gallery type
|
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
const [galleries, setGalleries] = useState<any[]>([]); // replace any with your gallery type
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [loading, setLoading] = useState<boolean>(true);
|
|
const [selectedGallery, setSelectedGallery] = useState<string | null>(null);
|
|
const [tags, setTags] = useState<any[]>([]);
|
|
const [search, setSearch] = useState<string>('');
|
|
const [galleryColumns, setColumns] = useState<number>(0);
|
|
const [selectedTags, setSelectedTags] = useState<number[]>([]);
|
|
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;
|
|
}
|
|
|
|
const selectGallery = (gallery: string, columns: number) => {
|
|
setRandomIds([generateRandomString(3), generateRandomString(3), generateRandomString(3), generateRandomString(3)]);
|
|
setSelectedGallery(gallery);
|
|
setColumns(columns);
|
|
setIsOpen(true);
|
|
};
|
|
|
|
const closeGallery = () => {
|
|
setSelectedGallery(null);
|
|
setColumns(0);
|
|
setIsOpen(false);
|
|
}
|
|
|
|
const getData = async () => {
|
|
let { data: { user } } = await supabase.auth.getUser();
|
|
const galleriesResponse = await fetch(`/api/galleries?search=` + search + '&nsfw=' + showNSFW, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ tags: selectedTags })
|
|
});
|
|
//console.log(galleriesResponse)
|
|
const galleriesData = await galleriesResponse.json();
|
|
const tagsResponse = await fetch(`/api/galleries/tags`);
|
|
const tagsData = await tagsResponse.json();
|
|
setGalleries(galleriesData);
|
|
setTags(tagsData);
|
|
setUser(user);
|
|
setLoading(false);
|
|
}
|
|
useEffect(() => {
|
|
getData();
|
|
|
|
}, [selectedTags, search, showNSFW]);
|
|
|
|
const handleTagClick = (tag: number) => {
|
|
if (selectedTags.includes(tag)) {
|
|
setSelectedTags(selectedTags.filter((selectedTag) => selectedTag !== tag));
|
|
} else {
|
|
setSelectedTags([...selectedTags, tag]);
|
|
}
|
|
//console.log(selectedTags)
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<div className="fixed w-full h-full overflow-hidden z-0 animate-fade-left animate-fade-left animate-once animate-duration-[2000ms] animate-normal animate-fill-forwards">
|
|
<img
|
|
src="gallery_girl.png"
|
|
className="float-right object-cover h-screen w-6/6 md:w-5/6 lg:w-3/6 opacity-50 overflow-hidden"
|
|
alt="Background"
|
|
/>
|
|
</div>
|
|
|
|
|
|
{/*
|
|
THIS IS THE SEARCH BAR AND TAGS SECTION
|
|
THIS IS THE SEARCH BAR AND TAGS SECTION
|
|
THIS IS THE SEARCH BAR AND TAGS SECTION
|
|
THIS IS THE SEARCH BAR AND TAGS SECTION
|
|
THIS IS THE SEARCH BAR AND TAGS SECTION
|
|
THIS IS THE SEARCH BAR AND TAGS SECTION
|
|
*/}
|
|
<section className="flex items-center w-full p-8 pt-20 opacity-90 animate-jump-in animate-once animate-duration-500">
|
|
{(tags.length > 0) ? (
|
|
<div className="container mx-auto py-8">
|
|
<div className="relative w-full mx-auto">
|
|
<input
|
|
className="w-full text-neroshi-blue-950 h-16 px-3 rounded mb-8 focus:outline-none focus:shadow-outline text-xl px-8 shadow-lg"
|
|
type="search"
|
|
placeholder="Search by title..."
|
|
onChange={(e) => setSearch(e.target.value)}
|
|
style={{
|
|
animation: 'expandFromLeft 2s ease-out forwards',
|
|
paddingRight: '2rem', // make room for the checkbox
|
|
}}
|
|
/>
|
|
<label htmlFor="toggleNSFW" className="absolute right-0 top-0 h-full mr-2 flex items-center text-neroshi-blue-950 animate-fade animate-once animate-duration-500 animate-delay-[2000ms] animate-ease-out">
|
|
Censor NSFW
|
|
<input
|
|
id="toggleNSFW"
|
|
type="checkbox"
|
|
checked={showNSFW}
|
|
onChange={() => setShowNSFW(!showNSFW)}
|
|
className="form-checkbox h-5 w-5 text-neroshi-blue-950 ml-2 "
|
|
/>
|
|
</label>
|
|
</div>
|
|
{(tags.length > 0) ? (
|
|
<nav className="grid grid-cols-3 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10 gap-4 justify-items-center">
|
|
{tags.map((tag, index) => (
|
|
<a
|
|
key={index}
|
|
className={`w-full rounded-lg no-underline text-white py-3 px-4 font-medium text-center animate-jump-in animate-once animate-duration-500 animate-ease-out ${selectedTags.includes(tag.name) ? 'bg-neroshi-blue-950 hover:bg-neroshi-blue-900' : 'bg-neroshi-blue-800 hover:bg-neroshi-blue-700'
|
|
}`}
|
|
href="#"
|
|
onClick={() => handleTagClick(tag.name)}
|
|
>
|
|
{tag.name}
|
|
</a>
|
|
))}
|
|
</nav>
|
|
) : (
|
|
<div className="flex justify-center">
|
|
<p className="text-white">Loading Tags...</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div className="animate-pulse bg-neroshi-blue-950 rounded-3xl w-full p-8 mt-10 h-48" ></div>
|
|
)}
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
{/*
|
|
These are the thumbnails for the gallery below the search bar
|
|
*/}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-60 gap-x-5 h-full mb-96 animate-in">
|
|
{galleries && galleries.map((gallery, index) => (
|
|
<div className="mx-auto">
|
|
<GalleryThumbnail
|
|
key={gallery.name + " " + showNSFW}
|
|
id={gallery.name}
|
|
title={gallery.name}
|
|
tags={gallery.tags}
|
|
columns={gallery.columns}
|
|
showNsfw={showNSFW}
|
|
subscription={gallery.tier as string}
|
|
onSelect={selectGallery}
|
|
nsfw={gallery.nsfw}
|
|
></GalleryThumbnail>
|
|
</div>
|
|
))}
|
|
</div>
|
|
{isOpen ? (
|
|
<>
|
|
{/*
|
|
This is the modal for holding the gallery
|
|
*/}
|
|
<div
|
|
className={`fixed inset-0 transition-opacity z-30 ${isOpen ? 'animate-in' : 'fade-out'
|
|
}`}
|
|
aria-hidden="true"
|
|
>
|
|
<div
|
|
className="absolute inset-0 bg-neroshi-blue-900 opacity-70 z-30"
|
|
onClick={() => setIsOpen(false)}
|
|
></div>
|
|
<div className="absolute inset-0 overflow-y-auto overflow-x-hidden no-scrollbar pt-2 w-full p-20 z-30">
|
|
<Gallery
|
|
id={selectedGallery as string}
|
|
columns={galleryColumns}
|
|
closeMenu={() => closeGallery()}
|
|
></Gallery>
|
|
</div>
|
|
</div>
|
|
</>
|
|
) : null}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default PageComponent; |