forked from
chadtmiller.com/slices-teal-relay
Teal.fm frontend powered by slices.network
tealfm-slices.wisp.place
tealfm
slices
1import AlbumArt from "./AlbumArt";
2
3interface Artist {
4 artistName: string;
5}
6
7interface AlbumItemProps {
8 releaseName: string;
9 releaseMbId: string | null | undefined;
10 artists: string | null | undefined;
11 count: number;
12 rank: number;
13 maxCount: number;
14}
15
16export default function AlbumItem({
17 releaseName,
18 releaseMbId,
19 artists,
20 count,
21 rank,
22 maxCount,
23}: AlbumItemProps) {
24 const barWidth = maxCount > 0 ? (count / maxCount) * 100 : 0;
25
26 // Parse artists JSON
27 let artistNames = "Unknown Artist";
28 if (artists) {
29 try {
30 const parsed = typeof artists === 'string' ? JSON.parse(artists) : artists;
31 if (Array.isArray(parsed)) {
32 artistNames = parsed.map((a: Artist) => a.artistName).join(", ");
33 } else if (typeof parsed === 'string') {
34 artistNames = parsed;
35 }
36 } catch (e) {
37 console.log('Failed to parse artists:', artists, e);
38 artistNames = String(artists);
39 }
40 } else {
41 console.log('No artists data for:', releaseName);
42 }
43
44 return (
45 <div className="group py-3 px-4 hover:bg-zinc-900/50 transition-colors relative overflow-hidden">
46 <div
47 className="absolute inset-y-0 left-0 bg-violet-500/10 transition-all"
48 style={{ width: `${barWidth}%` }}
49 />
50 <div className="flex items-center gap-4 relative">
51 <div className="text-xs text-zinc-600 w-8 text-right flex-shrink-0 font-medium">
52 {rank}
53 </div>
54
55 <div className="flex-shrink-0">
56 <AlbumArt releaseMbId={releaseMbId} alt={`${releaseName} album art`} />
57 </div>
58
59 <div className="flex-1 min-w-0">
60 <h3 className="text-sm font-medium text-zinc-100 truncate">
61 {releaseName}
62 </h3>
63 <p className="text-xs text-zinc-500 truncate">{artistNames}</p>
64 </div>
65
66 <div className="text-right flex-shrink-0">
67 <p className="text-xs text-zinc-400 font-medium">
68 {count.toLocaleString()}
69 </p>
70 </div>
71 </div>
72 </div>
73 );
74}