"use client"; import { useRouter } from "next/navigation"; import { useAudio } from "@/lib/audio-context"; import { useDownloadContext } from "@/lib/download-context"; import { LoadingScreen } from "@/components/ui/LoadingScreen"; import { useImageColor } from "@/hooks/useImageColor"; import { api } from "@/lib/api"; import { toast } from "sonner"; // Hooks import { useArtistData } from "@/features/artist/hooks/useArtistData"; import { useArtistActions } from "@/features/artist/hooks/useArtistActions"; import { useDownloadActions } from "@/features/artist/hooks/useDownloadActions"; import { usePreviewPlayer } from "@/features/artist/hooks/usePreviewPlayer"; // Components import { ArtistHero } from "@/features/artist/components/ArtistHero"; import { ArtistActionBar } from "@/features/artist/components/ArtistActionBar"; import { ArtistBio } from "@/features/artist/components/ArtistBio"; import { PopularTracks } from "@/features/artist/components/PopularTracks"; import { Discography } from "@/features/artist/components/Discography"; import { AvailableAlbums } from "@/features/artist/components/AvailableAlbums"; import { SimilarArtists } from "@/features/artist/components/SimilarArtists"; export default function ArtistPage() { const router = useRouter(); const { currentTrack, playTracks, isPlaying, pause } = useAudio(); const { isPendingByMbid } = useDownloadContext(); // Data hook const { artist, albums, loading, error, source, reloadArtist } = useArtistData(); // Action hooks const { playAll, shufflePlay } = useArtistActions(); const { downloadArtist, downloadAlbum } = useDownloadActions(); const { previewTrack, previewPlaying, handlePreview } = usePreviewPlayer(); // Separate owned and available albums const ownedAlbums = albums.filter((a) => a.owned); const availableAlbums = albums.filter((a) => !a.owned); // Get image URLs for display and color extraction const rawImageUrl = artist && source === "library" ? artist.coverArt : artist?.image || null; const heroImage = rawImageUrl ? api.getCoverArtUrl(rawImageUrl, 1200) : null; const { colors } = useImageColor(heroImage || rawImageUrl); // Play album handler async function handlePlayAlbum(albumId: string, albumTitle: string) { try { const albumData = await api.getAlbum(albumId); if (albumData.tracks && albumData.tracks.length > 0) { const tracksWithAlbum = albumData.tracks.map((track: any) => ({ ...track, album: { id: albumData.id, title: albumData.title, coverArt: albumData.coverArt, }, artist: albumData.artist, })); playTracks(tracksWithAlbum, 0); toast.success(`Playing ${albumTitle}`); } } catch (error) { console.error("Failed to play album:", error); toast.error("Failed to play album"); } } // Play track handler (for popular tracks) function handlePlayTrack(track: any) { if (!artist?.topTracks) return; const playableTracks = artist.topTracks.filter((t: any) => t.album?.id); const formattedTracks = playableTracks.map((t: any) => ({ id: t.id, title: t.title, artist: { name: artist.name, id: artist.id }, album: { title: t.album?.title || "Unknown", coverArt: t.album?.coverArt, id: t.album?.id, }, duration: t.duration, })); const startIndex = formattedTracks.findIndex((t: any) => t.id === track.id); playTracks(formattedTracks, Math.max(0, startIndex)); } // Download album handler function handleDownloadAlbum(album: any, e: React.MouseEvent) { downloadAlbum(album, artist?.name || "", e); } // Start artist radio handler async function handleStartRadio() { if (!artist) return; try { toast.success(`Starting ${artist.name} Radio...`); const response = await api.getRadioTracks("artist", artist.id); if (response.tracks && response.tracks.length > 0) { // Backend already returns properly formatted tracks - just pass them through playTracks(response.tracks, 0); toast.success(`Playing ${artist.name} Radio (${response.tracks.length} tracks)`); } else { toast.error("Not enough similar music in your library for artist radio"); } } catch (error) { console.error("Failed to start artist radio:", error); toast.error("Failed to start artist radio"); } } // Loading state if (loading) { return ; } // Error or not found state if (error || !artist) { return (

Artist Not Found

This artist isn't in your library yet.

); } return (
{/* Action bar inside hero for visual continuity */} playAll(artist, albums)} onShuffle={() => shufflePlay(artist, albums)} onDownloadAll={() => downloadArtist(artist)} onStartRadio={handleStartRadio} isPendingDownload={isPendingByMbid(artist.mbid || "")} isPlaying={isPlaying} isPlayingThisArtist={currentTrack?.artist?.id === artist.id || currentTrack?.artist?.name === artist.name} onPause={pause} /> {/* Main Content - fills remaining viewport height */}
{/* Dynamic color gradient background */}
{/* Bio / About */} {(artist.bio || artist.summary) && } {/* Popular Tracks */} {artist.topTracks && artist.topTracks.length > 0 && ( handlePreview(track, artist.name, e) } /> )} {/* Discography (Owned Albums) */} {/* Available Albums to Download */} {/* Similar Artists */} {artist.similarArtists && artist.similarArtists.length > 0 && ( router.push(`/artist/${id}`)} /> )}
); }