Aggancia Squadra, Presenze, Pagelle, Scout e calendario alla rosa reale
convocatiEvento() e compleanniEventi() prendono ora la rosa come parametro invece di leggere la lista statica; csvScoutMatch() idem. Le schermate di gestione eventi, dettaglio allenamento/partita, calendario e scout live, più i widget di presenze/pagelle/voto MVP/voto social/sondaggio cacche/turno palloni, passano tutte la rosa letta da useRosa() o useGiocatoriSquadra(): un giocatore aggiunto o disattivato dalla dashboard admin ora si riflette ovunque.
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { createFileRoute, Link } from "@tanstack/react-router";
|
||||
import { ArrowLeft, MapPin, Clock, Users, Dumbbell, CalendarDays } from "lucide-react";
|
||||
import { PageHeader, Section } from "@/components/crapp/ui-bits";
|
||||
import { formatData, giocatori } from "@/lib/crapp-data";
|
||||
import { formatData } from "@/lib/crapp-data";
|
||||
import { convocatiEvento, useEvento } from "@/lib/eventi";
|
||||
import { useRosa } from "@/lib/rosa";
|
||||
import { TurnoPalloni } from "@/components/crapp/TurnoPalloni";
|
||||
import { RosaPresenze } from "@/components/crapp/RosaPresenze";
|
||||
import { usePresenzeEvento } from "@/lib/presenze";
|
||||
@@ -34,7 +35,8 @@ function AllenamentoDetail() {
|
||||
const { id } = Route.useParams();
|
||||
const { evento } = useEvento(id);
|
||||
const { risposte } = usePresenzeEvento(id);
|
||||
const presentiVeri = giocatori.filter(
|
||||
const rosa = useRosa();
|
||||
const presentiVeri = rosa.filter(
|
||||
(g) => risposte[g.id] === "presente" || risposte[g.id] === "ritardo",
|
||||
).length;
|
||||
|
||||
@@ -90,7 +92,7 @@ function AllenamentoDetail() {
|
||||
|
||||
<div className="mt-4 inline-flex items-center gap-2 rounded-full bg-secondary px-3 py-1.5 text-xs font-semibold">
|
||||
<Users className="h-4 w-4" />
|
||||
Conferme: {presentiVeri}/{convocatiEvento(evento).length}
|
||||
Conferme: {presentiVeri}/{convocatiEvento(evento, rosa).length}
|
||||
</div>
|
||||
|
||||
<TurnoPalloni eventoId={evento.id} />
|
||||
|
||||
@@ -6,6 +6,7 @@ import { cn } from "@/lib/utils";
|
||||
import { EventoCard, linkPerEvento } from "@/components/crapp/EventoCard";
|
||||
import { PageHeader, Section } from "@/components/crapp/ui-bits";
|
||||
import { compleanniEventi, useEventi, type Evento } from "@/lib/eventi";
|
||||
import { useRosa } from "@/lib/rosa";
|
||||
import { useGiocatoreCorrente } from "@/lib/user-store";
|
||||
import { useIsAdmin } from "@/lib/ruoli";
|
||||
import {
|
||||
@@ -100,11 +101,12 @@ function Calendario() {
|
||||
const io = useGiocatoreCorrente();
|
||||
const admin = useIsAdmin();
|
||||
const { eventi } = useEventi();
|
||||
const rosa = useRosa();
|
||||
const { anno, mese, precedente, successivo } = useMeseNav();
|
||||
const { giorni, offsetLunedi } = giorniDelMese(anno, mese);
|
||||
const mesePrefix = `${anno}-${pad2(mese + 1)}`;
|
||||
|
||||
const compleanni = compleanniEventi(anno);
|
||||
const compleanni = compleanniEventi(rosa, anno);
|
||||
const compleanniMese = compleanni.filter((c) => c.data.startsWith(mesePrefix));
|
||||
const eventiMese = eventi.filter((e) => e.data.startsWith(mesePrefix));
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import { ArrowLeft, CalendarPlus, Loader2, Pencil, Trash2 } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { PageHeader, Section } from "@/components/crapp/ui-bits";
|
||||
import { formatData, giocatori } from "@/lib/crapp-data";
|
||||
import { formatData } from "@/lib/crapp-data";
|
||||
import { nomeCompleto, useGiocatoriSquadra } from "@/lib/giocatori-squadra";
|
||||
import {
|
||||
categoriaEvento,
|
||||
daCategoria,
|
||||
@@ -50,9 +51,11 @@ function GestioneEventi() {
|
||||
const io = useGiocatoreCorrente();
|
||||
const admin = useIsAdmin();
|
||||
const { eventi, isPending } = useEventi();
|
||||
const { righe: squadra } = useGiocatoriSquadra();
|
||||
const salva = useSalvaEvento();
|
||||
const elimina = useEliminaEvento();
|
||||
const [bozza, setBozza] = useState<Evento | null>(null);
|
||||
const rosa = squadra.filter((g) => g.attivo);
|
||||
|
||||
if (!io || !admin) {
|
||||
return (
|
||||
@@ -228,7 +231,7 @@ function GestioneEventi() {
|
||||
label={`Convocati (${bozza.convocati.length === 0 ? "tutta la rosa" : bozza.convocati.length})`}
|
||||
>
|
||||
<div className="grid grid-cols-2 gap-1.5">
|
||||
{giocatori.map((g) => {
|
||||
{rosa.map((g) => {
|
||||
const scelto = bozza.convocati.includes(g.id);
|
||||
return (
|
||||
<button
|
||||
@@ -248,7 +251,7 @@ function GestioneEventi() {
|
||||
: "bg-secondary text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
{g.nome}
|
||||
{nomeCompleto(g)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -2,8 +2,9 @@ import { createFileRoute, Link } from "@tanstack/react-router";
|
||||
import { ArrowLeft, MapPin, Clock, Users, Trophy, Swords, Download } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { PageHeader, Section } from "@/components/crapp/ui-bits";
|
||||
import { formatData, giocatori } from "@/lib/crapp-data";
|
||||
import { formatData } from "@/lib/crapp-data";
|
||||
import { convocatiEvento, useEvento } from "@/lib/eventi";
|
||||
import { useRosa } from "@/lib/rosa";
|
||||
import { useCsi } from "@/lib/csi";
|
||||
import { matchDaPartitaCsi, partiteGiocate } from "@/lib/csi-core";
|
||||
import { Pagelle } from "@/components/crapp/Pagelle";
|
||||
@@ -49,7 +50,8 @@ function PartitaDetail() {
|
||||
const scoutMatches = useScoutMatches();
|
||||
const { data: csi } = useCsi();
|
||||
const { risposte } = usePresenzeEvento(id);
|
||||
const presentiVeri = giocatori.filter(
|
||||
const rosa = useRosa();
|
||||
const presentiVeri = rosa.filter(
|
||||
(g) => risposte[g.id] === "presente" || risposte[g.id] === "ritardo",
|
||||
).length;
|
||||
|
||||
@@ -67,7 +69,7 @@ function PartitaDetail() {
|
||||
);
|
||||
}
|
||||
|
||||
const convocati = convocatiEvento(evento);
|
||||
const convocati = convocatiEvento(evento, rosa);
|
||||
const scout = scoutMatches.find((m) => m.id === evento.id || m.data === evento.data) ?? null;
|
||||
const csiMatch = csi
|
||||
? partiteGiocate(csi.partite).find((p) => p.data === evento.data)
|
||||
@@ -229,7 +231,7 @@ function PartitaDetail() {
|
||||
</p>
|
||||
<div className="mt-2 space-y-1">
|
||||
{[...totaliPerGiocatore(scout.azioni).entries()].map(([gid, t]) => {
|
||||
const g = giocatori.find((x) => x.id === gid);
|
||||
const g = rosa.find((x) => x.id === gid);
|
||||
if (!g) return null;
|
||||
return (
|
||||
<div
|
||||
@@ -250,7 +252,10 @@ function PartitaDetail() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
scaricaCsv(`scout-${scout.data}-${scout.avversario}.csv`, csvScoutMatch(scout))
|
||||
scaricaCsv(
|
||||
`scout-${scout.data}-${scout.avversario}.csv`,
|
||||
csvScoutMatch(scout, rosa),
|
||||
)
|
||||
}
|
||||
className="premi mt-4 flex w-full items-center justify-center gap-2 rounded-2xl bg-accent-grad py-3 text-sm font-bold uppercase text-accent-foreground shadow-pop"
|
||||
>
|
||||
|
||||
@@ -3,8 +3,9 @@ import { createFileRoute, useNavigate } from "@tanstack/react-router";
|
||||
import { Undo2, Save, CheckCircle2, Radio, Lock, CalendarX2, LogOut } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { giocatori, formatData } from "@/lib/crapp-data";
|
||||
import { formatData } from "@/lib/crapp-data";
|
||||
import type { Evento } from "@/lib/eventi";
|
||||
import { useRosa } from "@/lib/rosa";
|
||||
import { useGiocatoreCorrente } from "@/lib/user-store";
|
||||
import { useIsAdmin } from "@/lib/ruoli";
|
||||
import { usePresenzeEvento } from "@/lib/presenze";
|
||||
@@ -214,15 +215,16 @@ function ScoutBoard({
|
||||
const cancella = useCancellaStatoScout();
|
||||
const salvaMatch = useSalvaScoutMatch();
|
||||
const { risposte } = usePresenzeEvento(partita.id);
|
||||
const rosa = useRosa();
|
||||
const finito = useRef(false);
|
||||
|
||||
/** In campo solo chi ha confermato la presenza (anche in ritardo). */
|
||||
const convocati = useMemo(() => {
|
||||
const presenti = giocatori.filter(
|
||||
const presenti = rosa.filter(
|
||||
(g) => risposte[g.id] === "presente" || risposte[g.id] === "ritardo",
|
||||
);
|
||||
return presenti.length > 0 ? presenti : giocatori;
|
||||
}, [risposte]);
|
||||
return presenti.length > 0 ? presenti : rosa;
|
||||
}, [risposte, rosa]);
|
||||
|
||||
// Salvataggio condiviso: se chi scouta si disconnette, il prossimo riprende da qui.
|
||||
useEffect(() => {
|
||||
@@ -453,7 +455,7 @@ function ScoutBoard({
|
||||
) : (
|
||||
<ul className="mt-2 space-y-1.5">
|
||||
{ultime.map((a, i) => {
|
||||
const g = giocatori.find((x) => x.id === a.giocatoreId);
|
||||
const g = rosa.find((x) => x.id === a.giocatoreId);
|
||||
return (
|
||||
<li
|
||||
key={a.id}
|
||||
|
||||
Reference in New Issue
Block a user