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, Star, Clock, DollarSign, CheckCircle, Music, } from "lucide-react"; import { useNavigate } from "react-router-dom"; interface ArtistService { id: string; user_id: string; full_name: string; avatar_url?: string; bio?: string; skills: string[]; verified: boolean; rating: number; for_hire: boolean; price_list: { track_custom?: number; sfx_pack?: number; full_score?: number; day_rate?: number; contact_for_quote?: boolean; }; turnaround_days?: number; } const SERVICE_TYPES = [ { value: "track_custom", label: "Custom Track" }, { value: "sfx_pack", label: "SFX Pack" }, { value: "full_score", label: "Full Game Score" }, { value: "day_rate", label: "Day Rate Consulting" }, ]; export default function AudioServicesForHire() { const navigate = useNavigate(); const [artists, setArtists] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(""); const [selectedSkill, setSelectedSkill] = useState(null); const [selectedService, setSelectedService] = useState(null); const [minRating, setMinRating] = useState(0); useEffect(() => { const fetchArtists = async () => { try { setLoading(true); // Fetch artists who are for_hire const response = await fetch( `/api/ethos/artists?forHire=true&limit=50`, ); if (response.ok) { const result = await response.json(); const artistsData = result.data || result || []; // Map the response to expected format const mappedArtists = artistsData.map((artist: any) => ({ id: artist.user_id, user_id: artist.user_id, full_name: artist.user_profiles?.full_name || "Unknown Artist", avatar_url: artist.user_profiles?.avatar_url, bio: artist.bio, skills: artist.skills || [], verified: artist.verified || false, rating: 5.0, // Default rating - could be fetched from a ratings table for_hire: artist.for_hire, price_list: artist.price_list || { track_custom: artist.sample_price_track, sfx_pack: artist.sample_price_sfx, full_score: artist.sample_price_score, }, turnaround_days: artist.turnaround_days, })); setArtists(mappedArtists); } } catch (error) { console.error("Failed to fetch artists:", error); setArtists([]); } finally { setLoading(false); } }; const timer = setTimeout(fetchArtists, 300); return () => clearTimeout(timer); }, []); // Filter and sort artists const filteredArtists = artists.filter((artist) => { const matchesSearch = !searchQuery || artist.full_name.toLowerCase().includes(searchQuery.toLowerCase()) || artist.bio?.toLowerCase().includes(searchQuery.toLowerCase()); const matchesSkill = !selectedSkill || artist.skills.some((skill) => skill.toLowerCase().includes(selectedSkill.toLowerCase()), ); const matchesService = !selectedService || (artist.price_list as Record)[selectedService] !== null; const matchesRating = artist.rating >= minRating; return matchesSearch && matchesSkill && matchesService && matchesRating; }); // Get all unique skills from artists const allSkills = Array.from( new Set(artists.flatMap((artist) => artist.skills)), ).sort(); return (
{/* Search & Filters */}
setSearchQuery(e.target.value)} className="pl-10 bg-slate-800 border-slate-700" />
{/* Results Count */}
{loading ? "Loading..." : `${filteredArtists.length} artist${filteredArtists.length !== 1 ? "s" : ""} available`}
{/* Artists Grid */} {loading ? (
Loading artists...
) : filteredArtists.length === 0 ? (
No artists found matching your criteria. Try adjusting your filters.
) : (
{filteredArtists.map((artist) => (
{artist.avatar_url && ( {artist.full_name} )}
{artist.full_name} {artist.verified && ( )}
{artist.rating.toFixed(1)}
{/* Bio */} {artist.bio && (

{artist.bio}

)} {/* Skills */}

Skills

{artist.skills.slice(0, 3).map((skill) => ( {skill} ))} {artist.skills.length > 3 && ( +{artist.skills.length - 3} )}
{/* Service Pricing */}

Services

{artist.price_list.track_custom && (
Custom Track ${artist.price_list.track_custom}
)} {artist.price_list.sfx_pack && (
SFX Pack ${artist.price_list.sfx_pack}
)} {artist.price_list.full_score && (
Full Score ${artist.price_list.full_score}
)} {artist.price_list.day_rate && (
Day Rate ${artist.price_list.day_rate}/day
)} {artist.price_list.contact_for_quote && (
Enterprise rates available - contact for quote
)}
{/* Turnaround */} {artist.turnaround_days && (
{artist.turnaround_days} day turnaround
)} {/* CTA Buttons */}
))}
)}
); }