Blocca la modifica delle presenze e il sollecito per eventi già passati.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-06 10:27:12 +02:00
co-authored by Claude Sonnet 5
parent d4a02fb606
commit 208dd5f2f6
4 changed files with 12 additions and 8 deletions
+4 -2
View File
@@ -8,6 +8,7 @@ import { Barra } from "@/components/motion/Barra";
import { useGiocatoriSquadra } from "@/lib/giocatori-squadra"; import { useGiocatoriSquadra } from "@/lib/giocatori-squadra";
import { usePresenzeEvento, useSalvaPresenza } from "@/lib/presenze"; import { usePresenzeEvento, useSalvaPresenza } from "@/lib/presenze";
import { useGiocatoreCorrente } from "@/lib/user-store"; import { useGiocatoreCorrente } from "@/lib/user-store";
import { dataOggi } from "@/lib/scout-live";
const tipoMeta = { const tipoMeta = {
partita: { label: "Partita", className: "bg-accent text-accent-foreground" }, partita: { label: "Partita", className: "bg-accent text-accent-foreground" },
@@ -51,6 +52,7 @@ export function EventoCard({
const totale = rosa.length; const totale = rosa.length;
const perc = totale ? Math.round((presentiVeri / totale) * 100) : 0; const perc = totale ? Math.round((presentiVeri / totale) * 100) : 0;
const isCompleanno = evento.tipo === "compleanno"; const isCompleanno = evento.tipo === "compleanno";
const passato = evento.data < dataOggi();
if (isCompleanno) { if (isCompleanno) {
return ( return (
@@ -130,7 +132,7 @@ export function EventoCard({
<button <button
key={s} key={s}
type="button" type="button"
disabled={salva.isPending} disabled={salva.isPending || passato}
onClick={() => onClick={() =>
salva.mutate({ salva.mutate({
eventoId: evento.id, eventoId: evento.id,
@@ -142,7 +144,7 @@ export function EventoCard({
className={cn( className={cn(
// min-h-11: sono i controlli più toccati dell'app, sotto i // min-h-11: sono i controlli più toccati dell'app, sotto i
// 44px si sbaglia bersaglio. // 44px si sbaglia bersaglio.
"min-h-11 rounded-full border border-border px-3 text-xs font-semibold transition-all active:scale-95", "min-h-11 rounded-full border border-border px-3 text-xs font-semibold transition-all active:scale-95 disabled:opacity-50",
attivo attivo
? cn(meta.className, "border-transparent shadow-card") ? cn(meta.className, "border-transparent shadow-card")
: "bg-background text-muted-foreground", : "bg-background text-muted-foreground",
+6 -4
View File
@@ -10,16 +10,18 @@ import { usePresenzeEvento, useSalvaPresenza } from "@/lib/presenze";
import { useRosa } from "@/lib/rosa"; import { useRosa } from "@/lib/rosa";
import { useGiocatoreCorrente } from "@/lib/user-store"; import { useGiocatoreCorrente } from "@/lib/user-store";
import { useIsAdmin } from "@/lib/ruoli"; import { useIsAdmin } from "@/lib/ruoli";
import { dataOggi } from "@/lib/scout-live";
const ordine: Stato[] = ["presente", "ritardo", "forse", "infortunato", "assente"]; const ordine: Stato[] = ["presente", "ritardo", "forse", "infortunato", "assente"];
export function RosaPresenze({ eventoId }: { eventoId: string }) { export function RosaPresenze({ eventoId, data }: { eventoId: string; data: string }) {
const { risposte, isPending } = usePresenzeEvento(eventoId); const { risposte, isPending } = usePresenzeEvento(eventoId);
const salva = useSalvaPresenza(); const salva = useSalvaPresenza();
const io = useGiocatoreCorrente(); const io = useGiocatoreCorrente();
const admin = useIsAdmin(); const admin = useIsAdmin();
const rosa = useRosa(); const rosa = useRosa();
const [sollecito, setSollecito] = useState(false); const [sollecito, setSollecito] = useState(false);
const passato = data < dataOggi();
const mancanti = rosa.filter((g) => !risposte[g.id]); const mancanti = rosa.filter((g) => !risposte[g.id]);
const risposteN = rosa.length - mancanti.length; const risposteN = rosa.length - mancanti.length;
@@ -91,12 +93,12 @@ export function RosaPresenze({ eventoId }: { eventoId: string }) {
<button <button
key={s} key={s}
type="button" type="button"
disabled={salva.isPending} disabled={salva.isPending || passato}
onClick={() => onClick={() =>
salva.mutate({ eventoId, giocatoreId: io.id, stato: attivo ? null : s }) salva.mutate({ eventoId, giocatoreId: io.id, stato: attivo ? null : s })
} }
className={cn( className={cn(
"rounded-full border border-border px-2.5 py-1.5 text-xs font-semibold transition-all active:scale-95", "rounded-full border border-border px-2.5 py-1.5 text-xs font-semibold transition-all active:scale-95 disabled:opacity-50",
attivo attivo
? cn(statoMeta[s].className, "border-transparent shadow-card") ? cn(statoMeta[s].className, "border-transparent shadow-card")
: "bg-background text-muted-foreground", : "bg-background text-muted-foreground",
@@ -114,7 +116,7 @@ export function RosaPresenze({ eventoId }: { eventoId: string }) {
<button <button
type="button" type="button"
onClick={sollecita} onClick={sollecita}
disabled={sollecito || daSollecitare === 0} disabled={sollecito || daSollecitare === 0 || passato}
className="premi mt-4 flex w-full items-center justify-center gap-2 rounded-2xl bg-primary px-4 py-3 text-sm font-bold text-primary-foreground disabled:opacity-50" className="premi mt-4 flex w-full items-center justify-center gap-2 rounded-2xl bg-primary px-4 py-3 text-sm font-bold text-primary-foreground disabled:opacity-50"
> >
{sollecito ? ( {sollecito ? (
+1 -1
View File
@@ -91,7 +91,7 @@ function AllenamentoDetail() {
</Section> </Section>
<Section titolo="Rosa e presenze"> <Section titolo="Rosa e presenze">
<RosaPresenze eventoId={evento.id} /> <RosaPresenze eventoId={evento.id} data={evento.data} />
</Section> </Section>
</> </>
); );
+1 -1
View File
@@ -263,7 +263,7 @@ function PartitaDetail() {
) : null} ) : null}
<Section titolo="Rosa e presenze"> <Section titolo="Rosa e presenze">
<RosaPresenze eventoId={evento.id} /> <RosaPresenze eventoId={evento.id} data={evento.data} />
</Section> </Section>
</> </>
); );