From 953908388d575b62a156f65330e81370d43bfae1 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Fri, 28 Aug 2026 15:39:40 +0200 Subject: [PATCH] Sposto rosa, classifica e storico partite dagli array hardcoded al CMS Strapi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nuovi moduli src/lib/strapi-client.ts + rosa-base.ts/classifica-csi.ts/ storico-match.ts (hook TanStack Query, cache lunga, nessun polling). L'id stabile gN diventa il campo `codice` su Strapi, per non rompere le FK verso pagelle/cacche/mvp/palloni/presenze/azioni scout già chiavate su quella stringa. isAdmin ora prende il Giocatore invece di un id, così non dipende più dal roster. Rifattorizzati di conseguenza tutti i punti che importavano `giocatori`/`classifica`/`storicoMatch` come array sincroni (componenti, hook, due route server) per usare gli hook o un parametro esplicito. Co-Authored-By: Claude Sonnet 5 --- src/components/crapp/EventoCard.tsx | 60 ++++---- src/components/crapp/Pagelle.tsx | 17 ++- src/components/crapp/RosaPresenze.tsx | 11 +- src/components/crapp/ScoutEntry.tsx | 2 +- src/components/crapp/SondaggioCacche.tsx | 8 +- src/components/crapp/TurnoPalloni.tsx | 5 +- src/components/crapp/VotazioneMvp.tsx | 5 +- src/components/crapp/VotoSocial.tsx | 8 +- src/lib/classifica-csi.ts | 44 ++++++ src/lib/crapp-data.ts | 117 ++-------------- src/lib/eventi.ts | 9 +- src/lib/obiettivi.ts | 32 +++-- src/lib/palloni-core.ts | 23 ++- src/lib/palloni.ts | 4 +- src/lib/presenze-mese.ts | 10 +- src/lib/rosa-base.ts | 62 ++++++++ src/lib/rosa.ts | 14 +- src/lib/scout-export.ts | 13 +- src/lib/scout-store.ts | 74 +++++++--- src/lib/storico-match.ts | 43 ++++++ src/lib/strapi-client.ts | 22 +++ src/lib/user-store.ts | 8 +- src/routeTree.gen.ts | 21 +++ src/routes/__root.tsx | 45 ++++-- src/routes/allenamento.$id.tsx | 16 ++- src/routes/api/public/promemoria-palloni.ts | 6 +- src/routes/api/public/push-messaggio.ts | 15 +- src/routes/api/public/sollecita-presenze.ts | 4 +- src/routes/benvenuto.tsx | 3 +- src/routes/calendario.tsx | 17 ++- src/routes/classifica.tsx | 11 +- src/routes/eventi.tsx | 19 ++- src/routes/index.tsx | 148 +++++++++++--------- src/routes/partita.$id.tsx | 41 ++++-- src/routes/scout.tsx | 48 +++++-- src/routes/squadra.tsx | 57 +++++--- 36 files changed, 678 insertions(+), 364 deletions(-) create mode 100644 src/lib/classifica-csi.ts create mode 100644 src/lib/rosa-base.ts create mode 100644 src/lib/storico-match.ts create mode 100644 src/lib/strapi-client.ts diff --git a/src/components/crapp/EventoCard.tsx b/src/components/crapp/EventoCard.tsx index f583865..6f81405 100644 --- a/src/components/crapp/EventoCard.tsx +++ b/src/components/crapp/EventoCard.tsx @@ -1,11 +1,12 @@ import { MapPin, Clock, Users, Cake, ArrowRight } from "lucide-react"; import { Link } from "@tanstack/react-router"; import { cn } from "@/lib/utils"; -import { formatData, giocatori, statoMeta, type Stato } from "@/lib/crapp-data"; +import { formatData, statoMeta, type Stato } from "@/lib/crapp-data"; import type { Evento } from "@/lib/eventi"; import { Barra } from "@/components/motion/Barra"; import { usePresenzeEvento, useSalvaPresenza } from "@/lib/presenze"; import { useGiocatoreCorrente } from "@/lib/user-store"; +import { useRosaBase } from "@/lib/rosa-base"; const tipoMeta = { partita: { label: "Partita", className: "bg-accent text-accent-foreground" }, @@ -36,6 +37,7 @@ export function EventoCard({ const { risposte } = usePresenzeEvento(evento.id); const salva = useSalvaPresenza(); const io = useGiocatoreCorrente(); + const giocatori = useRosaBase(); const stato = io ? risposte[io.id] : undefined; const presentiVeri = giocatori.filter( (g) => risposte[g.id] === "presente" || risposte[g.id] === "ritardo", @@ -118,33 +120,35 @@ export function EventoCard({ {io ? ( -
- {stati.map((s) => { - const meta = statoMeta[s]; - const attivo = stato === s; - return ( - - ); - })} -
+
+ {stati.map((s) => { + const meta = statoMeta[s]; + const attivo = stato === s; + return ( + + ); + })} +
) : null} ); -} \ No newline at end of file +} diff --git a/src/components/crapp/Pagelle.tsx b/src/components/crapp/Pagelle.tsx index 5ebfe43..b75fb11 100644 --- a/src/components/crapp/Pagelle.tsx +++ b/src/components/crapp/Pagelle.tsx @@ -3,7 +3,8 @@ import { ClipboardCheck, Lock } from "lucide-react"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; import { Avatar } from "@/components/crapp/Avatar"; -import { giocatori } from "@/lib/crapp-data"; +import type { Giocatore } from "@/lib/crapp-data"; +import { useRosaBase } from "@/lib/rosa-base"; import { useGiocatoreCorrente } from "@/lib/user-store"; import { mieiVoti, pagellePartita, usePagelle, useVotaPagella } from "@/lib/pagelle"; @@ -12,21 +13,23 @@ const voti = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; /** Pagelle di fine partita: voto anonimo 1-10 a ciascun compagno. */ export function Pagelle({ matchId, - convocati = giocatori, + convocati, chiuse = false, }: { matchId: string; - convocati?: typeof giocatori; + convocati?: Giocatore[]; chiuse?: boolean; }) { + const rosaBase = useRosaBase(); const io = useGiocatoreCorrente(); const { voti: tutti, isPending } = usePagelle(); const vota = useVotaPagella(); const [apertoPer, setApertoPer] = useState(null); + const lista = convocati ?? rosaBase; const medie = pagellePartita(tutti, matchId); const miei = io ? mieiVoti(tutti, matchId, io.id) : {}; - const daVotare = convocati.filter((g) => g.id !== io?.id); + const daVotare = lista.filter((g) => g.id !== io?.id); const fatti = daVotare.filter((g) => miei[g.id] !== undefined).length; async function invia(votatoId: string, voto: number) { @@ -58,7 +61,7 @@ export function Pagelle({

Carico le pagelle…

) : (
- {convocati.map((g) => { + {lista.map((g) => { const media = medie[g.id]; const mio = miei[g.id]; const sonoIo = g.id === io?.id; @@ -104,7 +107,9 @@ export function Pagelle({ onClick={() => invia(g.id, v)} className={cn( "rounded-lg py-1.5 text-[11px] font-bold tabular-nums transition-transform active:scale-90", - mio === v ? "bg-accent text-accent-foreground" : "bg-card text-foreground", + mio === v + ? "bg-accent text-accent-foreground" + : "bg-card text-foreground", )} > {v} diff --git a/src/components/crapp/RosaPresenze.tsx b/src/components/crapp/RosaPresenze.tsx index 8836039..cfacc21 100644 --- a/src/components/crapp/RosaPresenze.tsx +++ b/src/components/crapp/RosaPresenze.tsx @@ -4,7 +4,8 @@ import { toast } from "sonner"; import { cn } from "@/lib/utils"; import { Avatar } from "@/components/crapp/Avatar"; import { Barra } from "@/components/motion/Barra"; -import { giocatori, isAdmin, statoMeta, type Stato } from "@/lib/crapp-data"; +import { isAdmin, statoMeta, type Giocatore, type Stato } from "@/lib/crapp-data"; +import { useRosaBase } from "@/lib/rosa-base"; import { usePresenzeEvento, useSalvaPresenza } from "@/lib/presenze"; import { useGiocatoreCorrente } from "@/lib/user-store"; @@ -14,12 +15,14 @@ export function RosaPresenze({ eventoId }: { eventoId: string }) { const { risposte, isPending } = usePresenzeEvento(eventoId); const salva = useSalvaPresenza(); const io = useGiocatoreCorrente(); + const giocatori = useRosaBase(); const [sollecito, setSollecito] = useState(false); const mancanti = giocatori.filter((g) => !risposte[g.id]); const risposteN = giocatori.length - mancanti.length; const perc = Math.round((risposteN / giocatori.length) * 100); - const daSollecitare = mancanti.length + giocatori.filter((g) => risposte[g.id] === "forse").length; + const daSollecitare = + mancanti.length + giocatori.filter((g) => risposte[g.id] === "forse").length; async function sollecita() { setSollecito(true); @@ -105,7 +108,7 @@ export function RosaPresenze({ eventoId }: { eventoId: string }) {
) : null} - {io && isAdmin(io.id) ? ( + {io && isAdmin(io) ? (