Files
lidify/frontend/features/home/components/ArtistsGrid.tsx
2025-12-25 18:58:06 -06:00

88 lines
2.9 KiB
TypeScript

"use client";
import Link from "next/link";
import Image from "next/image";
import { Music } from "lucide-react";
import { api } from "@/lib/api";
import { memo } from "react";
import { HorizontalCarousel, CarouselItem } from "@/components/ui/HorizontalCarousel";
interface Artist {
id: string;
mbid?: string;
name: string;
coverArt?: string;
albumCount?: number;
}
interface ArtistsGridProps {
artists: Artist[];
}
// Helper to get the correct image source
const getArtistImageSrc = (coverArt: string | undefined) => {
if (!coverArt) {
return null;
}
return api.getCoverArtUrl(coverArt, 300);
};
interface ArtistCardProps {
artist: Artist;
index: number;
}
const ArtistCard = memo(
function ArtistCard({ artist, index }: ArtistCardProps) {
const imageSrc = getArtistImageSrc(artist.coverArt);
return (
<CarouselItem>
<Link
href={`/artist/${artist.mbid || artist.id}`}
data-tv-card
data-tv-card-index={index}
tabIndex={0}
>
<div className="p-3 rounded-md group cursor-pointer hover:bg-white/5 transition-colors">
<div className="aspect-square bg-[#282828] rounded-full mb-3 flex items-center justify-center overflow-hidden relative shadow-lg">
{artist.coverArt && imageSrc ? (
<Image
src={imageSrc}
alt={artist.name}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
sizes="180px"
priority={false}
unoptimized
/>
) : (
<Music className="w-10 h-10 text-gray-600" />
)}
</div>
<h3 className="text-sm font-semibold text-white truncate">
{artist.name}
</h3>
<p className="text-xs text-gray-400 mt-0.5">Artist</p>
</div>
</Link>
</CarouselItem>
);
},
(prevProps, nextProps) => {
return prevProps.artist.id === nextProps.artist.id && prevProps.index === nextProps.index;
}
);
const ArtistsGrid = memo(function ArtistsGrid({ artists }: ArtistsGridProps) {
return (
<HorizontalCarousel>
{artists.map((artist, index) => (
<ArtistCard key={artist.id} artist={artist} index={index} />
))}
</HorizontalCarousel>
);
});
export { ArtistsGrid, getArtistImageSrc };