// Progetti — command center for the artist // 3 sub-tabs: Collaborazioni / Richieste open / Acquisti beat (UC-A6, UC-A3, UC-A1 storico) const ProgIcons = window.SonaraIcons; const { useState: useStateProg, useMemo: useMemoProg } = React; // ---------- mock data ---------- const COLLAB_DATA = [ { id: 1, title: "Mix · 'Notte Lunga'", type: "Mix", typeIcon: "mix", counterpart: "Marco Vitale", counterpartInit: "MV", counterpartGenre: "Trap", art: "art-a", verified: true, status: "in_review", statusLabel: "Da revisionare", urgent: false, deadline: "2g", deadlineSub: "auto-approval", price: 80, lastActivity: "Producer ha consegnato v2 · 1 revisione rimasta", progress: 80, started: "12 mar", }, { id: 2, title: "Beat custom · 'Trap dark'", type: "Custom production", typeIcon: "beat", counterpart: "Yoshi Beats", counterpartInit: "Y", counterpartGenre: "Trap", art: "art-b", verified: true, status: "in_progress", statusLabel: "In lavorazione", urgent: false, deadline: "5g", deadlineSub: "deadline", price: 150, lastActivity: "Stems consegnati · revisione 0 di 2", progress: 45, started: "8 mar", }, { id: 3, title: "Master · 'Skyline EP'", type: "Master", typeIcon: "master", counterpart: "Studio Riva", counterpartInit: "SR", counterpartGenre: "R&B", art: "art-c", verified: false, status: "in_review", statusLabel: "Scade oggi", urgent: true, deadline: "6h", deadlineSub: "scadenza", price: 220, lastActivity: "Producer chiede approvazione finale", progress: 95, started: "5 mar", }, { id: 4, title: "Vocal production · 'Onde'", type: "Vocal prod", typeIcon: "vocal", counterpart: "Diego K.", counterpartInit: "DK", counterpartGenre: "Pop", art: "art-d", verified: true, status: "briefing", statusLabel: "Briefing", urgent: false, deadline: "12g", deadlineSub: "deadline", price: 60, lastActivity: "Stems da caricare · richiesto entro 18 mar", progress: 15, started: "13 mar", }, ]; const COLLAB_CLOSED = [ { id: 5, title: "Mix + Master · 'Verde'", type: "Mix + Master", typeIcon: "mix", counterpart: "Studio Riva", counterpartInit: "SR", counterpartGenre: "R&B", art: "art-c", verified: false, status: "completed", statusLabel: "Completato", urgent: false, deadline: null, deadlineSub: null, price: 180, lastActivity: "Approvato · ★★★★★ recensione lasciata", progress: 100, started: "12 feb", closed: "20 feb", }, { id: 6, title: "Beat custom · 'Sonar'", type: "Custom production", typeIcon: "beat", counterpart: "Marco Vitale", counterpartInit: "MV", counterpartGenre: "Trap", art: "art-a", verified: true, status: "completed", statusLabel: "Completato", urgent: false, deadline: null, deadlineSub: null, price: 200, lastActivity: "Approvato · ★★★★★ recensione lasciata", progress: 100, started: "1 feb", closed: "9 feb", }, { id: 7, title: "Master · 'Demo 2'", type: "Master", typeIcon: "master", counterpart: "Vale Frey", counterpartInit: "VF", counterpartGenre: "Pop", art: "art-e", verified: false, status: "cancelled", statusLabel: "Annullato", urgent: false, deadline: null, deadlineSub: null, price: 50, lastActivity: "Annullato per accordo · rimborso emesso", progress: 30, started: "20 gen", closed: "23 gen", }, ]; const RICHIESTE_DATA = [ { id: 1, title: "Cerco beat trap dark · 140 BPM", type: "Beat", typeChip: "beat", status: "open", statusLabel: "Aperta", offers: 8, newOffers: 1, budget: "€80–150", deadline: "22g", deadlineSub: "rimasti", description: "Cerco un beat dark per nuovo singolo, atmosfera notturna, 808 grossi tipo Sfera Ebbasta ultima produzione…", posted: "12 mar", views: 187, }, { id: 2, title: "Mix per singolo R&B notturno", type: "Mix", typeChip: "mix", status: "negotiation", statusLabel: "In trattativa", offers: 5, newOffers: 0, budget: "€60–100", deadline: "8g", deadlineSub: "rimasti", description: "Voce già registrata, stems puliti, cerco mix che valorizzi il low-end e mantenga l'aria…", posted: "5 mar", views: 92, }, { id: 3, title: "Producer per EP 5 tracce", type: "Custom production", typeChip: "custom", status: "open", statusLabel: "Aperta", offers: 3, newOffers: 2, budget: "Decideremo insieme", deadline: "28g", deadlineSub: "rimasti", description: "Cerco producer di fiducia per progetto a lungo termine, EP 5 tracce, scadenza estate…", posted: "9 mar", views: 64, }, ]; const RICHIESTE_CLOSED = [ { id: 4, title: "Cerco master per album", type: "Master", typeChip: "master", status: "accepted", statusLabel: "Accettata", offers: 12, newOffers: 0, budget: "€200–400", linkedProject: 6, description: "Album 9 tracce, già mixato. Cerco mastering coeso e pronto per streaming…", posted: "22 feb", closed: "1 mar", }, { id: 5, title: "Beat afro per estate", type: "Beat", typeChip: "beat", status: "expired", statusLabel: "Scaduta", offers: 0, newOffers: 0, budget: "€40–80", description: "Beat afro estivo, vibe spiaggia, melodico…", posted: "10 gen", closed: "9 feb", }, ]; const ACQUISTI_DATA = [ { id: 1, title: "Sognando blue moon", producer: "Yoshi Beats", producerInit: "Y", art: "art-a", license: "Non-esclusiva", price: 49, bpm: 140, key: "A min", genre: "Trap", purchased: "14 mar 2025", verified: true, }, { id: 2, title: "Notte di stelle", producer: "Marco Vitale", producerInit: "MV", art: "art-b", license: "Non-esclusiva", price: 35, bpm: 95, key: "F# min", genre: "R&B", purchased: "8 mar 2025", verified: true, }, { id: 3, title: "Spirale", producer: "Diego K.", producerInit: "DK", art: "art-c", license: "Esclusiva", price: 220, bpm: 128, key: "G min", genre: "Drill", purchased: "1 mar 2025", verified: true, }, { id: 4, title: "Ombre", producer: "Studio Riva", producerInit: "SR", art: "art-d", license: "Non-esclusiva", price: 28, bpm: 110, key: "C maj", genre: "Pop", purchased: "22 feb 2025", verified: false, }, { id: 5, title: "Mare scuro", producer: "Vale Frey", producerInit: "VF", art: "art-e", license: "Non-esclusiva", price: 40, bpm: 92, key: "D min", genre: "Afro", purchased: "12 feb 2025", verified: false, }, { id: 6, title: "Codice nero", producer: "Yoshi Beats", producerInit: "Y", art: "art-f", license: "Non-esclusiva", price: 49, bpm: 145, key: "E min", genre: "Drill", purchased: "3 feb 2025", verified: true, }, ]; // ---------- main page ---------- function ProgettiPage() { const [tab, setTab] = useStateProg(() => { const h = (window.location.hash || "").replace("#", ""); if (h === "richieste") return "richieste"; if (h === "acquisti") return "acquisti"; return "collab"; }); const tabs = [ ["collab", "Collaborazioni", COLLAB_DATA.length, true], ["richieste", "Richieste open", RICHIESTE_DATA.length, RICHIESTE_DATA.some(r => r.newOffers > 0)], ["acquisti", "Acquisti beat", ACQUISTI_DATA.length, false], ]; return (
Command center

