From 94cb7551565e57a9192f8fea319772b78e660096 Mon Sep 17 00:00:00 2001 From: "Builder.io" Date: Tue, 11 Nov 2025 23:09:44 +0000 Subject: [PATCH] Ethos track metadata form component (genre, BPM, license type) cgen-7227aa2e467e40459b7606b188834487 --- client/components/ethos/TrackMetadataForm.tsx | 188 ++++++++++++++++++ client/components/ethos/TrackUploadModal.tsx | 177 +++++++++++++++++ 2 files changed, 365 insertions(+) create mode 100644 client/components/ethos/TrackMetadataForm.tsx create mode 100644 client/components/ethos/TrackUploadModal.tsx diff --git a/client/components/ethos/TrackMetadataForm.tsx b/client/components/ethos/TrackMetadataForm.tsx new file mode 100644 index 00000000..b52a0070 --- /dev/null +++ b/client/components/ethos/TrackMetadataForm.tsx @@ -0,0 +1,188 @@ +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; + +interface TrackMetadata { + title: string; + description?: string; + genre: string[]; + bpm?: number; + license_type: "ecosystem" | "commercial_sample"; + is_published: boolean; +} + +interface TrackMetadataFormProps { + onSubmit: (metadata: TrackMetadata) => void; + initialData?: Partial; + isLoading?: boolean; +} + +const GENRES = [ + "Synthwave", + "Orchestral", + "SFX", + "Ambient", + "Electronic", + "Cinematic", + "Jazz", + "Hip-Hop", + "Folk", +]; + +export default function TrackMetadataForm({ + onSubmit, + initialData, + isLoading, +}: TrackMetadataFormProps) { + const [title, setTitle] = useState(initialData?.title || ""); + const [description, setDescription] = useState(initialData?.description || ""); + const [selectedGenres, setSelectedGenres] = useState( + initialData?.genre || [], + ); + const [bpm, setBpm] = useState(initialData?.bpm || ""); + const [licenseType, setLicenseType] = useState<"ecosystem" | "commercial_sample">( + initialData?.license_type || "ecosystem", + ); + const [isPublished, setIsPublished] = useState( + initialData?.is_published !== false, + ); + + const toggleGenre = (genre: string) => { + setSelectedGenres((prev) => + prev.includes(genre) + ? prev.filter((g) => g !== genre) + : [...prev, genre], + ); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + if (!title || selectedGenres.length === 0) { + alert("Title and at least one genre are required"); + return; + } + + onSubmit({ + title, + description: description || undefined, + genre: selectedGenres, + bpm: bpm ? Number(bpm) : undefined, + license_type: licenseType, + is_published: isPublished, + }); + }; + + return ( +
+
+ + setTitle(e.target.value)} + placeholder="e.g., Synthwave Dream" + className="bg-slate-800 border-slate-700" + required + /> +
+ +
+ +