import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import axiosInstance, { baseURL } from "../api/axiosInstance"; import PlaylistDropdown from "../components/playlist/PlaylistDropdown"; import AlbumResult from "../components/search/AlbumResult"; import SongResult from "../components/search/SongResult"; import UserResult from "../components/search/UserResult"; import { useAuth } from "../context/authContext"; import { usePlayer } from "../context/playerContext"; import type { Album, BaseNonAdminUser, SearchCategory, Song, } from "../utils/types"; import { toEmbedUrl } from "../utils/utils"; const CATEGORIES: { value: SearchCategory; label: string }[] = [ { value: "songs", label: "Songs" }, { value: "albums", label: "Albums" }, { value: "artists", label: "Artists" }, { value: "users", label: "Users" }, ]; const LandingPage = () => { const navigate = useNavigate(); const { play, currentSong } = usePlayer(); const { user } = useAuth(); const [songs, setSongs] = useState([]); const [loading, setLoading] = useState(true); const [searchInput, setSearchInput] = useState(""); const [activeQuery, setActiveQuery] = useState(""); const [searchCategory, setSearchCategory] = useState("songs"); const [searchResults, setSearchResults] = useState([]); const [searchLoading, setSearchLoading] = useState(false); const [hasSearched, setHasSearched] = useState(false); const [openPlaylistDropdown, setOpenPlaylistDropdown] = useState< number | null >(null); useEffect(() => { const fetchSongs = async () => { try { const response = await axiosInstance.get("/songs/top"); setSongs(response.data); } catch (error) { console.error("Error fetching songs:", error); } finally { setLoading(false); } }; fetchSongs(); }, []); const toggleLike = async (songId: number) => { try { await axiosInstance.post(`/musical-entity/${songId}/like`); setSongs((prevSongs) => prevSongs.map((song) => song.id === songId ? { ...song, isLikedByCurrentUser: !song.isLikedByCurrentUser } : song, ), ); } catch (error) { console.error("Error toggling like:", error); } }; const togglePlaylistDropdown = (songId: number) => { if (openPlaylistDropdown === songId) { setOpenPlaylistDropdown(null); } else { setOpenPlaylistDropdown(songId); } }; const performSearch = async (query: string, category: SearchCategory) => { if (!query.trim()) return; setSearchLoading(true); setHasSearched(true); setActiveQuery(query); setSearchCategory(category); try { let endpoint = ""; switch (category) { case "songs": endpoint = `/songs/search?q=${encodeURIComponent(query)}`; break; case "albums": endpoint = `/albums/search?q=${encodeURIComponent(query)}`; break; case "artists": endpoint = `/users/search?type=ARTIST&q=${encodeURIComponent(query)}`; break; case "users": endpoint = `/users/search?type=LISTENER&q=${encodeURIComponent(query)}`; break; } const response = await axiosInstance.get(endpoint); setSearchResults(response.data); } catch (error) { console.error("Search error:", error); setSearchResults([]); } finally { setSearchLoading(false); } }; const handleSearch = () => { performSearch(searchInput, searchCategory); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter") { handleSearch(); } }; const handleCategorySwitch = (category: SearchCategory) => { performSearch(activeQuery, category); }; const clearSearch = () => { setSearchInput(""); setActiveQuery(""); setHasSearched(false); setSearchResults([]); }; const renderResults = () => { if (searchLoading) { return (
); } if (searchResults.length === 0) { return (

No {searchCategory} found for "{activeQuery}"

); } return (
{searchResults.map((result, index) => { switch (searchCategory) { case "songs": return ( ); case "albums": return ( ); case "artists": return ( ); case "users": return ( ); } })}
); }; return (
{/* Search Bar */}
{/* Category Dropdown */} {/* Search Input */} setSearchInput(e.target.value)} onKeyDown={handleKeyDown} className="flex-1 bg-[#282828] border border-white/10 border-r-0 py-2 px-4 text-white focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all" /> {/* Search Button */}
{/* Search Results Section */} {hasSearched ? (

Results for "{activeQuery}"

{/* Quick category switch buttons */}
{CATEGORIES.map((cat) => ( ))}
{/* Results list */}
{renderResults()}
) : ( /* Default song grid */ <>

Top Songs

Listen to the newest tracks on FinkWave

{loading ? (

Loading songs...

) : (
{songs.map((song) => (
navigate(`/songs/${song.id}`)} onMouseEnter={() => { if ( openPlaylistDropdown !== null && openPlaylistDropdown !== song.id ) { setOpenPlaylistDropdown(null); } }} className="bg-[#282828] rounded-xl cursor-pointer shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-2 hover:shadow-2xl group relative" >
{song.title} { (e.target as HTMLImageElement).src = "/favicon.png"; }} />
{song.link ? ( ) : (
)}

{song.title}

{song.album && (

{ e.stopPropagation(); if (song.albumId) { navigate(`/collection/album/${song.albumId}`); } }} className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${ song.albumId ? "hover:underline cursor-pointer hover:text-white" : "" }`} > {song.album}

)}

{ e.stopPropagation(); if (song.artistUsername) { navigate(`/users/${song.artistUsername}`); } }} className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${ song.artistUsername ? "hover:underline cursor-pointer hover:text-white" : "" }`} > {song.releasedBy}

{user && (
{/* Like button */} {/* Add to playlist button */}
setOpenPlaylistDropdown(null)} direction="above" />
)}
))}
)} )}
); }; export default LandingPage;