Files
mice/app/components/SimilarArtists.tsx
angel 579eb740c0 chore: update Tailwind CSS from 3.4.15, to 4.1.11
- Changed the PostCSS configuration to use '@tailwindcss/postcss' instead of 'tailwindcss'.
- Deleted the Tailwind configuration file as it is no longer needed.
2025-07-03 02:53:19 +00:00

97 lines
3.0 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import Image from 'next/image';
import { lastFmAPI } from '@/lib/lastfm-api';
import { Button } from '@/components/ui/button';
import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area';
import Link from 'next/link';
interface SimilarArtist {
name: string;
url: string;
image?: Array<{
'#text': string;
size: string;
}>;
}
interface SimilarArtistsProps {
artistName: string;
}
export function SimilarArtists({ artistName }: SimilarArtistsProps) {
const [similarArtists, setSimilarArtists] = useState<SimilarArtist[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchSimilarArtists = async () => {
if (!lastFmAPI.isAvailable()) return;
setLoading(true);
try {
const similar = await lastFmAPI.getSimilarArtists(artistName, 6);
if (similar?.artist) {
setSimilarArtists(similar.artist);
}
} catch (error) {
console.error('Failed to fetch similar artists:', error);
} finally {
setLoading(false);
}
};
fetchSimilarArtists();
}, [artistName]);
const getArtistImage = (artist: SimilarArtist): string => {
if (!artist.image || artist.image.length === 0) {
return '/default-user.jpg';
}
// Try to get medium or large image
const mediumImage = artist.image.find(img => img.size === 'medium' || img.size === 'large');
const anyImage = artist.image[artist.image.length - 1]; // Fallback to last image
return mediumImage?.['#text'] || anyImage?.['#text'] || '/default-user.jpg';
};
if (!lastFmAPI.isAvailable() || loading || similarArtists.length === 0) {
return null;
}
return (
<div className="space-y-4">
<h2 className="text-2xl font-semibold tracking-tight">Fans also like</h2>
<ScrollArea>
<div className="flex space-x-4 pb-4">
{similarArtists.map((artist) => (
<Link
key={artist.name}
href={`/artist/${encodeURIComponent(artist.name)}`}
className="shrink-0"
>
<div className="w-32 space-y-2 group cursor-pointer">
<div className="relative w-32 h-32 bg-muted rounded-full overflow-hidden">
<Image
src={getArtistImage(artist)}
alt={artist.name}
width={128}
height={128}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200"
/>
</div>
<div className="text-center">
<p className="text-sm font-medium truncate group-hover:text-primary transition-colors">
{artist.name}
</p>
</div>
</div>
</Link>
))}
</div>
<ScrollBar orientation="horizontal" />
</ScrollArea>
</div>
);
}