"use client"; import { useState, useEffect } from "react"; import { Album, ArtistSource } from "../types"; import { PlayableCard } from "@/components/ui/PlayableCard"; import { Disc3 } from "lucide-react"; import { api } from "@/lib/api"; interface AvailableAlbumsProps { albums: Album[]; artistName: string; source: ArtistSource; colors: any; onDownloadAlbum: (album: Album, e: React.MouseEvent) => void; isPendingDownload: (mbid: string) => boolean; } // Component to handle lazy-loading cover art for albums without cached covers function LazyAlbumCard({ album, source, colors, onDownloadAlbum, isPendingDownload, index, }: { album: Album; source: ArtistSource; colors: any; onDownloadAlbum: (album: Album, e: React.MouseEvent) => void; isPendingDownload: (mbid: string) => boolean; index: number; }) { const [coverArt, setCoverArt] = useState(() => { // Initial cover art from props if (source === "library" && album.coverArt) { return api.getCoverArtUrl(album.coverArt, 300); } if (album.coverUrl) { return api.getCoverArtUrl(album.coverUrl, 300); } return null; }); const [fetchAttempted, setFetchAttempted] = useState(false); // Lazy-load cover art if not available useEffect(() => { if (coverArt || fetchAttempted) return; const mbid = album.rgMbid || album.mbid; if (!mbid || mbid.startsWith("temp-")) return; // Fetch cover art from our backend (which caches it) const fetchCover = async () => { try { const response = await api.request<{ coverUrl: string }>( `/library/album-cover/${mbid}` ); if (response.coverUrl) { setCoverArt(api.getCoverArtUrl(response.coverUrl, 300)); } } catch { // Cover not found, leave as null } finally { setFetchAttempted(true); } }; // Delay fetch slightly to avoid thundering herd on page load const timeoutId = setTimeout(fetchCover, index * 100); return () => clearTimeout(timeoutId); }, [album, coverArt, fetchAttempted, index]); // Get MBID for download tracking const albumMbid = album.rgMbid || album.mbid || ""; // Build subtitle with year and type const subtitleParts: string[] = []; if (album.year) subtitleParts.push(String(album.year)); if (album.type) subtitleParts.push(album.type); const subtitle = subtitleParts.join(" • "); return ( } circular={false} badge="download" showPlayButton={false} colors={colors} isDownloading={isPendingDownload(albumMbid)} onDownload={(e) => onDownloadAlbum(album, e)} tvCardIndex={index} /> ); } function AlbumGrid({ albums, source, colors, onDownloadAlbum, isPendingDownload, }: Omit) { return (
{albums.map((album, index) => ( ))}
); } export function AvailableAlbums({ albums, artistName, source, colors, onDownloadAlbum, isPendingDownload, }: AvailableAlbumsProps) { if (!albums || albums.length === 0) { return null; } // Separate studio albums from EPs/Singles/Demos const studioAlbums = albums.filter( (album) => album.type?.toLowerCase() === "album" ); const epsAndSingles = albums.filter( (album) => album.type?.toLowerCase() !== "album" ); return ( <> {/* Studio Albums Section */} {studioAlbums.length > 0 && (

Albums Available

)} {/* EPs, Singles & Demos Section */} {epsAndSingles.length > 0 && (

Singles and EPs

)} ); }