// SONARA — Order detail page (shared across artista + producer) // Reads window.SONARA_ROLE → renders different actions for each role. // Same structure, same layout, same CSS — coherence is locked by design. const OrdIcons = window.SonaraIcons; /* ────────── ORDER STATES ────────── */ const ORDER_STATES = { pending_acceptance: { label: "In attesa di conferma", color: "warning", step: 1 }, awaiting_stems: { label: "In attesa di stems", color: "warning", step: 2 }, in_progress: { label: "In lavorazione", color: "info", step: 3 }, delivered: { label: "Consegnato", color: "info", step: 4 }, revision_requested: { label: "Revisione richiesta", color: "warning", step: 4 }, completed: { label: "Completato", color: "success", step: 5 }, cancelled: { label: "Annullato", color: "neutral", step: 0 }, }; const TIMELINE_STEPS = [ { k: "acceptance", l: "Accettato", when: o => o.acceptedOn }, { k: "stems", l: "Briefing & stems", when: o => o.stemsOn }, { k: "work", l: "Lavorazione", when: o => o.workOn }, { k: "review", l: "Revisione", when: o => o.reviewOn }, { k: "done", l: "Consegnato", when: o => o.doneOn }, ]; const MOCK_ORDER = { id: "ORD-4821", kind: "Mix + Master", title: "EP \"Asfalto\" (5 brani)", state: "revision_requested", artist: { name: "Romeo Zappalà", alias: "RAZZA", init: "RZ", verified: true, age: 24, city: "Catania", orders: 12, rating: 4.7 }, producer: { name: "Nico Vega", alias: "@nicovega", init: "NV", verified: true, topRated: true, rating: 4.9, city: "Milano" }, startedOn: "8 maggio 2026", acceptedOn: "8 maggio", stemsOn: "9 maggio", workOn: "9–14 maggio", reviewOn: "in corso", deadline: "16 maggio 2026 · 18:00", deadlineHours: 22, payment: { gross: 180, fee: 21.6, net: 158.4 }, revisions: { included: 2, used: 1, extraCost: 20 }, brief: 'EP 5 tracce, già recorded. Mood notturno, 808 spaziali. Cerco un mix radio-ready ma che mantenga la profondità — riferimento Travis Scott "After Hours" + spazialità su voci stile Frank Ocean. Vorrei master loud ma con dinamica preservata sui crash.', specs: [ { l: "Tracce", v: "5" }, { l: "Mix incluso", v: "Sì · stereo" }, { l: "Master", v: "Sì · radio-ready" }, { l: "Revisioni incluse", v: "2 · usate 1" }, ], stems: [ { name: "01_intro_stems.zip", size: "412 MB", time: "9 mag · 14:22" }, { name: "02_vento_stems.zip", size: "388 MB", time: "9 mag · 14:24" }, { name: "03_asfalto_stems.zip", size: "445 MB", time: "9 mag · 14:30" }, { name: "04_pioggia_stems.zip", size: "367 MB", time: "9 mag · 14:35" }, { name: "05_outro_stems.zip", size: "390 MB", time: "9 mag · 14:42" }, ], deliverables: [ { name: "Asfalto_v1_MIX.zip", size: "186 MB", time: "13 mag · 22:10", version: "v1" }, ], revisionNote: "v1 ottimo, ma 808 troppo grossi sul brano 3 (Asfalto) → vorrei più punch, meno sub. Pulire un po' la riverbero sul ritornello di Vento.", autoApprovalDays: 7, autoApprovalLeft: "6gg 22h", chat: [ { from: "artist", t: "8 mag 19:42", text: "Ehi Nico, ti carico stems entro domani." }, { from: "producer", t: "8 mag 19:55", text: "Perfetto, accetto l'ordine. Ti aggiorno mercoledì con v1." }, { from: "producer", t: "13 mag 22:10", text: "Caricato v1. Fammi sapere cosa ne pensi." }, { from: "artist", t: "14 mag 09:31", text: "Bella v1, lasciami sentire bene poi ti dico." }, ], }; /* ────────── Small UI bits ────────── */ const ChevR = () => ; function StatusBadge({ state }) { const s = ORDER_STATES[state]; const cls = { success: "ok", warning: "warn", info: "info", neutral: "muted" }[s.color] || "muted"; return {s.label}; } function Timeline({ order }) { const cur = ORDER_STATES[order.state].step; return (
{TIMELINE_STEPS.map((step, i) => { const idx = i + 1; const done = idx < cur; const active = idx === cur; return (
{done ? : {idx}}
{step.l}
{step.when(order) || "—"}
{idx < TIMELINE_STEPS.length &&
} ); })}
); } function FilesList({ items, icon, emptyText }) { if (!items?.length) return
{emptyText}
; return (
{items.map((f, i) => (
{icon || }
{f.name}
{f.size} · {f.time}{f.version ? ` · ${f.version}` : ""}
))}
); } function ChatInline({ order, role }) { const [text, setText] = React.useState(""); return (
{order.chat.map((m, i) => { const me = (role === "artista" && m.from === "artist") || (role === "producer" && m.from === "producer"); return (
{m.text}
{m.t}
); })}
setText(e.target.value)}/>
); } /* ────────── ROLE-SPECIFIC ACTION PANELS ────────── */ function ProducerActions({ order, setOrder }) { const s = order.state; if (s === "pending_acceptance") return (
Devi rispondere entro 47h

Vuoi accettare questo ordine?

Hai letto il brief e i requisiti? Una volta accettato, il countdown della deadline parte appena l'artista carica gli stems.

); if (s === "awaiting_stems") return (
Countdown deadline in pausa

In attesa che l'artista carichi gli stems

La deadline contrattuale parte solo dal momento in cui ricevi i file. Se preferisci puoi sollecitarlo.

); if (s === "in_progress") return (
In lavorazione

Consegna la prima versione

Deadline contrattuale: 16 maggio · 18:00. Carica il deliverable quando è pronto.

); if (s === "delivered") return (
v1 consegnata · in attesa di feedback

L'artista sta valutando la tua consegna

Auto-approval tra {order.autoApprovalLeft}. Se accetta, l'escrow viene rilasciato automaticamente.

); if (s === "revision_requested") return (
Revisione richiesta · {order.revisions.included - order.revisions.used} incluse rimaste

Note dell'artista

"{order.revisionNote}"

); if (s === "completed") return (
Ordine completato · €{order.payment.net} in clearance

Lascia una recensione all'artista

La sua recensione su di te sarà visibile solo dopo che entrambi avete scritto (o dopo 14gg). Niente bias.

); return null; } function ArtistActions({ order, setOrder }) { const s = order.state; if (s === "pending_acceptance") return (
In attesa del producer · 47h rimasti

Nico sta valutando il tuo brief

Se rifiuta o non risponde entro 48h, riceverai un refund automatico sul wallet. I tuoi €180 sono al sicuro in escrow.

); if (s === "awaiting_stems") return (
Manca solo questo per iniziare

Carica gli stems

Il producer non può partire finché non riceve i file sorgente. Stai bloccando il tuo stesso ordine. Soft-deadline: entro 7gg o l'ordine viene cancellato.

); if (s === "in_progress") return (
Nico è al lavoro

Aspetta la prima versione

La consegna è attesa entro 16 maggio · 18:00. Ti notifichiamo via push + email appena è pronta.

); if (s === "delivered") return (
Auto-approval tra {order.autoApprovalLeft}

Hai ricevuto la v1 — cosa ne pensi?

Ascoltala con calma. Se non rispondi entro {order.autoApprovalDays}gg, l'ordine si chiude in automatico e l'escrow va a Nico.

); if (s === "revision_requested") return (
Revisione in corso

Nico sta lavorando alle tue note

"{order.revisionNote}"

Ti aspettiamo entro 2-3 giorni. Una revisione su due usate.

); if (s === "completed") return (
Ordine completato · file scaricabili indefinitamente

Lascia una recensione

Verrà visibile sul profilo di Nico solo dopo che anche lui ne ha scritto una su di te (o dopo 14gg).

); return null; } /* ────────── MAIN PAGE ────────── */ function OrdinePage() { const role = window.SONARA_ROLE || "producer"; const [order, setOrder] = React.useState(MOCK_ORDER); const back = role === "artista" ? "Progetti.html" : "Ordini.html"; return (
Tutti gli ordini {/* HEADER */}
{order.kind} {order.id}

{order.title}

{role === "producer" ? order.artist.init : order.producer.init} {role === "producer" ? order.artist.name : order.producer.name} {role === "producer" && order.artist.verified && } · {role === "producer" ? order.artist.alias : order.producer.alias} · Iniziato il {order.startedOn}
Deadline
Tra {order.deadlineHours}h
{order.deadline}
{role === "producer" ? (
Netto a te
€{order.payment.net.toLocaleString("it", { minimumFractionDigits: 2 })}
In escrow · si libera alla consegna
) : (
Hai pagato
€{order.payment.gross}
In escrow · si libera all'approvazione
)}
{/* TIMELINE */} {/* ROLE ACTION CARD */}
{role === "producer" ? : }
{/* MAIN GRID */}

Brief dell'artista

{order.brief}

{order.specs.map((s, i) => (
{s.l}
{s.v}
))}

Stems ricevuti dall'artista {order.stems.length}

{role === "producer" && ( )}

Deliverable consegnati dal producer {order.deliverables.length}

{role === "artista" && order.deliverables.length > 0 && ( )}

Chat dell'ordine

); } window.OrdinePage = OrdinePage; window.SONARA_ORDER_STATES = ORDER_STATES; window.SONARA_MOCK_ORDER = MOCK_ORDER;