Remove unnecessary files
This commit is contained in:
@ -1,41 +0,0 @@
|
|||||||
import { Image } from "@/generated/prisma";
|
|
||||||
import clsx from "clsx";
|
|
||||||
import NextImage from "next/image";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
export default function ImageList({ images, gallerySlug, albumSlug }: { images: Image[], gallerySlug: string, albumSlug: string }) {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
<h1 className="text-2xl font-bold mb-4">Images</h1>
|
|
||||||
<div className="grid gap-6 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4">
|
|
||||||
{images ? images.map((img) => (
|
|
||||||
<Link href={`/galleries/${gallerySlug}/${albumSlug}/${img.id}`} key={img.id}>
|
|
||||||
<div className="group rounded-lg border overflow-hidden hover:shadow-lg transition-shadow bg-background">
|
|
||||||
<div className="relative aspect-[4/3] w-full bg-muted items-center justify-center">
|
|
||||||
{img.fileKey ? (
|
|
||||||
<NextImage
|
|
||||||
src={`/api/image/thumbnails/${img.fileKey}.webp`}
|
|
||||||
alt={img.imageName}
|
|
||||||
fill
|
|
||||||
className={clsx(
|
|
||||||
" object-cover",
|
|
||||||
img.nsfw && "blur-md scale-105"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center justify-center h-full text-muted-foreground text-sm">
|
|
||||||
No cover image
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="p-4">
|
|
||||||
<h2 className="text-lg font-semibold truncate text-center">{img.imageName}</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
)) : "There are no images here!"}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
// import ImageCard from "@/components/image/ImageCard"; // You likely have this already
|
|
||||||
// import type { Album, Gallery, Image, ImageVariant } from "@prisma/client";
|
|
||||||
import { Album, Gallery, Image, ImageVariant } from "@/generated/prisma";
|
|
||||||
import { useState } from "react";
|
|
||||||
import ImageCard from "./ImageCard";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
images: (Image & {
|
|
||||||
album: Album & { gallery: Gallery | null } | null;
|
|
||||||
variants: ImageVariant[];
|
|
||||||
})[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function ArtistImageGrid({ images }: Props) {
|
|
||||||
const [showNSFW, setShowNSFW] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<button
|
|
||||||
onClick={() => setShowNSFW(!showNSFW)}
|
|
||||||
className="text-sm underline text-muted-foreground"
|
|
||||||
>
|
|
||||||
{showNSFW ? "Hide NSFW" : "Show NSFW"} content
|
|
||||||
</button>
|
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
|
|
||||||
{images.map((img) => (
|
|
||||||
<ImageCard key={img.id} image={img} showNSFW={showNSFW} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
import { Album, Gallery, Image, ImageVariant } from "@/generated/prisma";
|
|
||||||
import NextImage from "next/image";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
image: Image & {
|
|
||||||
variants: ImageVariant[];
|
|
||||||
album: Album & { gallery: Gallery | null } | null;
|
|
||||||
};
|
|
||||||
showNSFW?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function ImageCard({ image, showNSFW = false }: Props) {
|
|
||||||
const variant = image.variants.find(v => v.type === "thumbnail") || image.variants[0];
|
|
||||||
if (!variant) return null;
|
|
||||||
|
|
||||||
const href = image.album?.gallery && image.album
|
|
||||||
? `/galleries/${image.album.gallery.slug}/${image.album.slug}/${image.id}`
|
|
||||||
: `/image/${image.id}`;
|
|
||||||
|
|
||||||
const shouldBlur = image.nsfw && !showNSFW;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link href={href} className="group relative overflow-hidden rounded-lg border bg-background shadow transition hover:shadow-lg">
|
|
||||||
<div className="aspect-[4/5] w-full relative">
|
|
||||||
<NextImage
|
|
||||||
src={`/api/image/${variant.s3Key}`}
|
|
||||||
alt={image.altText || image.imageName}
|
|
||||||
width={variant.width}
|
|
||||||
height={variant.height}
|
|
||||||
className={`object-cover h-full transition duration-200 ease-in-out ${shouldBlur ? "blur-md scale-105" : ""
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
{image.nsfw && (
|
|
||||||
<div className="absolute top-1 left-1 bg-black/60 text-white text-xs px-2 py-0.5 rounded z-10">
|
|
||||||
NSFW
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="absolute bottom-0 left-0 w-full bg-black/50 text-white text-sm px-2 py-1 line-clamp-1 truncate">
|
|
||||||
{image.imageName}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
import { Album, Image } from "@/generated/prisma";
|
|
||||||
import NextImage from "next/image";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
album: Album & {
|
|
||||||
coverImage: Image | null;
|
|
||||||
};
|
|
||||||
gallerySlug: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function AlbumCard({ album, gallerySlug }: Props) {
|
|
||||||
const href = `/galleries/${gallerySlug}/${album.slug}`;
|
|
||||||
const cover = album.coverImage;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
href={href}
|
|
||||||
className="group relative overflow-hidden rounded-lg border bg-background shadow transition hover:shadow-lg"
|
|
||||||
>
|
|
||||||
<div className="aspect-[4/3] w-full relative">
|
|
||||||
{cover ? (
|
|
||||||
<NextImage
|
|
||||||
src={`/api/image/thumbnails/${cover.fileKey}.webp`}
|
|
||||||
alt={cover.imageName}
|
|
||||||
fill
|
|
||||||
className="object-cover"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center justify-center h-full w-full bg-muted text-muted-foreground text-sm">
|
|
||||||
No cover image
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Overlay: Album label */}
|
|
||||||
<div className="absolute top-1 left-1 bg-black/60 text-white text-xs px-2 py-0.5 rounded z-10">
|
|
||||||
Album
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Bottom: Album name */}
|
|
||||||
<div className="absolute bottom-0 left-0 w-full bg-black/50 text-white text-sm px-2 py-1 line-clamp-1 truncate">
|
|
||||||
{album.name}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
import { Album, Gallery, Image } from "@/generated/prisma";
|
|
||||||
import NextImage from "next/image";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
type ImagesWithItems = (Pick<Image, "id" | "fileKey" | "imageName" | "altText" | "nsfw"> & {
|
|
||||||
album?: (Pick<Album, "slug"> & {
|
|
||||||
gallery?: Pick<Gallery, "slug"> | null
|
|
||||||
}) | null
|
|
||||||
})[]
|
|
||||||
|
|
||||||
export default function CategoryImageList({ images }: { images: ImagesWithItems }) {
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
<h1 className="text-2xl font-bold mb-4">Images</h1>
|
|
||||||
<div className="grid gap-6 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4">
|
|
||||||
{images ? images.map((img) => {
|
|
||||||
const gallerySlug = img.album?.gallery?.slug;
|
|
||||||
const albumSlug = img.album?.slug;
|
|
||||||
if (!gallerySlug || !albumSlug || !img.id) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link href={`/${gallerySlug}/${albumSlug}/${img.id}`} key={img.id}>
|
|
||||||
<div className="group rounded-lg border overflow-hidden hover:shadow-lg transition-shadow bg-background">
|
|
||||||
<div className="relative aspect-[4/3] w-full bg-muted items-center justify-center">
|
|
||||||
{img.fileKey ? (
|
|
||||||
<NextImage
|
|
||||||
src={`/api/image/thumbnails/${img.fileKey}.webp`}
|
|
||||||
alt={img.altText || ""}
|
|
||||||
fill
|
|
||||||
className="object-cover"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center justify-center h-full text-muted-foreground text-sm">
|
|
||||||
No cover image
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="p-4">
|
|
||||||
<h2 className="text-lg font-semibold truncate text-center">{img.imageName}</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}) : "There are no images here!"}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
import { Album, Image } from "@/generated/prisma";
|
|
||||||
import NextImage from "next/image";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
type AlbumsWithItems = Album & {
|
|
||||||
coverImage: Image | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function AlbumList({ albums, gallerySlug }: { albums: AlbumsWithItems[], gallerySlug: string }) {
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
<h1 className="text-2xl font-bold mb-4">Albums</h1>
|
|
||||||
<div className="grid gap-6 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4">
|
|
||||||
{albums ? albums.map((album) => (
|
|
||||||
<Link href={`/galleries/${gallerySlug}/${album.slug}`} key={album.id}>
|
|
||||||
<div className="group rounded-lg border overflow-hidden hover:shadow-lg transition-shadow bg-background">
|
|
||||||
<div className="relative aspect-[4/3] w-full bg-muted items-center justify-center">
|
|
||||||
{album.coverImage?.fileKey ? (
|
|
||||||
<NextImage
|
|
||||||
src={`/api/image/thumbnails/${album.coverImage.fileKey}.webp`}
|
|
||||||
alt={album.coverImage.imageName}
|
|
||||||
fill
|
|
||||||
className="object-cover"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center justify-center h-full text-muted-foreground text-sm">
|
|
||||||
No cover image
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="p-4">
|
|
||||||
<h2 className="text-lg font-semibold truncate text-center">{album.name}</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
)) : "There are no albums here!"}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { Color, ImageColor, ImageVariant } from "@/generated/prisma"
|
|
||||||
import clsx from "clsx"
|
|
||||||
import { useTheme } from "next-themes"
|
|
||||||
import NextImage from "next/image"
|
|
||||||
import { useEffect, useState } from "react"
|
|
||||||
|
|
||||||
type Colors = ImageColor & {
|
|
||||||
color: Color
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
alt: string,
|
|
||||||
variant: ImageVariant,
|
|
||||||
colors: Colors[],
|
|
||||||
src: string,
|
|
||||||
revealed?: boolean,
|
|
||||||
className?: string,
|
|
||||||
animate?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function GlowingImageBorder({
|
|
||||||
alt,
|
|
||||||
variant,
|
|
||||||
colors,
|
|
||||||
src,
|
|
||||||
className,
|
|
||||||
revealed = true,
|
|
||||||
animate = true,
|
|
||||||
}: Props) {
|
|
||||||
const { resolvedTheme } = useTheme()
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getColor = (type: string) =>
|
|
||||||
colors.find((c) => c.type === type)?.color.hex
|
|
||||||
|
|
||||||
const vibrantLight = getColor("Vibrant") || "#ff5ec4"
|
|
||||||
const mutedLight = getColor("Muted") || "#5ecaff"
|
|
||||||
|
|
||||||
const darkVibrant = getColor("DarkVibrant") || "#fc03a1"
|
|
||||||
const darkMuted = getColor("DarkMuted") || "#035efc"
|
|
||||||
|
|
||||||
const vibrant = resolvedTheme === "dark" ? darkVibrant : vibrantLight
|
|
||||||
const muted = resolvedTheme === "dark" ? darkMuted : mutedLight
|
|
||||||
|
|
||||||
if (!mounted) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
"relative inline-block rounded-xl overflow-hidden p-[12px]",
|
|
||||||
animate ? "glow-border" : "static-glow-border",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--vibrant": vibrant,
|
|
||||||
"--muted": muted,
|
|
||||||
} as React.CSSProperties
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className="relative z-10 rounded-xl overflow-hidden group">
|
|
||||||
<NextImage
|
|
||||||
src={src}
|
|
||||||
alt={alt || "Image"}
|
|
||||||
width={variant.width}
|
|
||||||
height={variant.height}
|
|
||||||
className={clsx(
|
|
||||||
"rounded-xl transition duration-300",
|
|
||||||
!revealed && "blur-md scale-105"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { Color, ImageColor, ImageVariant } from "@/generated/prisma";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { Label } from "../ui/label";
|
|
||||||
import { Switch } from "../ui/switch";
|
|
||||||
import GlowingImageBorder from "./GlowingImageBorder";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
variant: ImageVariant;
|
|
||||||
colors: (ImageColor & { color: Color })[];
|
|
||||||
alt: string;
|
|
||||||
src: string;
|
|
||||||
nsfw: boolean;
|
|
||||||
imageId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function GlowingImageWithToggle({ variant, colors, alt, src, nsfw, imageId }: Props) {
|
|
||||||
const [animate, setAnimate] = useState(true);
|
|
||||||
const [revealed, setRevealed] = useState(!nsfw)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative w-full max-w-fit">
|
|
||||||
|
|
||||||
<Link href={`/raw/${imageId}`} passHref>
|
|
||||||
<GlowingImageBorder
|
|
||||||
alt={alt}
|
|
||||||
variant={variant}
|
|
||||||
colors={colors}
|
|
||||||
src={src}
|
|
||||||
animate={animate}
|
|
||||||
revealed={revealed}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<div className="flex flex-col items-center gap-4 pt-8">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Switch id="animate" checked={animate} onCheckedChange={setAnimate} />
|
|
||||||
<Label htmlFor="animate">Animate glow</Label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
nsfw && (
|
|
||||||
<div className="flex flex-col items-center gap-4 pt-8">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Switch id="animate" checked={revealed} onCheckedChange={setRevealed} />
|
|
||||||
<Label htmlFor="animate">Reveal NSFW</Label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div >
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
import { Image as ImageType } from "@/generated/prisma";
|
|
||||||
import Link from "next/link";
|
|
||||||
// import { SocialIcon } from "react-social-icons";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
image: ImageType & {
|
|
||||||
artist?: {
|
|
||||||
id: string;
|
|
||||||
slug: string;
|
|
||||||
displayName: string;
|
|
||||||
socials?: { type: string; handle: string; link: string }[];
|
|
||||||
};
|
|
||||||
categories?: { id: string; name: string }[];
|
|
||||||
tags?: { id: string; name: string }[];
|
|
||||||
album?: { id: string; name: string; slug: string };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function ImageInfoPanel({ image }: Props) {
|
|
||||||
return (
|
|
||||||
<div className="w-full max-w-2xl mt-8 border border-border rounded-lg p-6 shadow-sm bg-background">
|
|
||||||
{/* Creator */}
|
|
||||||
{image.artist && (
|
|
||||||
<div className="mb-4">
|
|
||||||
<h2 className="text-lg font-semibold mb-1">Creator</h2>
|
|
||||||
<Link
|
|
||||||
href={`/artists/${image.artist.slug}`}
|
|
||||||
className="text-primary hover:underline font-medium"
|
|
||||||
>
|
|
||||||
{image.artist.displayName}
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{image.artist.socials?.length > 0 && (
|
|
||||||
<div className="flex gap-2 mt-2">
|
|
||||||
{image.artist.socials.map((social, i) => (
|
|
||||||
<SocialIcon
|
|
||||||
key={i}
|
|
||||||
url={social.link}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
style={{ height: 28, width: 28 }}
|
|
||||||
title={social.type}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Album */}
|
|
||||||
{image.album && (
|
|
||||||
<div className="mb-4">
|
|
||||||
<h2 className="text-lg font-semibold mb-1">Album</h2>
|
|
||||||
<Link
|
|
||||||
href={`/galleries/${image.album.slug}`}
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
{image.album.name}
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Categories */}
|
|
||||||
{image.categories?.length > 0 && (
|
|
||||||
<div className="mb-4">
|
|
||||||
<h2 className="text-lg font-semibold mb-1">Categories</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{image.categories.map((cat) => (
|
|
||||||
<Link
|
|
||||||
key={cat.id}
|
|
||||||
href={`/categories/${cat.id}`}
|
|
||||||
className="bg-muted text-sm px-2 py-1 rounded hover:bg-accent"
|
|
||||||
>
|
|
||||||
{cat.name}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Tags */}
|
|
||||||
{image.tags?.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<h2 className="text-lg font-semibold mb-1">Tags</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{image.tags.map((tag) => (
|
|
||||||
<Link
|
|
||||||
key={tag.id}
|
|
||||||
href={`/tags/${tag.id}`}
|
|
||||||
className="bg-muted text-sm px-2 py-1 rounded hover:bg-accent"
|
|
||||||
>
|
|
||||||
#{tag.name}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
Reference in New Issue
Block a user