feat: dashboard box "Messaggi Clienti" — chat clienti in attesa di risposta
Nuovo MessagesWidget nella colonna 1/3 della dashboard: riusa getConversations() filtrando le conversazioni unread, mostra le prime 4 con anteprima e deep-link "Rispondi" a /admin/conversazioni?c=<clientId>. Pill emerald "N Nuovi" + pallino pulsante, empty state quando non c'è nulla in attesa. Stessa fonte di verità (clients.admin_last_read_at) del badge sidebar. Aggiornato DESIGN-SYSTEM.md (inventory + note Conversazioni/dashboard) e il mock design-reference/pagina-dashboard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -150,6 +150,8 @@ across all future admin pages.
|
||||
| `LeadDetail` | `src/components/admin/leads/LeadDetail.tsx` | Lead detail page (`/admin/pipeline/[id]`): bespoke header (name + inline `StatusBadge` + action bar), asymmetric `lg:grid-cols-3` layout (1/3 profile card w/ icon-chip rows + tags, 2/3 Note/Follow-up + unified timeline). |
|
||||
| `ClientProfitability` | `src/components/admin/dashboard/ClientProfitability.tsx` | Dashboard widget: valore orario reale per cliente (`getClientProfitability` → contrattualizzato ÷ ore tracciate) con badge margine (Ottimo `bg-primary/10 text-primary` / In Linea `bg-muted`). |
|
||||
| `YearSelector` | `src/components/admin/YearSelector.tsx` | Selettore anno restilizzato a pill (`rounded-full border-border bg-card shadow-card`), frecce ←/→, valore `font-mono`. Guida i dati year-scoped della dashboard via `?year=`. |
|
||||
| `ConversationsView` | `src/components/admin/conversazioni/ConversationsView.tsx` | Inbox messaggi clienti (`/admin/conversazioni`) a due pannelli: lista conversazioni filtrabile (search su nome/brand/ultimo messaggio, pallino unread) + thread attivo con bolle messaggio (admin a destra `bg-primary`, cliente a sinistra), badge entità per messaggio (Generale/Fase/Task/Deliverable) e form di risposta. Auto-mark-read all'apertura. |
|
||||
| `MessagesWidget` | `src/components/admin/dashboard/MessagesWidget.tsx` | Widget dashboard "Messaggi Clienti": chat clienti in attesa di risposta (`getConversations()` filtrato su `unread`), pill emerald "N Nuovi" + pallino pulsante, righe con anteprima e link `Rispondi →` deep-link a `/admin/conversazioni?c=<clientId>`. Empty state "Nessun messaggio in attesa ✓". |
|
||||
|
||||
**Unified timeline pattern**: activities + transcripts merged into one
|
||||
reverse-chronological "Storico delle Interazioni". Vertical connector = absolute
|
||||
@@ -171,12 +173,34 @@ layout: no in-`<main>` `PageHeader` (sidebar + shell header carry the chrome).
|
||||
`text-emerald-600 dark:text-emerald-400`.
|
||||
- **Griglia `lg:grid-cols-3`**: 2/3 col = `ForecastChart` (istogramma flussi 12
|
||||
mesi, mese prossimo evidenziato `bg-primary`) + `ClientProfitability`; 1/3 col =
|
||||
`FollowUpWidget` (count pill amber) + `OffersSoldChart` ("Offerte Più Richieste").
|
||||
`FollowUpWidget` (count pill amber) + `MessagesWidget` ("Messaggi Clienti", pill
|
||||
emerald "N Nuovi" + pallino pulsante, chat clienti in attesa di risposta) +
|
||||
`OffersSoldChart` ("Offerte Più Richieste").
|
||||
- **Year selector** interattivo (`YearSelector`) in una toolbar top-right; governa
|
||||
i KPI year-scoped + redditività. Il forecast è rolling-12-mesi (non year-scoped).
|
||||
- Widget rimossi dal legacy: chart incassi mensili, card "Da incassare"/"Clienti
|
||||
acquisiti", barre "Ore per cliente" (sostituite dalla redditività oraria).
|
||||
|
||||
### Conversazioni (inbox) notes
|
||||
|
||||
`/admin/conversazioni` è l'inbox unificata dei messaggi clienti (replica
|
||||
`design-reference/pagina-conversazioni`). Ogni conversazione è **per cliente**:
|
||||
raccoglie tutti i suoi commenti — `general` + quelli su fasi/task/deliverable —
|
||||
in un unico thread ordinato, con badge entità per messaggio.
|
||||
|
||||
- **Fonte unread**: `clients.admin_last_read_at` confrontato con l'ultimo
|
||||
messaggio autore `client`. Una conversazione è non letta se esiste un messaggio
|
||||
cliente dopo `admin_last_read_at` (o se è `NULL`). Query in
|
||||
`src/lib/conversations-queries.ts` (`getConversations`, `getConversationThread`,
|
||||
`getUnreadConversationsCount`).
|
||||
- **Badge sidebar**: voce "Conversazioni" (`AdminSidebar`) con pill emerald del
|
||||
numero di clienti con non letti (pallino verde se collapsed), alimentato da
|
||||
`getUnreadConversationsCount()` in `src/app/admin/layout.tsx`. Stessa fonte di
|
||||
verità del `MessagesWidget` in dashboard.
|
||||
- **Reply**: salvata come commento `general` sul cliente e aggiorna
|
||||
`admin_last_read_at` (mark-read). L'apertura di una conversazione fa
|
||||
auto-mark-read. Deep-link a un thread specifico via `?c=<clientId>`.
|
||||
|
||||
### Client Portal restyle notes
|
||||
|
||||
The `/client/[token]` portal was migrated to the same "Quiet Luxury" tokens
|
||||
|
||||
Reference in New Issue
Block a user