Aggiunge sottosezioni a swipe nel profilo, con stagione e serie unite.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Cacciari
2026-09-05 22:07:58 +02:00
co-authored by Cursor
parent f4398fce25
commit e9755d364c
2 changed files with 202 additions and 175 deletions
+21 -7
View File
@@ -265,9 +265,12 @@ export function CampiProfilo({
export function ProfiloAmministrativo({ export function ProfiloAmministrativo({
giocatoreId, giocatoreId,
indice = 0, indice = 0,
/** Se false, mostra solo il contenuto (es. dentro `BarraSottosezioni`). */
conTendina = true,
}: { }: {
giocatoreId: string; giocatoreId: string;
indice?: number; indice?: number;
conTendina?: boolean;
}) { }) {
const { profili } = useProfili(); const { profili } = useProfili();
const salva = useSalvaProfilo(); const salva = useSalvaProfilo();
@@ -301,19 +304,19 @@ export function ProfiloAmministrativo({
const caricato = (campo: keyof Profilo) => async (path: string) => const caricato = (campo: keyof Profilo) => async (path: string) =>
scrivi({ ...corrente, [campo]: path }); scrivi({ ...corrente, [campo]: path });
return ( const corpo = (
<SezioneTendina
titolo="Dati per il tesseramento"
indice={indice}
azione={<span className="text-xs font-bold tabular-nums text-muted-foreground">{perc}%</span>}
>
<div className="space-y-3 rounded-3xl bg-card p-4 shadow-card"> <div className="space-y-3 rounded-3xl bg-card p-4 shadow-card">
<div className="h-1.5 overflow-hidden rounded-full bg-secondary"> <div className="flex items-center justify-between gap-2">
<div className="h-1.5 min-w-0 flex-1 overflow-hidden rounded-full bg-secondary">
<div <div
className="h-full rounded-full bg-accent-grad transition-all" className="h-full rounded-full bg-accent-grad transition-all"
style={{ width: `${perc}%` }} style={{ width: `${perc}%` }}
/> />
</div> </div>
<span className="shrink-0 text-xs font-bold tabular-nums text-muted-foreground">
{perc}%
</span>
</div>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
Servono agli amministratori per il tesseramento CSI. Li vedi solo tu e loro. Servono agli amministratori per il tesseramento CSI. Li vedi solo tu e loro.
@@ -374,6 +377,17 @@ export function ProfiloAmministrativo({
{sporco ? "Salva" : "Salvato"} {sporco ? "Salva" : "Salvato"}
</button> </button>
</div> </div>
);
if (!conTendina) return corpo;
return (
<SezioneTendina
titolo="Dati per il tesseramento"
indice={indice}
azione={<span className="text-xs font-bold tabular-nums text-muted-foreground">{perc}%</span>}
>
{corpo}
</SezioneTendina> </SezioneTendina>
); );
} }
+37 -24
View File
@@ -3,14 +3,8 @@ import { useEffect, useRef, useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { Flame, Camera, Trash2, Bell, LogOut, ShieldCheck, Bug, Lightbulb } from "lucide-react"; import { Flame, Camera, Trash2, Bell, LogOut, ShieldCheck, Bug, Lightbulb } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { import { Card, PageHeader, StatTile, TeamLogo } from "@/components/crapp/ui-bits";
Card, import { BarraSottosezioni } from "@/components/crapp/BarraSottosezioni";
PageHeader,
Section,
SezioneTendina,
StatTile,
TeamLogo,
} from "@/components/crapp/ui-bits";
import { Avatar } from "@/components/crapp/Avatar"; import { Avatar } from "@/components/crapp/Avatar";
import { import {
caricaAvatar, caricaAvatar,
@@ -126,7 +120,7 @@ function Profilo() {
<PageHeader <PageHeader
titolo={g.nome} titolo={g.nome}
sottotitolo={`#${g.numero} · ${g.ruolo}`} sottotitolo={`#${g.numero} · ${g.ruolo}`}
azione={<TeamLogo src="/logo-nerorosso.svg" className="h-11 w-11" />} azione={<TeamLogo src="/logo-nerorosso.svg" className="h-14 w-14" />}
/> />
<Reveal className="-mt-6 px-5"> <Reveal className="-mt-6 px-5">
@@ -183,9 +177,20 @@ function Profilo() {
</Card> </Card>
</Reveal> </Reveal>
<Section titolo="Stagione" indice={1}> <BarraSottosezioni
defaultId="stagione"
voci={[
{
id: "stagione",
label: "Stagione",
contenuto: (
<div className="space-y-4">
<div className="grid grid-cols-3 gap-2"> <div className="grid grid-cols-3 gap-2">
<StatTile valore={g.presenze} label="Presenze" hint={`${percPresenze}% del totale`} /> <StatTile
valore={g.presenze}
label="Presenze"
hint={`${percPresenze}% del totale`}
/>
<StatTile <StatTile
valore={`${ultimoMese.percentuale}%`} valore={`${ultimoMese.percentuale}%`}
label="Presenze 30gg" label="Presenze 30gg"
@@ -204,19 +209,24 @@ function Profilo() {
<StatTile valore={g.mvp} label="MVP" /> <StatTile valore={g.mvp} label="MVP" />
<StatTile valore={g.palloni} label="Turni palloni" /> <StatTile valore={g.palloni} label="Turni palloni" />
</div> </div>
</Section>
<Section titolo="Serie di presenze" indice={2}>
<SerieGriglia g={g} /> <SerieGriglia g={g} />
</Section> </div>
),
<SezioneTendina titolo="Collezione badge" indice={3}> },
<CollezioneBadge g={g} votiSocial={votiSocial.data ?? []} /> {
</SezioneTendina> id: "badge",
label: "Badge",
<ProfiloAmministrativo giocatoreId={g.id} indice={4} /> contenuto: <CollezioneBadge g={g} votiSocial={votiSocial.data ?? []} />,
},
<Section titolo="Impostazioni"> {
id: "tesseramento",
label: "Tesseramento",
contenuto: <ProfiloAmministrativo giocatoreId={g.id} conTendina={false} />,
},
{
id: "impostazioni",
label: "Impostazioni",
contenuto: (
<div className="divide-y divide-border overflow-hidden rounded-3xl bg-card shadow-card"> <div className="divide-y divide-border overflow-hidden rounded-3xl bg-card shadow-card">
<button <button
type="button" type="button"
@@ -281,7 +291,10 @@ function Profilo() {
<LogOut className="h-4 w-4 text-muted-foreground" /> <LogOut className="h-4 w-4 text-muted-foreground" />
</button> </button>
</div> </div>
</Section> ),
},
]}
/>
</> </>
); );
} }