import { useState, useEffect } from "react"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Search, Download, Music, Star } from "lucide-react"; import { useNavigate } from "react-router-dom"; interface Track { id: string; title: string; artist_name: string; artist_id: string; genre: string[]; bpm: number; duration_seconds: number; license_type: string; download_count: number; rating: number; price?: number; description?: string; } const GENRE_OPTIONS = [ "Synthwave", "Orchestral", "Electronic", "Ambient", "Jazz", "Folk", "Hip-Hop", "Cinematic", "Game Audio", "SFX", ]; const LICENSE_OPTIONS = [ { value: "ecosystem", label: "Ecosystem (Free)" }, { value: "commercial_sample", label: "Commercial (Paid)" }, ]; export default function AudioTracksForSale() { const navigate = useNavigate(); const [tracks, setTracks] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(""); const [selectedGenre, setSelectedGenre] = useState(null); const [selectedLicense, setSelectedLicense] = useState(null); const [sortBy, setSortBy] = useState("popularity"); useEffect(() => { const fetchTracks = async () => { try { setLoading(true); // Build query parameters const params = new URLSearchParams(); if (searchQuery) params.append("search", searchQuery); if (selectedGenre) params.append("genre", selectedGenre); if (selectedLicense) params.append("licenseType", selectedLicense); const response = await fetch( `/api/ethos/tracks?${params.toString()}&limit=20`, ); if (response.ok) { const { data } = await response.json(); setTracks(data); } } catch (error) { console.error("Failed to fetch tracks:", error); } finally { setLoading(false); } }; // Debounce search const timer = setTimeout(fetchTracks, 300); return () => clearTimeout(timer); }, [searchQuery, selectedGenre, selectedLicense]); const sortedTracks = [...tracks].sort((a, b) => { switch (sortBy) { case "popularity": return b.download_count - a.download_count; case "newest": return 0; // Would need created_at from API case "rating": return (b.rating || 0) - (a.rating || 0); case "price-low": return (a.price || 0) - (b.price || 0); case "price-high": return (b.price || 0) - (a.price || 0); default: return 0; } }); return (
{/* Search & Filters */}
setSearchQuery(e.target.value)} className="pl-10 bg-slate-800 border-slate-700" />
{/* Results Count */}
{loading ? "Loading..." : `${sortedTracks.length} tracks found`}
{/* Tracks Grid */} {loading ? (
Loading tracks...
) : sortedTracks.length === 0 ? (
No tracks found. Try adjusting your filters.
) : (
{sortedTracks.map((track) => ( navigate(`/ethos/library/${track.id}`)} >
{track.title}

by {track.artist_name}

{/* Genre & BPM */}
{track.genre.slice(0, 2).map((g) => ( {g} ))} {track.bpm} BPM
{/* License & Price */}
{track.license_type === "ecosystem" ? "Free" : "Commercial"} {track.price && ( ${track.price} )}
{/* Rating & Downloads */}
{track.rating || 5.0}
{track.download_count} downloads
{/* Duration */}

{Math.floor(track.duration_seconds / 60)}: {String(track.duration_seconds % 60).padStart(2, "0")}

{/* CTA Button */}
))}
)}
); }