"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.displayTitle ?? track.title}
{track.album?.artist?.name}
{/* Album - hidden on mobile */}
{/* 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 */}
{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}
/>
>
);
}