fix(conversazioni): il menu dei tag mostra una riga per persona, non per alias

Con un cliente «Gian Luca Caruso / Caruso Speaker» il menu proponeva tre voci
per un destinatario solo. Non era un difetto di resa: al menu era stata passata
la stessa lista che il parser usa per RICONOSCERE un tag rileggendo il testo.

Sono due domande diverse, e il codice le aveva confuse:
  - come lo si puo' scrivere -> tutti gli alias, invisibili, solo in lettura
  - chi si puo' scegliere    -> una riga per destinatario

`MentionTarget` le separa: `label` per il menu, `aliases` per la rilettura.
Scrivere «@Gian» a mano continua a valere come tag e a far partire la mail --
cambia solo cosa viene offerto, non cosa viene accettato.

Il filtro del menu ora passa da `normalizeForSearch`, la stessa
normalizzazione del parser: con un toLowerCase() a parte, digitare «nicolo»
non avrebbe trovato «Nicolò» nel menu mentre nel messaggio sarebbe stato
riconosciuto -- due regole per la stessa domanda, e la seconda si scopre solo
quando la mail non parte.

Il difetto scalava peggio del valore: con tre contatti per cliente sarebbero
diventate nove righe. `mentionTargets()` ritorna gia' un array per questo, ma
il tag per singola persona resta impossibile finche' `client_emails` ha gli
indirizzi e non i nomi: serve una migration, ed e' un lavoro a se'.

Verificato: build e lint puliti, 23 test su parser e menu. Mai visto a schermo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 11:22:38 +02:00
parent 614eb00040
commit 9ce6f02ee4
5 changed files with 116 additions and 26 deletions
+2 -1
View File
@@ -40,7 +40,7 @@ Phase 27 resta a metà — schema e fonti in prod, resto da scrivere.
| Rifiniture — tassonomie, tab pagamenti, riordino task | ✅ in prod 2026-08-20 (`0019`) |
| Portale cliente — stepper compatto/full-width, card offerta | ✅ in prod 2026-08-21 (`0020`); override provato su Caruso Speaker |
| Chat — canali, modifica messaggi, firma admin | ✅ in prod 2026-08-21 (`0021`, `0022`); **mai provata a mano**; manca l'attribuzione |
| Conversazioni — scrivere per primo, menzioni `@Nome`, mail sul tag | ✅ pushata 2026-09-01 (`41530b5`), nessuna migration. Build + lint puliti, parser provato su 9 casi; **mai vista a schermo, nessuna mail di tag mai partita davvero** |
| Conversazioni — scrivere per primo, menzioni `@Nome`, mail sul tag | ✅ pushata 2026-09-01 (`41530b5`), nessuna migration. Menu dei tag corretto lo stesso giorno: mostrava **una riga per alias** invece che per persona. Build + lint puliti, 23 test sul parser e sul menu; **nessuna mail di tag mai partita davvero** |
| Portale — stati task (forma, pill, legenda, «Cancellata») + date dei pagamenti | ✅ in prod 2026-08-22 (`2e9bd2a`, `8b54f48`, `fe76789`, migration `0023`); **mai visto a schermo**, nessuna `due_date` ancora inserita |
| D — Whop → audit | ⏸️ dipende dal motore v2.5 |
@@ -70,6 +70,7 @@ Passo per passo in `STATUS.md` e in `.claude/plans/v2.5-audit-motore.md`.
Log completo in `PROJECT.md`. Vive per il lavoro corrente:
- **[2026-09-01] Una lista che serve a leggere non è una lista da offrire in scrittura** — il menu dei tag mostrava tre voci (nome, brand, nome di battesimo) per una persona sola, perché gli era stata passata la stessa lista che il parser usa per **riconoscere** un tag nel testo. Sono due domande diverse: *come lo si può scrivere* (tutti gli alias, invisibili) e *chi si può scegliere* (una riga per destinatario). Ora `MentionTarget` le tiene separate — `label` per il menu, `aliases` per la rilettura — e il filtro passa da `normalizeForSearch`, la stessa normalizzazione del parser: con un `toLowerCase()` a parte, digitare «nicolo» non troverebbe «Nicolò» nel menu mentre nel messaggio verrebbe riconosciuto. Il difetto scalava peggio del valore: con tre contatti sarebbero state nove righe.
- **[2026-09-01] L'accesso a Gitea si recupera dalla sua CLI, non dal web** — il push rispondeva 403 (la credenziale nel portachiavi leggeva ma non scriveva) e l'account web non era piu' accessibile, quindi la via del browser era chiusa in partenza. Si rientra da dentro il container: `docker exec -u git gitea-tgw04ws48sogkso84oogwckk gitea admin user change-password` per la password e `... generate-access-token --scopes write:repository --raw` per il token del push. Il token va messo nel portachiavi con `git credential approve`, **non** nell'URL del remote: li' finirebbe in chiaro dentro `.git/config`. Da ricordare perche' senza push non esiste deploy — Coolify parte da `main` e basta.
- **[2026-08-22] Un task cancellato esce dai denominatori, non dalla lista** — resta visibile barrato (il cliente ha letto quella voce e deve capire che fine ha fatto) ma non conta, via un solo `countsTowardProgress()` in `task-status.ts`: contarlo terrebbe la fase sotto il 100% per sempre, contarlo come fatto racconterebbe una consegna mai avvenuta. Se in una fase restano solo cancellati torna «Da iniziare»: degenere, ma «Completata» mentirebbe.
- **[2026-08-22] Le date dei pagamenti sì, gli importi per riga no** — LOCKED #2 parla di cifre, non di date. Salvate a **mezzogiorno UTC** (a mezzanotte il giorno civile a Roma è già quello dopo) e contate sui giorni civili a Roma in `src/lib/payment-dates.ts`, lo stesso modulo del futuro promemoria email: mail e portale non devono contraddirsi su quanti giorni mancano.