From 9cef0fb0a6028f3a81bc4841fb8fb3e2799546a3 Mon Sep 17 00:00:00 2001 From: "Builder.io" Date: Wed, 12 Nov 2025 02:33:29 +0000 Subject: [PATCH] NEXUS Audio: Tracks for Sale browsing component cgen-39a7a7fcbd514c15bf78c88c468271d0 --- .../components/nexus/AudioTracksForSale.tsx | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 client/components/nexus/AudioTracksForSale.tsx diff --git a/client/components/nexus/AudioTracksForSale.tsx b/client/components/nexus/AudioTracksForSale.tsx new file mode 100644 index 00000000..f1a6239a --- /dev/null +++ b/client/components/nexus/AudioTracksForSale.tsx @@ -0,0 +1,273 @@ +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 */} + +
+
+ ))} +
+ )} +
+ ); +}