'use client' import { useState, useEffect } from 'react' import { Trash2, CheckSquare, Square, X } from 'lucide-react' import Navbar from '@/components/Navbar' import Header from '@/components/Header' import SongCard from '@/components/SongCard' import { useToast } from '@/components/Toast' import { usePlayer } from '@/components/PlayerContext' interface Song { id: string youtubeId: string title: string channelName: string thumbnail: string duration: number playlists?: Playlist[] } interface Playlist { id: string name: string } export default function Home() { const [songs, setSongs] = useState([]) const [playlists, setPlaylists] = useState([]) const [isLoading, setIsLoading] = useState(false) const [isSelectionMode, setIsSelectionMode] = useState(false) const [selectedSongs, setSelectedSongs] = useState>(new Set()) const [isDeletingSelected, setIsDeletingSelected] = useState(false) const { showToast } = useToast() const { playSong } = usePlayer() // Fetch songs and playlists on mount useEffect(() => { fetchData() }, []) const fetchData = async () => { await Promise.all([fetchSongs(), fetchPlaylists()]) } const fetchPlaylists = async () => { try { const response = await fetch('/api/playlists') if (response.ok) { const data = await response.json() setPlaylists(data) // Update songs with playlist information updateSongsWithPlaylists(data) } } catch (error) { console.error('Error fetching playlists:', error) } } const updateSongsWithPlaylists = (playlistData: any[]) => { setSongs(prevSongs => prevSongs.map(song => { const songPlaylists = playlistData .filter(playlist => playlist.playlistSongs?.some((ps: any) => ps.song.id === song.id) ) .map(playlist => ({ id: playlist.id, name: playlist.name })) return { ...song, playlists: songPlaylists } }) ) } const fetchSongs = async () => { try { const response = await fetch('/api/songs') if (response.ok) { const data = await response.json() setSongs(data) } } catch (error) { console.error('Error fetching songs:', error) } } const handleAddSong = async (url: string) => { setIsLoading(true) try { const response = await fetch('/api/songs', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ url }), }) if (response.ok) { const newSong = await response.json() setSongs((prev) => [newSong, ...prev]) showToast('Song added successfully', 'success') } else { showToast('Failed to add song. Please check the URL.', 'error') } } catch (error) { console.error('Error adding song:', error) showToast('An error occurred while adding the song.', 'error') } finally { setIsLoading(false) } } const handlePlaySong = (song: Song) => { const index = songs.findIndex((s) => s.id === song.id) playSong(song, index, songs, false) } const handleDeleteSong = async (songId: string) => { try { const response = await fetch(`/api/songs/${songId}`, { method: 'DELETE', }) if (response.ok) { // Remove song from state setSongs((prev) => prev.filter((s) => s.id !== songId)) showToast('Song deleted', 'success') } else { showToast('Error deleting song', 'error') } } catch (error) { console.error('Error deleting song:', error) showToast('Error deleting song', 'error') } } // Selection mode functions const toggleSelectionMode = () => { setIsSelectionMode(!isSelectionMode) setSelectedSongs(new Set()) } const toggleSongSelection = (songId: string) => { const newSelected = new Set(selectedSongs) if (newSelected.has(songId)) { newSelected.delete(songId) } else { newSelected.add(songId) } setSelectedSongs(newSelected) } const selectAllSongs = () => { if (selectedSongs.size === songs.length) { setSelectedSongs(new Set()) } else { setSelectedSongs(new Set(songs.map(song => song.id))) } } const deleteSelectedSongs = async () => { if (selectedSongs.size === 0) return setIsDeletingSelected(true) try { const deletePromises = Array.from(selectedSongs).map(songId => fetch(`/api/songs/${songId}`, { method: 'DELETE' }) ) const results = await Promise.all(deletePromises) const successfulDeletes = results.filter(r => r.ok).length if (successfulDeletes > 0) { setSongs(prev => prev.filter(song => !selectedSongs.has(song.id))) showToast(`${successfulDeletes} song${successfulDeletes !== 1 ? 's' : ''} deleted`, 'success') } if (successfulDeletes < selectedSongs.size) { showToast(`Failed to delete ${selectedSongs.size - successfulDeletes} song${selectedSongs.size - successfulDeletes !== 1 ? 's' : ''}`, 'error') } setSelectedSongs(new Set()) setIsSelectionMode(false) } catch (error) { console.error('Error deleting selected songs:', error) showToast('Error deleting songs', 'error') } finally { setIsDeletingSelected(false) } } const handleAddToPlaylist = async (songId: string, playlistId: string) => { try { const response = await fetch(`/api/playlists/${playlistId}/songs`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ songId }), }) if (response.ok) { showToast('Song added to playlist', 'success') // Refresh playlists to update song-playlist relationships await fetchPlaylists() } else { const data = await response.json() showToast(data.error || 'Error adding song to playlist', 'error') } } catch (error) { console.error('Error adding to playlist:', error) showToast('Error adding song to playlist', 'error') } } return (
{/* Selection mode bar */} {isSelectionMode && (
{selectedSongs.size} of {songs.length} selected
{selectedSongs.size > 0 && ( )}
)}
{songs.length === 0 ? (

No songs yet

Add your first song by pasting a YouTube URL

) : (
{!isSelectionMode && (
)}
{songs.map((song) => ( ))}
)}
) }