76 lines
2 KiB
TypeScript
76 lines
2 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import Image from "next/image";
|
|
import { useMemo, useState } from "react";
|
|
import { urlFor } from "@/lib/sanityImage";
|
|
import { ARTIST_PLACEHOLDER_SRC } from "@/lib/constants";
|
|
|
|
import type { SanityImageSource } from "@sanity/image-url";
|
|
|
|
export type ArtistCardProps = {
|
|
name?: string;
|
|
subtitle?: string;
|
|
image?: SanityImageSource;
|
|
href: string;
|
|
label?: string;
|
|
className?: string;
|
|
};
|
|
|
|
export function useCardImage(image?: SanityImageSource) {
|
|
const [imgError, setImgError] = useState(false);
|
|
|
|
const src = useMemo(() => {
|
|
if (imgError || !image) return ARTIST_PLACEHOLDER_SRC;
|
|
return urlFor(image).url();
|
|
}, [image, imgError]);
|
|
|
|
return { src, onError: () => setImgError(true) };
|
|
}
|
|
|
|
export function ArtistCard({
|
|
name,
|
|
subtitle,
|
|
image,
|
|
href,
|
|
label = "Artist",
|
|
className = "",
|
|
}: ArtistCardProps) {
|
|
const { src, onError } = useCardImage(image);
|
|
|
|
return (
|
|
<Link
|
|
href={href}
|
|
className={[
|
|
"group relative z-10 rounded-xl bg-lightbg shadow-lg ring-1 ring-lightline dark:bg-darkbg dark:ring-darkline",
|
|
"hover:text-trptkblue hover:ring-lightline-hover dark:hover:text-white dark:hover:ring-darkline-hover",
|
|
"transition-color duration-300 ease-in-out",
|
|
className,
|
|
].join(" ")}
|
|
aria-label={name ? `${label}: ${name}` : label}
|
|
>
|
|
<div className="relative aspect-square w-full overflow-hidden rounded-xl">
|
|
<Image
|
|
src={src}
|
|
alt={name ? `Photo of ${name}` : `${label} photo`}
|
|
fill
|
|
sizes="(max-width: 560px) calc(100vw - 32px), 450px"
|
|
className="object-cover"
|
|
onError={onError}
|
|
/>
|
|
</div>
|
|
|
|
<div className="p-3 sm:p-5">
|
|
<h3 className="text-sm break-words sm:mb-1 sm:text-base md:mb-2">
|
|
{name ?? `Untitled ${label.toLowerCase()}`}
|
|
</h3>
|
|
|
|
{subtitle ? (
|
|
<h4 className="hidden text-sm break-words text-lightsec sm:block dark:text-darksec">
|
|
{subtitle}
|
|
</h4>
|
|
) : null}
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|