"use client"; import { Play, Pause, ArrowUpDown, Clock, Music2, User } from "lucide-react"; import { useEffect, useState } from "react"; import { usePlayer } from "@/context/PlayerContext"; import Link from "next/link"; import { libraryService } from "@/services/library"; import { Track } from "@/types"; import CoverImage from "@/components/CoverImage"; import Skeleton from "@/components/Skeleton"; type SortOption = 'recent' | 'alpha-asc' | 'alpha-desc' | 'artist'; export default function Home() { const [timeOfDay, setTimeOfDay] = useState("Good evening"); const [browseData, setBrowseData] = useState>({}); const [loading, setLoading] = useState(true); const [sortBy, setSortBy] = useState('recent'); const [showSortMenu, setShowSortMenu] = useState(false); useEffect(() => { const hour = new Date().getHours(); if (hour < 12) setTimeOfDay("Good morning"); else if (hour < 18) setTimeOfDay("Good afternoon"); else setTimeOfDay("Good evening"); // Fetch Browse Content setLoading(true); libraryService.getBrowseContent() .then(data => { setBrowseData(data); setLoading(false); }) .catch(err => { console.error("Error fetching browse:", err); setLoading(false); }); }, []); // Sort playlists based on selected option const sortPlaylists = (playlists: any[]) => { const sorted = [...playlists]; switch (sortBy) { case 'alpha-asc': return sorted.sort((a, b) => (a.title || '').localeCompare(b.title || '')); case 'alpha-desc': return sorted.sort((a, b) => (b.title || '').localeCompare(a.title || '')); case 'artist': return sorted.sort((a, b) => (a.author || a.creator || '').localeCompare(b.author || b.creator || '')); case 'recent': default: return sorted; } }; // Use first item of first category as Hero const firstCategory = Object.keys(browseData)[0]; const heroPlaylist = firstCategory && browseData[firstCategory].length > 0 ? browseData[firstCategory][0] : null; const sortOptions = [ { value: 'recent', label: 'Recently Added', icon: Clock }, { value: 'alpha-asc', label: 'Alphabetical (A-Z)', icon: ArrowUpDown }, { value: 'alpha-desc', label: 'Alphabetical (Z-A)', icon: ArrowUpDown }, { value: 'artist', label: 'Artist Name', icon: User }, ]; return (
{/* Header / Greetings with Sort Button */}

{timeOfDay}

{/* Sort Dropdown */}
{showSortMenu && (
{sortOptions.map((option) => ( ))}
)}
{/* Hero Section (Big Playlist Banner - AT THE TOP) */} {loading ? (
) : heroPlaylist && (
Featured Playlist

{heroPlaylist.title}

{heroPlaylist.description}

Play Now
)} {/* Made For You Section (Recommendations) */} {/* Artist Section (Vietnam) */} {/* Dynamic Recommended Albums based on history */} {/* Recently Listened */} {/* Main Browse Lists */} {loading ? (
{[1, 2].map(i => (
{[1, 2, 3, 4, 5].map(j => (
))}
))}
) : Object.keys(browseData).length > 0 ? ( Object.entries(browseData).map(([category, playlists]) => (

{category}

Show all
{sortPlaylists(playlists).slice(0, 5).map((playlist: any) => (

{playlist.title}

{playlist.description}

))}
)) ) : (

Ready to explore?

Browse content is loading or empty. Try initializing data.

)}
); } // NEW: Recently Listened Section - Pinned to top function RecentlyListenedSection() { const { playHistory, playTrack } = usePlayer(); if (playHistory.length === 0) return null; return (

Recently Listened

{/* Horizontal Scrollable Row */}
{playHistory.slice(0, 10).map((track, i) => (
playTrack(track, playHistory)} className="flex-shrink-0 w-40 bg-[#181818] rounded-lg overflow-hidden hover:bg-[#282828] transition duration-300 group cursor-pointer" >

{track.title}

{track.artist}

))}
); } function MadeForYouSection() { const { playHistory, playTrack } = usePlayer(); const [recommendations, setRecommendations] = useState([]); const [seedTrack, setSeedTrack] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { if (playHistory.length > 0) { const seed = playHistory[0]; // Last played setSeedTrack(seed); setLoading(true); // Fetch actual recommendations from backend fetch(`/api/recommendations?seed_id=${seed.id}`) .then(res => res.json()) .then(data => { if (data.tracks) { setRecommendations(data.tracks); } setLoading(false); }) .catch(err => { console.error("Rec error:", err); setLoading(false); }); } }, [playHistory.length > 0 ? playHistory[0].id : null]); if (playHistory.length === 0) return null; if (!loading && recommendations.length === 0) return null; return (

Made For You

{seedTrack ? ( <>Because you listened to {seedTrack.artist} ) : "Recommended for you"}

{loading ? (
{[1, 2, 3, 4, 5].map(i => (
))}
) : (
{recommendations.slice(0, 5).map((track, i) => (
playTrack(track, recommendations)} className="bg-[#181818] p-2 md:p-4 rounded-md hover:bg-[#282828] transition duration-300 group cursor-pointer relative h-full flex flex-col">

{track.title}

{track.artist}

))}
)}
); } function RecommendedAlbumsSection() { const { playHistory } = usePlayer(); const [albums, setAlbums] = useState([]); const [seedArtist, setSeedArtist] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { if (playHistory.length > 0) { const artist = playHistory[0].artist; if (!artist) return; // Clean artist name (remove delimiters like commas if multiple) const primaryArtist = artist.split(',')[0].trim(); setSeedArtist(primaryArtist); setLoading(true); fetch(`/api/recommendations/albums?seed_artist=${encodeURIComponent(primaryArtist)}`) .then(res => res.json()) .then(data => { if (Array.isArray(data)) setAlbums(data); setLoading(false); }) .catch(err => { console.error("Album Rec error:", err); setLoading(false); }); } }, [playHistory.length > 0 ? playHistory[0].artist : null]); if (playHistory.length === 0) return null; if (!loading && albums.length === 0) return null; return (

More from {seedArtist}

Albums you might like

{loading ? (
{[1, 2, 3, 4, 5].map(i => (
))}
) : (
{albums.slice(0, 5).map((album, i) => (

{album.title}

{album.description}

))}
)}
); } // NEW: Artist Vietnam Section with dynamic photos function ArtistVietnamSection() { // Popular Vietnamese artists const artistNames = [ "Sơn Tùng M-TP", "HIEUTHUHAI", "Đen Vâu", "Hoàng Dũng", "Vũ.", "MONO", "Tlinh", "Erik", ]; const [artistPhotos, setArtistPhotos] = useState>({}); const [loading, setLoading] = useState(true); useEffect(() => { // Fetch artist photos from API const fetchArtistPhotos = async () => { setLoading(true); const apiUrl = process.env.NEXT_PUBLIC_API_URL || ''; const photos: Record = {}; await Promise.all( artistNames.map(async (name) => { try { const res = await fetch(`${apiUrl}/api/artist/info?name=${encodeURIComponent(name)}`); if (res.ok) { const data = await res.json(); if (data.photo) { photos[name] = data.photo; } } } catch (e) { console.error(`Failed to fetch photo for ${name}:`, e); } }) ); setArtistPhotos(photos); setLoading(false); }; fetchArtistPhotos(); }, []); return (

Artist Vietnam

Popular Vietnamese artists

{/* Horizontal Scrollable Row */}
{loading ? ( // Skeleton Row [1, 2, 3, 4, 5, 6].map(i => (
)) ) : ( artistNames.map((name, i) => (

{name}

Artist

)) )}
); }