jefflix-website/components/music/search-results.tsx

93 lines
2.8 KiB
TypeScript

'use client'
import { useMusicPlayer, type Track } from './music-provider'
import { DownloadButton } from './download-button'
import { SwipeableRow } from './swipeable-row'
import { Play, Pause, ListPlus } from 'lucide-react'
function formatDuration(secs: number) {
if (!secs) return ''
const m = Math.floor(secs / 60)
const s = Math.floor(secs % 60)
return `${m}:${s.toString().padStart(2, '0')}`
}
export function SongRow({
song,
songs,
index,
showDownload = false,
}: {
song: Track
songs: Track[]
index: number
showDownload?: boolean
}) {
const { state, playTrack, togglePlay, addToQueue } = useMusicPlayer()
const isActive = state.currentTrack?.id === song.id
const isPlaying = isActive && state.isPlaying
return (
<SwipeableRow onSwipeRight={() => addToQueue(song)}>
<div
className={`flex items-center gap-3 px-4 py-2.5 hover:bg-muted/50 transition-colors group ${
isActive ? 'bg-primary/5' : ''
}`}
>
{/* Play button / track number */}
<button
onClick={() => isActive ? togglePlay() : playTrack(song, songs, index)}
className="flex-shrink-0 w-8 h-8 flex items-center justify-center rounded-full hover:bg-muted transition-colors"
>
{isPlaying ? (
<Pause className="h-4 w-4 text-primary" />
) : (
<Play className="h-4 w-4 text-primary ml-0.5" />
)}
</button>
{/* Cover art */}
<div className="flex-shrink-0 w-10 h-10 rounded overflow-hidden bg-muted">
{song.coverArt ? (
<img
src={`/api/music/cover/${song.coverArt}?size=80`}
alt={song.album}
className="w-full h-full object-cover"
loading="lazy"
/>
) : (
<div className="w-full h-full bg-muted" />
)}
</div>
{/* Info */}
<div className="flex-1 min-w-0">
<div className={`text-sm font-medium truncate ${isActive ? 'text-primary' : ''}`}>
{song.title}
</div>
<div className="text-xs text-muted-foreground truncate">
{song.artist} &middot; {song.album}
</div>
</div>
{/* Duration */}
<span className="text-xs text-muted-foreground tabular-nums hidden sm:block">
{formatDuration(song.duration)}
</span>
{/* Download */}
{showDownload && <DownloadButton track={song} />}
{/* Add to queue (desktop hover) */}
<button
onClick={(e) => { e.stopPropagation(); addToQueue(song) }}
className="p-1.5 opacity-0 group-hover:opacity-100 hover:bg-muted/50 rounded transition-all"
title="Add to queue"
>
<ListPlus className="h-4 w-4 text-muted-foreground" />
</button>
</div>
</SwipeableRow>
)
}