Refactr a lot of things
This commit is contained in:
93
src/components/cards/CoverCard.tsx
Normal file
93
src/components/cards/CoverCard.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
"use client"
|
||||
|
||||
import { type Color, type Image, type ImageColor } from "@/generated/prisma"
|
||||
import { useGlobalSettings } from "@/hooks/useGlobalSettings"
|
||||
import clsx from "clsx"
|
||||
import { BookOpenIcon, EyeOffIcon, ImagePlusIcon } from "lucide-react"
|
||||
import NextImage from "next/image"
|
||||
import Link from "next/link"
|
||||
import { GlowingBorderWrapper } from "./GlowingBorderWrapper"
|
||||
import { TagBadge } from "./TagBadge"
|
||||
|
||||
type CoverCardProps = {
|
||||
item: {
|
||||
id: string
|
||||
name: string
|
||||
slug: string
|
||||
coverImage?: (Image & {
|
||||
colors?: (ImageColor & { color: Color })[]
|
||||
}) | null
|
||||
type: "album" | "gallery"
|
||||
gallerySlug?: string
|
||||
}
|
||||
}
|
||||
|
||||
export default function CoverCard({ item }: CoverCardProps) {
|
||||
const { showNSFW, animateGlow } = useGlobalSettings()
|
||||
const { coverImage } = item
|
||||
|
||||
const href =
|
||||
item.type === "album"
|
||||
? `/galleries/${item.gallerySlug}/${item.slug}`
|
||||
: `/galleries/${item.slug}`
|
||||
|
||||
const badgeText = item.type === "album" ? "Album" : "Gallery"
|
||||
const badgeIcon =
|
||||
item.type === "album" ? <BookOpenIcon size={12} className="mr-1" /> : <ImagePlusIcon size={12} className="mr-1" />
|
||||
|
||||
const borderColors =
|
||||
coverImage?.colors?.map((c) => c.color?.hex).filter((hex): hex is string => Boolean(hex)) ?? []
|
||||
|
||||
const shouldBlur = coverImage?.nsfw && !showNSFW
|
||||
|
||||
const content = (
|
||||
<div className="group rounded-lg border overflow-hidden hover:shadow-lg transition-shadow bg-background relative">
|
||||
<div className="relative aspect-[4/3] w-full bg-muted items-center justify-center">
|
||||
{coverImage?.fileKey ? (
|
||||
<NextImage
|
||||
src={`/api/image/thumbnails/${coverImage.fileKey}.webp`}
|
||||
alt={coverImage.imageName}
|
||||
fill
|
||||
className={clsx(
|
||||
"object-cover transition duration-300",
|
||||
shouldBlur && "blur-md scale-105"
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-muted-foreground text-sm">
|
||||
No cover image
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute top-1 left-1 z-10 flex gap-1">
|
||||
<TagBadge
|
||||
label={badgeText}
|
||||
variant="secondary"
|
||||
className="text-xs px-2 py-0.5 inline-flex items-center"
|
||||
icon={badgeIcon}
|
||||
/>
|
||||
{coverImage?.nsfw && (
|
||||
<TagBadge
|
||||
label="NSFW"
|
||||
variant="destructive"
|
||||
icon={<EyeOffIcon size={12} />}
|
||||
className="text-xs px-2 py-0.5 inline-flex items-center"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<h2 className="text-lg font-semibold truncate text-center">{item.name}</h2>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<Link href={href}>
|
||||
{coverImage && animateGlow && borderColors.length > 0 ? (
|
||||
<GlowingBorderWrapper colors={borderColors}>{content}</GlowingBorderWrapper>
|
||||
) : (
|
||||
content
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user