diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index b94e869..57b0d6f 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -20,7 +20,7 @@ schema in [docs/DATABASE.md](docs/DATABASE.md), le procedure in `foto_path`: il codice che non la legge più (1.2.2) va rilasciato. - **Su `develop`, non ancora rilasciato:** obiettivi cliccabili con card di dettaglio, presenze del mese calcolate sui convocati, obiettivi «Presenze collettive» e «evento di squadra al mese» (ora dell'evento), - tessera CSI tolta dalla dashboard (DD-048), notifica di compleanno (DD-047, migration `m31`). Dettaglio in + tessera CSI tolta dalla dashboard (DD-048), avvisi in Home ridisegnati e caratteri più grandi in tutta l'app (DD-049), notifica di compleanno (DD-047, migration `m31`). Dettaglio in [docs/CHANGELOG.md](docs/CHANGELOG.md). - **Worker delle notifiche** (`mailer/`): in funzione su un Raspberry Pi con Docker dal 29/09/2026 ([docs/WORKER_EMAIL.md](docs/WORKER_EMAIL.md)). Il codice con l'interruttore «Email» in Profilo diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 614a699..febec84 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -88,6 +88,10 @@ Componenti condivisi in `src/components/crapp/` (`ui-bits.tsx` per `Card`, `Page `Section`, `StatTile`; `Avviso.tsx` per gli avvisi colorati in Home; i drawer di dettaglio `BadgeDrawer` e `ObiettivoDrawer`), animazioni in `src/components/motion/`. Mobile-first (DD-005): poche schermate, pochi click. +**Caratteri** (DD-049): niente testo sotto i 13 px, tranne la navigazione a pillola e i badge +da 10-11 px. Scala in uso: 13 px note, 15 px corpo, 16 px titoli di card; si usano le misure +fisse `text-[13px]`…`text-[16px]`, non `text-xs` e `text-sm`. + In `src/components/ui/` restano solo le due primitive shadcn davvero usate, `drawer` (vaul) e `sonner`: le altre 43 non erano importate da nessuna parte (DD-021). Il resto dell'interfaccia è composto con Tailwind e la primitiva `Card`, che è l'unica definizione di raggio, sfondo e diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2c855e6..573596c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -25,6 +25,9 @@ versioni `0.y.z` erano pre-release. ### Modificato +- **Caratteri più grandi in tutta l'app** — ogni testo sotto i 16 px sale di un passo (12→13, 14→15, ecc.), nelle + card, negli elenchi, nelle statistiche e nei drawer. Restano uguali le barre a pillola dei menu (navigazione in + basso e sottosezioni) e i badge minuscoli. Solo aspetto, nessuna migration (DD-049). - **Avvisi in Home più leggibili** — certificati e turno palloni usano lo stesso componente (`Avviso`): icona propria per ogni caso (non solo il colore), titolo e testo più grandi, elenchi di persone in righe con il dettaglio a destra e il conteggio, freccia dove la card porta ai documenti, comparsa graduale. Solo aspetto: testi e regole diff --git a/docs/decisions/DD-049.md b/docs/decisions/DD-049.md new file mode 100644 index 0000000..3401e11 --- /dev/null +++ b/docs/decisions/DD-049.md @@ -0,0 +1,53 @@ +# DD-049 — Caratteri più grandi in tutta l'app + +**Data:** 6 ottobre 2026 +**Stato:** Accettata (solo interfaccia, nessuna migration) + +**Contesto** +L'app si usa soprattutto dal telefono, anche da chi non è pratico. Molti testi erano a 12 px +(`text-xs`) e 14 px (`text-sm`): faticosi da leggere, soprattutto in Home, dove le card di +avvisi, eventi e statistiche hanno quasi solo testo piccolo. + +**Decisione** + +1. Tutti i testi sotto i 16 px salgono di **un passo**, in ogni pagina: + + | Prima | Dopo | + | ----------------- | ----- | + | `text-xs` (12 px) | 13 px | + | 13 px | 14 px | + | 14 px | 15 px | + | `text-sm` (14 px) | 15 px | + | 15 px | 16 px | + + Si usano le misure fisse `text-[13px]`, `text-[14px]`, `text-[15px]`, `text-[16px]`, già + presenti nel codice. `text-base` (16 px) e i titoli grandi non cambiano. + +2. **Restano invariati** i testi delle barre a pillola dei menu, cioè la navigazione in basso + (`BottomNav`) e le sottosezioni (`BarraSottosezioni`), e i testi minuscoli da 10 e 11 px + (conteggio sulla campanella). +3. **Avvisi in Home** (certificati e turno palloni): un solo componente, `Avviso` + (`src/components/crapp/Avviso.tsx`), con titolo da 18 px, testi da 15 px, icona propria per + ogni caso (il colore non è l'unico segnale), elenchi in righe con il dettaglio a destra. Il + turno palloni ha in più la pillola «Oggi» o «In arrivo» e i messaggi in riquadri. Cambia solo + l'aspetto, non i testi né le regole su quando un avviso compare. + +**Alternative scartate** + +- Alzare la dimensione base del browser (`rem`) → scartata: ingrandirebbe anche icone, spazi e + barre a pillola, e ogni schermata andrebbe ricontrollata. +- Ingrandire solo la Home → scartata: le altre pagine avevano gli stessi testi piccoli. +- Salire di due passi → scartata: in contenitori stretti (badge, tessere, righe di classifica) + il testo andrebbe a capo o verrebbe troncato. + +**Conseguenze** + +- Un testo che stava stretto può andare a capo o troncarsi: non c'è un controllo visivo + automatico, va guardato sul telefono. Chi vede un punto rotto segnala la schermata. +- Per un testo nuovo, la scala di partenza è 13 px per le note, 15 px per il corpo, 16 px per i + titoli di card. +- Le card degli eventi sono condivise tra Home e Calendario: crescono insieme. + +**Riesame** +Se dopo l'uso sul telefono compaiono testi troncati in più punti, tornare a un passo solo nei +contenitori stretti, senza toccare il resto. diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 5fa5128..9166d4b 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -86,6 +86,7 @@ Una decisione sostituita non si cancella: si cambia il suo **Stato** e si rimand | [DD-038](DD-038.md) | Tre canali per ogni notifica | | [DD-039](DD-039.md) | Niente promemoria all'allenatore | | [DD-040](DD-040.md) | Palloni e solleciti automatici | +| [DD-049](DD-049.md) | Caratteri più grandi in tutta l'app | | [DD-048](DD-048.md) | Via la tessera dalla dashboard | | [DD-047](DD-047.md) | Notifica di compleanno | | [DD-046](DD-046.md) | Avviso certificati mancanti | diff --git a/docs/modules/allenatore.md b/docs/modules/allenatore.md index c885cd9..2ceeae3 100644 --- a/docs/modules/allenatore.md +++ b/docs/modules/allenatore.md @@ -97,7 +97,7 @@ nessuna schermata: | Dove | Cosa si nasconde all'allenatore | | ----------------------------------- | -------------------------------------------------------------------------------- | | `/squadra` → Stats | il criterio di ordinamento «Cacche» (`cacchePartita`) | -| `/squadra` → Rosa, scheda giocatore | la riga «Cacche/partita 💩» | +| `/squadra` → Rosa, scheda giocatore | la riga «Cacche 💩» | | `/partita/$id` | la sezione «Badge votati dai compagni» e il sondaggio cacche (`SondaggioCacche`) | | push «Sondaggio pre-partita aperto» | non parte verso i dispositivi degli allenatori (`apri-sondaggio.ts`) | | `/profilo`, `/squadra` | le tab Badge (già escluse sopra) | diff --git a/docs/modules/squadra.md b/docs/modules/squadra.md index 65cf7c6..ffbb90f 100644 --- a/docs/modules/squadra.md +++ b/docs/modules/squadra.md @@ -48,7 +48,7 @@ gli allenatori (`tipo = 'allenatore'`, DD-034): hanno uno slot ma non giocano. Nella tab Rosa gli allenatori attivi compaiono in cima, con foto, nome e la dicitura «Allenatore» dove i giocatori hanno il ruolo in campo (`ruoloVisibile()`); niente numero, statistiche né badge, e niente posto nella tab Stats. Chi usa l'app da allenatore vede solo -Rosa e Stats, senza badge e senza cacche (criterio «Cacche» e riga «Cacche/partita»). La +Rosa e Stats, senza badge e senza cacche (criterio «Cacche» e riga «Cacche»). La specifica completa sta in [allenatore.md](allenatore.md). ## Gestione dati squadra (solo amministratore) diff --git a/src/components/crapp/BadgeDrawer.tsx b/src/components/crapp/BadgeDrawer.tsx index f923156..41d2cfe 100644 --- a/src/components/crapp/BadgeDrawer.tsx +++ b/src/components/crapp/BadgeDrawer.tsx @@ -33,7 +33,7 @@ function DettaglioBadge({ def, stato }: { def: BadgeDef; stato?: BadgeStato }) {
+
Stato attuale
{grado ? ( - {meta?.label} + + {meta?.label} + ) : ( - + In progresso )} @@ -59,19 +61,19 @@ function DettaglioBadge({ def, stato }: { def: BadgeDef; stato?: BadgeStato }) { {stato.prossimaSoglia ? ( <>+
Mancano {stato.prossimaSoglia - stato.valore} {def.unita} per il{" "} {gradoMeta[stato.prossimo as Grado].label.toLowerCase()}
> ) : ( -Hai raggiunto il livello massimo.
+Hai raggiunto il livello massimo.
)}+
Soglie
@@ -102,7 +104,7 @@ function DettaglioBadge({ def, stato }: { def: BadgeDef; stato?: BadgeStato }) { > {def.soglie[g]}
-{def.unita}
+{def.unita}
+
“{def.celebrazione}”
) : null} @@ -142,7 +144,7 @@ export function BadgeDrawer({+
{notifica.tono === "segreto" ? "Badge segreto sbloccato" : "Traguardo raggiunto"}
{notifica.titolo}
-{notifica.testo}
+{notifica.testo}
{b.def.nome}
-+
{b.def.nome}
+{b.valore} {b.def.unita}
{b.prossimaSoglia ? ( <>{mancanoPer(b)}
-{microcopyBadge(b)}
+{mancanoPer(b)}
+{microcopyBadge(b)}
> ) : ( -{microcopyBadge(b)}
+{microcopyBadge(b)}
)} ); @@ -90,13 +90,15 @@ function SocialDrawer({Vinto
++ Vinto +
{conteggio}{" "}
@@ -109,7 +111,7 @@ function SocialDrawer({
+
Collezione badge
@@ -147,7 +149,7 @@ export function CollezioneBadge({
/{c.totali}
+
+
Prossimo traguardo
{vicino.def.nome} {vicino.def.nome}
+
{mancanoPer(vicino)} · {microcopyBadge(vicino)}
+
Sbloccati ({c.sbloccati.length})
+
In progresso ({c.inProgresso.length})
+
Votati dai compagni
{cat.emoji} {cat.nome}
+ {cat.nome}
Vinto {social[cat.id]} {social[cat.id] === 1 ? "volta" : "volte"}
+
Badge segreti
{b.def.nome}
+ {b.def.nome}
{b.def.celebrazione ?? "Badge segreto sbloccato."}
??? Badge segreto da scoprire
+ ???
+ Badge segreto da scoprire
+
{squadra.squadra}
+
Probabilità di vittoria (calcolo CSI):{" "}
{favoritaNoi ? NOME_NOI : avversario}{" "}
favorita al {Math.max(noi, avversarioPct).toFixed(0)}%.
@@ -171,13 +171,13 @@ function BarraProbabilita({
+
{precedenti.totale > 0
? `${precedenti.totale} precedenti in archivio sul portale CSI.`
: "Nessun precedente in archivio sul portale CSI: primo confronto tra le due squadre."}
@@ -248,20 +248,22 @@ export function DettaglioCsiEsteso({
const { data, isLoading } = useCsiPartita(matchId);
if (isLoading) {
- return Carico i dati dal CSI… Carico i dati dal CSI…
+
{[data.giornata, data.nota].filter(Boolean).join(" · ")}
{evento.luogo} {evento.luogo} {sottotitoloPartita} {sottotitoloPartita} 📝 {noteCard} 📝 {noteCard}
{metaStato.emoji}
diff --git a/src/components/crapp/ObiettivoDrawer.tsx b/src/components/crapp/ObiettivoDrawer.tsx
index 2662f1b..90d7803 100644
--- a/src/components/crapp/ObiettivoDrawer.tsx
+++ b/src/components/crapp/ObiettivoDrawer.tsx
@@ -17,12 +17,12 @@ import {
function Elenco({ titolo, voci, segno }: { titolo: string; voci: string[]; segno: string }) {
return (
+
{titolo}
+
{titolo}
{testo} {testo}
+
Stato attuale
+
{pct}%{o.scadenza ? ` · entro il ${formatData(o.scadenza)}` : ""}
{microcopyObiettivo(o)} {microcopyObiettivo(o)}
+
{o.impatto}
+
+
Dai un voto da 1 a 10 ai compagni: nessuno vedrà chi ha votato cosa, solo la media.
+
Carico le pagelle…
+
{allenatore
? "Data e luogo di nascita, telefono ed email."
: "Documento e certificato medico servono per il tesseramento CSI."}
diff --git a/src/components/crapp/RosaPresenze.tsx b/src/components/crapp/RosaPresenze.tsx
index f02d065..ad9c9cf 100644
--- a/src/components/crapp/RosaPresenze.tsx
+++ b/src/components/crapp/RosaPresenze.tsx
@@ -70,7 +70,7 @@ export function RosaPresenze({
+
Hanno risposto {risposteN}/{rosa.length}
+
La tua risposta
+
Carico le risposte…
+
{titolo} · {n}
{attenzione ? {s.def.label} {s.def.descrizione} {s.def.label} {s.def.descrizione}
+
{s.prossimo ? `${s.valore}/${s.prossimo} · ` : ""}
{s.messaggio}
+
Serie {top.def.label.toLowerCase()}: {top.valore}
{top.messaggio} {top.messaggio} {s.valore}
+
{s.def.label}
+
💩 Sondaggio pre-partita
+
{sondaggioTerminato(dataEvento, oraEvento)
? "Sondaggio chiuso: era aperto fino al fischio d'inizio."
: "Apre alle 8:00 del giorno della partita: riceverai una notifica."}
@@ -96,14 +96,14 @@ export function SondaggioCacche({
return (
+
💩 Sondaggio pre-partita
+
Quante cacche hai fatto prima di questa partita? Dato scientifico fondamentale.
+
+
Apre {ORE_ATTESA_MVP} ore dopo l'inizio della partita.
+
+
{testa && !pareggio ? (
Hai votato {mio.votato_nome} Hai votato {mio.votato_nome}
+
Vota chi era presente a questa partita.
+
Nessun voto ancora: apri e scegli un compagno.
+
+
Parità con {totale} voti: servono altri voti per assegnare il badge.
{notifica.titolo} {notifica.corpo} {tempoRelativo(notifica.creataIl)} {tempoRelativo(notifica.creataIl)}
+
La pagina che cerchi non esiste o è stata spostata.
+
Qualcosa è andato storto da parte nostra. Puoi riprovare o tornare alla home.
{evento.titolo}
- {evento.titolo}
+ {evento.titolo}
{sottotitoloPartita ? (
-
{voci.map((v) => (
-
{titolo}
+ {titolo}
{completa ? 404
Pagina non trovata
-
Questa pagina non si è caricata
- Dati squadra
+ Dati squadra
Dati personali
+ Dati personali