"use client"; import { useState, memo, useCallback } from "react"; import Image from "next/image"; import { Track } from "../types"; import { Button } from "@/components/ui/Button"; import { EmptyState } from "@/components/ui/EmptyState"; import { PlaylistSelector } from "@/components/ui/PlaylistSelector"; import { GradientSpinner } from "@/components/ui/GradientSpinner"; import { AudioLines, ListPlus, Plus, Trash2, Play } from "lucide-react"; import { cn } from "@/utils/cn"; import { api } from "@/lib/api"; interface TracksListProps { tracks: Track[]; onPlay: (tracks: Track[], startIndex?: number) => void; onAddToQueue: (track: Track) => void; onAddToPlaylist: (playlistId: string, trackId: string) => void; onDelete: (trackId: string, trackTitle: string) => void; currentTrackId?: string; isLoading?: boolean; } const formatDuration = (seconds: number) => { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${mins}:${secs.toString().padStart(2, "0")}`; }; interface TrackRowProps { track: Track; index: number; isCurrentlyPlaying: boolean; onPlayTrack: () => void; onAddToQueue: (track: Track) => void; onShowAddToPlaylist: (trackId: string) => void; onDelete: (trackId: string, trackTitle: string) => void; } const TrackRow = memo(function TrackRow({ track, index, isCurrentlyPlaying, onPlayTrack, onAddToQueue, onShowAddToPlaylist, onDelete, }: TrackRowProps) { return (
{/* Track number / Play icon */}
{isCurrentlyPlaying ? ( ) : ( index + 1 )}
{/* Cover + Title/Artist */}
{track.album?.coverArt ? ( {track.title} ) : ( )}

{track.displayTitle ?? track.title}

{track.album?.artist?.name}

{/* Album - hidden on mobile */}

{track.album?.title}

{/* Actions + Duration */}
{formatDuration(track.duration)}
); }, (prevProps, nextProps) => { return ( prevProps.track.id === nextProps.track.id && prevProps.isCurrentlyPlaying === nextProps.isCurrentlyPlaying && prevProps.index === nextProps.index ); }); export function TracksList({ tracks, onPlay, onAddToQueue, onAddToPlaylist, onDelete, currentTrackId, isLoading = false, }: TracksListProps) { const [showPlaylistSelector, setShowPlaylistSelector] = useState(false); const [selectedTrackId, setSelectedTrackId] = useState(null); const handleShowAddToPlaylist = useCallback((trackId: string) => { setSelectedTrackId(trackId); setShowPlaylistSelector(true); }, []); const handleAddToPlaylist = useCallback(async (playlistId: string) => { if (!selectedTrackId) return; onAddToPlaylist(playlistId, selectedTrackId); setShowPlaylistSelector(false); setSelectedTrackId(null); }, [selectedTrackId, onAddToPlaylist]); if (isLoading) { return (
); } if (tracks.length === 0) { return ( } title="No songs yet" description="Your library is empty. Sync your music to get started." /> ); } return ( <> {/* Header row */}
#
Title
Album
Duration
{tracks.map((track, index) => { const isCurrentlyPlaying = currentTrackId === track.id; return ( onPlay(tracks, index)} onAddToQueue={onAddToQueue} onShowAddToPlaylist={handleShowAddToPlaylist} onDelete={onDelete} /> ); })}
{ setShowPlaylistSelector(false); setSelectedTrackId(null); }} onSelectPlaylist={handleAddToPlaylist} /> ); }