feat(portale): barra full-width, card offerta senza accordion, valore override

Barra di avanzamento a tutta larghezza (via il max-w-[1200px]).

Card offerta: rimosso l'accordion "Cosa è compreso". La lista servizi non
arriva più al client — client-view.ts legge dai servizi i soli prezzi — e
OffersSection perde il suo unico useState, quindi anche il "use client".

"Valore incluso" diventa "Valore dell'offerta" e accetta un override manuale
(migration 0020, project_offers.offer_value_override). Prima era sempre la
somma dei prezzi di catalogo del tier: in produzione mostrava €20.250 su
offerte vendute a 7.000 e 5.500. NULL torna al calcolo, 0 nasconde la riga.
Si gestisce dal tab Offerte del progetto, che affianca la cifra calcolata
per far vedere cosa si sta sostituendo.

La somma calcolata vive ora in src/lib/offer-value.ts, letta sia dal portale
sia dall'admin: duplicarla avrebbe fatto divergere le due viste.

"Prezzo finale" diventa "Investimento finale" (il ricorrente resta "Canone
mensile").

Migration 0020 applicata a prod prima del push. Override tutti NULL, quindi
il comportamento resta invariato finché non se ne imposta uno.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 07:54:55 +02:00
parent 7e58031528
commit 44be190631
12 changed files with 270 additions and 133 deletions
+28 -1
View File
@@ -1,6 +1,6 @@
# ClientHub (IAMCAVALLI) — Status
_Ultimo aggiornamento: 2026-08-20_
_Ultimo aggiornamento: 2026-08-21_
Questo è **l'unico documento narrativo** del progetto: a che punto siamo, cosa manca,
cosa abbiamo imparato. `.planning/STATE.md` è il digest che leggono i comandi
@@ -94,6 +94,33 @@ interazioni: la matita di rinomina con il dialog di conferma, e il drag di un ta
di proposito: **l'unico DB raggiungibile in locale è la produzione**, e una prova di
rinomina riscriverebbe titoli di fasi veri.
**In produzione dal 2026-08-21** (migration `0020`) — portale cliente:
- **Barra di avanzamento compatta e a tutta larghezza.** Rubava ~147px di altezza sopra
la piega per dire una cosa sola. Ora "Step N" e lo stato stanno sulla stessa riga, il
titolo della fase sotto — due righe invece di tre — e il padding scende da `py-8` a
`py-3`: ~88px. Il mock sta in `design-reference/Client-Portal-Progress-Bar`, scritto in
`slate-*` grezzi come tutti i mock: tradotto a token, non copiato.
- **Card offerta senza accordion.** Via "Cosa è compreso": la lista dei servizi non serve
al cliente e non viene più nemmeno **proiettata**`client-view.ts` ora legge dai
servizi i soli prezzi. `OffersSection` ha perso il suo unico `useState` e con esso il
`"use client"`.
- **"Valore incluso" → "Valore dell'offerta", con override.** Era sempre la somma dei
prezzi di catalogo dei servizi del tier: un artefatto che si muove quando si muove il
listino. In produzione produceva **€20.250 su offerte vendute a 7.000 e 5.500** — al
cliente sembrava uno sconto del 70%. Ora `project_offers.offer_value_override` vince
sulla somma; NULL torna al calcolo, `0` nasconde la riga. Si gestisce dal tab Offerte
del progetto, che mostra accanto la cifra calcolata per far vedere cosa si sta
sostituendo. La somma vive in `src/lib/offer-value.ts`, letta **sia** dal portale sia
dall'admin: duplicarla avrebbe fatto divergere le due viste.
- **"Prezzo finale" → "Investimento finale"** (solo una tantum; il ricorrente resta
"Canone mensile").
⚠️ **Scritto e buildato, non reso a runtime.** Build verde, migration `0020` applicata e
verificata in prod, override tutti NULL quindi comportamento invariato finché non si
tocca. La prova a runtime **non è stata possibile**: la password del DB in `.env.local` è
ormai stale e l'estrazione di quella viva è stata bloccata. Va guardato in prod.
Cosa manca, e perché:
- **[BLOCCANTE] TidyCal.** Non ha webhook — è scritto nella loro FAQ, la strada