import { useEffect, useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; import { baseURL } from "../api/axiosInstance"; import { usePlayer } from "../context/playerContext"; import { toEmbedUrl } from "../utils/utils"; export interface SongItemData { id: number; title: string; cover?: string | null; genre?: string; link?: string | null; releasedBy?: string; isLikedByCurrentUser?: boolean; } interface SongItemProps { song: SongItemData; /** Optional label shown before the artist, e.g. "Song" for search results */ label?: string; /** Optional role badge for artist contributions, e.g. "PERFORMER" */ role?: string; /** Optional index number for playlist/collection views */ index?: number; /** Callback when the like button is clicked */ onLikeToggle?: (songId: number) => void; } const ROLE_COLORS: { [key: string]: string } = { COMPOSER: "bg-purple-500/20 text-purple-300", PERFORMER: "bg-blue-500/20 text-blue-300", PRODUCER: "bg-green-500/20 text-green-300", MAIN_VOCAL: "bg-pink-500/20 text-pink-300", }; const SongItem = ({ song, label, role, index, onLikeToggle, }: SongItemProps) => { const navigate = useNavigate(); const { play, currentSong } = usePlayer(); const [playlistOpen, setPlaylistOpen] = useState(false); const dropdownRef = useRef(null); const isPlaying = currentSong?.id === song.id; useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setPlaylistOpen(false); } }; if (playlistOpen) { document.addEventListener("mousedown", handleClickOutside); } return () => document.removeEventListener("mousedown", handleClickOutside); }, [playlistOpen]); const handleAddToPlaylist = (playlistName: string) => { console.log(`Adding song ${song.id} to ${playlistName}`); // TODO: Implement actual API call setPlaylistOpen(false); }; const handleCreateNewPlaylist = () => { console.log(`Creating new playlist for song ${song.id}`); // TODO: Implement actual playlist creation setPlaylistOpen(false); }; // Build subtitle const subtitleParts: string[] = []; if (label) subtitleParts.push(label); if (song.releasedBy) subtitleParts.push(song.releasedBy); const subtitle = subtitleParts.join(" • "); return (
navigate(`/songs/${song.id}`)} className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group" > {/* Optional index */} {index != null && ( {index} )} {/* Cover */} {song.title} { (e.target as HTMLImageElement).src = "/favicon.png"; }} /> {/* Title & subtitle */}

{song.title}

{subtitle && (

{subtitle}

)}
{/* Role badge (artist contributions) */} {role && ( )} {/* Genre */} {song.genre && ( {song.genre} )} {/* Play button */} {song.link && ( )} {/* Like button */} {onLikeToggle && ( )} {/* Three-dot menu */}
{playlistOpen && (
Add to playlist
)}
); }; export default SongItem;