Progetti

12 completati
€1.840 spesi lifetime
4,7 rating dato (8 recensioni)
{tab === "collab" && } {tab === "richieste" && } {tab === "acquisti" && }
); } // ---------- Collaborazioni ---------- function CollaborazioniTab() { const [viewMode, setViewMode] = useStateProg("active"); const [sort, setSort] = useStateProg("deadline"); const data = viewMode === "active" ? COLLAB_DATA : COLLAB_CLOSED; const sorted = useMemoProg(() => { const list = [...data]; if (sort === "deadline") return list.sort((a, b) => a.progress - b.progress); if (sort === "recent") return list.sort((a, b) => b.id - a.id); if (sort === "price") return list.sort((a, b) => b.price - a.price); return list; }, [data, sort]); return (
{sorted.map(p => )}
); } function CollabCard({ p, closed }) { return (
{p.type}

{p.title}

{p.statusLabel}
€{p.price}
{p.counterpartInit} {p.counterpart} {p.verified && } {p.counterpartGenre}
{p.lastActivity}
{p.deadline && (
{p.deadline} {p.deadlineSub}
)} {closed && (
Chiuso {p.closed}
)} Apri
); } // ---------- Richieste open ---------- function RichiesteTab() { const [viewMode, setViewMode] = useStateProg("active"); const data = viewMode === "active" ? RICHIESTE_DATA : RICHIESTE_CLOSED; const slotsLeft = 3 - RICHIESTE_DATA.length; return (
Hai {RICHIESTE_DATA.length} richieste attive · {slotsLeft >= 0 ? slotsLeft : 0} slot{slotsLeft !== 1 ? "" : ""} disponibil{slotsLeft !== 1 ? "i" : "e"}
Le richieste open invitano i producer a fare offerte a te. Max 3 attive contemporaneamente.
{slotsLeft <= 0 ? ( ) : ( Pubblica richiesta )}
{data.map(r => )}
); } function RichiestaCard({ r }) { return (
{r.type} {r.statusLabel}

{r.title}

{r.description}

{r.budget} {r.deadline && {r.deadline} {r.deadlineSub}} {r.posted && Pubblicata {r.posted}} {r.views !== undefined && {r.views} viste}
{(r.status === "open" || r.status === "negotiation") && (
{r.offers} {r.offers === 1 ? "offerta ricevuta" : "offerte ricevute"} {r.newOffers > 0 && +{r.newOffers} nuova}
Vedi offerte ({r.offers})
)} {r.status === "accepted" && (
Accettata · convertita in progetto
Vai al progetto
)} {r.status === "expired" && (
Scaduta senza offerte
Ripubblica con modifiche
)}
); } // ---------- Acquisti beat ---------- function AcquistiTab() { const [filter, setFilter] = useStateProg("all"); const [sort, setSort] = useStateProg("recent"); const filtered = useMemoProg(() => { let list = [...ACQUISTI_DATA]; if (filter === "exclusive") list = list.filter(a => a.license === "Esclusiva"); if (filter === "non-exclusive") list = list.filter(a => a.license === "Non-esclusiva"); if (sort === "price") list.sort((a, b) => b.price - a.price); if (sort === "alpha") list.sort((a, b) => a.title.localeCompare(b.title)); return list; }, [filter, sort]); const totalSpent = ACQUISTI_DATA.reduce((s, a) => s + a.price, 0); return (
{ACQUISTI_DATA.length} beat acquistati
€{totalSpent} spesi in beat
1 esclusiva
{filtered.map(a => )}
); } function AcquistoCard({ a }) { return (
{a.license === "Esclusiva" && Esclusiva}

{a.title}

{a.producerInit} {a.producer} {a.verified && }
{a.bpm} BPM {a.key} {a.genre}
Pagato €{a.price} {a.purchased}
); } window.ProgettiPage = ProgettiPage;