v0.1 — Dashboard Roles: PR/Promoter System

Branch: v0.1/feat/dashboard-roles Data: 24/03/2026 Tipo: feat (multi-ruolo, dashboard vendor, dashboard admin, nuovo ruolo PR)


Contesto

Il sistema richiede 4 ruoli distinti nell’area gestionale:

RuoloChi èCosa può fare
AdminNoi (proprietari Flow)Tutto — gestione globale, approvazioni, statistiche complete
ModeratorPersone selezionate da noiModerazione contenuti con livelli configurabili
VendorGestori/proprietari di localiGestire il proprio locale, eventi, campagne, statistiche
PR / PromoterPromoter approvatiCreare e gestire eventi per i locali a cui sono assegnati

Flusso di approvazione PR (dual-path)

Vendor propone un PR (email)
    → status: pending
    → Admin vede la richiesta in /admin/staff
    → Admin approva → status: active
    → PR accede a /pr/dashboard con il locale assegnato

Admin assegna direttamente
    → status: active (salta il pending)
    → PR ha accesso immediato

Modifiche apportate

DB — Migrazione Supabase

File: supabase/migrations/20260324000002_venue_pr_role_policies.sql

Nuova colonna venue_prs.invited_by_role

ALTER TABLE public.venue_prs
  ADD COLUMN IF NOT EXISTS invited_by_role TEXT
    CHECK (invited_by_role IN ('admin', 'vendor'))
    DEFAULT 'vendor';

Permette di distinguere se l’invito è partito da un vendor manager o da un admin (utile per audit e per la UX del pannello admin).

Nuove policy RLS

PolicySoggettoOperazioniCondizione
venue_prs_admin_allAdminALLrole IN ('admin', 'ADMIN')
venue_prs_vendor_readVendorSELECTOwner del venue
venue_prs_vendor_insert_pendingVendorINSERTSolo status='pending' + owner del venue
venue_prs_vendor_delete_ownVendorDELETESolo inviti propri + pending
venue_prs_pr_read_ownPRSELECTProprie associazioni

Nota di sicurezza: i vendor non possono auto-approvare. L’INSERT è vincolato a status='pending'. Solo gli admin possono portare a status='active'.


components/dashboard/AdminSidebar.tsx

Aggiunta voce “Staff Locali”/admin/staff (icona UserGroupIcon).

components/dashboard/VendorSidebar.tsx

Aggiunta voce “Collaboratori PR”/vendor/staff (icona UserGroupIcon).

components/dashboard/PRSidebar.tsx (nuovo)

Sidebar per il ruolo PR con:

  • Panoramica → /pr/dashboard
  • I miei eventi → /pr/events
  • Impostazioni → /pr/settings

app/admin/(dashboard)/staff/page.tsx (nuovo)

Pagina globale di gestione staff per gli admin.

Funzionalità:

  • Tabella di tutti i venue_prs con filtri per status (pending/active/paused/terminated)
  • Badge numerale sul filtro “In attesa” per visibilità immediata
  • Ricerca per nome PR, email, username, nome venue
  • Azioni per stato:
    • pendingApprova (→ active) | Rifiuta (→ terminated)
    • activePausa (→ paused) | Termina (→ terminated)
    • pausedRiattiva (→ active)
  • Form Assegnazione diretta (toggle): admin inserisce email + seleziona locale → status='active' senza passare da pending, invited_by_role='admin'

app/vendor/(dashboard)/staff/page.tsx (nuovo)

Pagina gestione collaboratori per i vendor manager.

Funzionalità:

  • Banner informativo sul flusso di approvazione
  • Form invito PR per email (ricerca in profiles per email, verifica ruolo compatibile)
  • Sezione “In attesa di approvazione” — con pulsante annulla invito
  • Sezione “PR attivi” — lista con avatar, nome, email
  • Sezione “Terminati/In pausa” — read-only

Limitazioni intenzionali:

  • Il vendor non può approvare — può solo proporre e annullare inviti pending propri
  • Il vendor non vede gli inviti fatti da altri vendor o da admin

app/pr/(dashboard)/ (nuovo — route group completo)

Nuovo dashboard per il ruolo PR.

layout.tsx

Usa DashboardLayout + PRSidebar.

dashboard/page.tsx

Panoramica: lista dei locali attivi a cui il PR è assegnato (da venue_prs con status='active'), con link rapido a /pr/events.

events/page.tsx

Gestione eventi:

  • Selector locale (se assegnato a più venue)
  • Lista eventi creati dal PR per il locale selezionato (filtrati per organizer_id = current_user)
  • Form creazione evento (inline) con validazione ticket_external_url
  • Edit inline per ogni evento

Nota: il PR vede e modifica solo gli eventi che ha creato lui. Non ha accesso agli eventi creati dal vendor.


Flusso completo end-to-end

1. Admin crea utente con role='pr' (o utente esistente)

2a. Vendor propone:
    Vendor → /vendor/staff → "Invita" (email)
    → INSERT venue_prs(status='pending', invited_by_role='vendor')
    → Admin vede badge in /admin/staff
    → Admin clicca "Approva"
    → UPDATE venue_prs SET status='active'

2b. Admin assegna direttamente:
    Admin → /admin/staff → "Assegna direttamente" (email + venue)
    → INSERT venue_prs(status='active', invited_by_role='admin')

3. PR accede a /pr/dashboard
   → Vede i locali assegnati
   → Va su /pr/events
   → Crea/modifica eventi per il locale

File modificati / creati

  • supabase/migrations/20260324000002_venue_pr_role_policies.sql
  • components/dashboard/AdminSidebar.tsx
  • components/dashboard/VendorSidebar.tsx
  • components/dashboard/PRSidebar.tsx (nuovo)
  • app/admin/(dashboard)/staff/page.tsx (nuovo)
  • app/vendor/(dashboard)/staff/page.tsx (nuovo)
  • app/pr/(dashboard)/layout.tsx (nuovo)
  • app/pr/(dashboard)/dashboard/page.tsx (nuovo)
  • app/pr/(dashboard)/events/page.tsx (nuovo)