EventoCard monta un hook per ogni card mostrata: usava useGiocatoreCorrente (= useIo = useRosa, le 6 statistiche pesanti) solo per leggere il proprio id. Il Calendario ne rende diverse insieme (prossimi eventi, compleanni, drawer del giorno), quindi ogni apertura moltiplicava il ricalcolo dell'intera rosa. Audit di tutti gli altri usi di useGiocatoreCorrente: 12 su 13 leggevano solo id/nome/verita', mai una statistica. Corretti allo stesso modo (-> useGiocatoreBase): benvenuto.tsx, VotazioneMvp, SondaggioCacche, VotoSocial, eventi.tsx, PromemoriaPalloni (Home), TurnoPalloni, ScoutEntry, Pagelle. partita.$id.tsx: `io` era dichiarato e mai piu' usato, rimosso. Stesso pattern trovato anche su useRosa (non solo useGiocatoreCorrente) in scout.tsx e RosaPresenze.tsx (montata su partita e allenamento): entrambi passati al nuovo useAnagraficaRosa, esteso con ruolo e numero. Unica eccezione: CelebrazioneBadge.tsx usa davvero le statistiche complete (badge, MVP, serie) ed e' montato globalmente in __root.tsx - non downgradabile, resta il costo di base piu' alto rimasto in giro. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
import { Link } from "@tanstack/react-router";
|
|
import { ChevronRight, Lock, Radio } from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
import { sessioneScaduta, usePartitaDiOggi, useSessioneScout } from "@/lib/scout-live";
|
|
import { useGiocatoreBase } from "@/lib/user-store";
|
|
|
|
/**
|
|
* Accesso allo scout live: attivo solo il giorno della partita e se nessun altro lo sta usando.
|
|
* Con `eventoId` si accende solo se quella partita è proprio quella di oggi.
|
|
*/
|
|
export function ScoutEntry({
|
|
variante = "grande",
|
|
eventoId,
|
|
}: {
|
|
variante?: "grande" | "compatto";
|
|
eventoId?: string;
|
|
}) {
|
|
const { pronto, partita: diOggi } = usePartitaDiOggi();
|
|
const partita = eventoId && diOggi?.id !== eventoId ? null : diOggi;
|
|
// Solo `.id` serve qui: `useGiocatoreBase` basta, niente statistiche.
|
|
const io = useGiocatoreBase();
|
|
const { data: sessione } = useSessioneScout(partita?.id ?? null);
|
|
|
|
const attiva = sessione && !sessioneScaduta(sessione) ? sessione : null;
|
|
const occupato = !!attiva && attiva.giocatore_id !== io?.id;
|
|
const disponibile = pronto && !!partita && !occupato;
|
|
|
|
const titolo = !partita ? "Scout live non attivo" : occupato ? "Scout occupato" : "Scout live";
|
|
const sottotitolo = !partita
|
|
? "Si attiva il giorno della partita"
|
|
: occupato
|
|
? `In uso da ${attiva!.giocatore_nome}`
|
|
: "Segna punti, ace e muri in tempo reale";
|
|
|
|
const contenuto = (
|
|
<>
|
|
{occupato ? <Lock className="h-5 w-5 shrink-0" /> : <Radio className="h-5 w-5 shrink-0" />}
|
|
<span className="min-w-0 flex-1">
|
|
<span className="block font-display text-lg uppercase leading-none">{titolo}</span>
|
|
<span className="block text-xs opacity-80">{sottotitolo}</span>
|
|
</span>
|
|
{disponibile ? <ChevronRight className="h-5 w-5 shrink-0" /> : null}
|
|
</>
|
|
);
|
|
|
|
const classi = cn(
|
|
"flex items-center gap-3 rounded-3xl p-4 shadow-card",
|
|
variante === "compatto" && "gap-2 rounded-2xl p-3",
|
|
disponibile
|
|
? "bg-accent-grad text-accent-foreground shadow-pop"
|
|
: "bg-card text-muted-foreground",
|
|
);
|
|
|
|
if (!disponibile) {
|
|
return (
|
|
<div className={classi} aria-disabled>
|
|
{contenuto}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Link to="/scout" className={classi}>
|
|
{contenuto}
|
|
</Link>
|
|
);
|
|
}
|