Rende raggiungibile il voto MVP dalle card dei risultati

"Ultima partita" in home e le card di "Storico match" in squadra ora
sono link a /partita/$id quando esiste un evento di calendario con la
stessa data del risultato (CSI o scout), con un'indicazione "Vota MVP"
quando non è ancora stato eletto. Prima erano card statiche: per votare
bisognava trovare la partita a mano dal calendario.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 13:56:56 +02:00
co-authored by Claude Sonnet 5
parent 1a93c7657a
commit f6036f21ec
2 changed files with 72 additions and 29 deletions
+42 -24
View File
@@ -56,6 +56,9 @@ function Index() {
: null; : null;
const obiettivi = useObiettivi(); const obiettivi = useObiettivi();
const obiettivo = obiettivi.find((o) => progressoObiettivo(o) < 100) ?? obiettivi[0] ?? null; const obiettivo = obiettivi.find((o) => progressoObiettivo(o) < 100) ?? obiettivi[0] ?? null;
const eventoUltima = ultima
? (eventi.find((e) => e.tipo === "partita" && e.data === ultima.data) ?? null)
: null;
if (!giocatore) return null; if (!giocatore) return null;
@@ -143,30 +146,45 @@ function Index() {
} }
> >
{ultima ? ( {ultima ? (
<div className="premi rounded-3xl bg-card p-4 shadow-card"> (() => {
<div className="flex items-center justify-between gap-3"> const corpo = (
<div className="min-w-0"> <>
<p className="truncate text-sm font-bold">CRAP Volley vs {ultima.avversario}</p> <div className="flex items-center justify-between gap-3">
<p className="text-xs text-muted-foreground"> <div className="min-w-0">
{ultima.casa ? "In casa" : "Trasferta"} <p className="truncate text-sm font-bold">CRAP Volley vs {ultima.avversario}</p>
{ultima.mvp ? ` · MVP ${ultima.mvp}` : ""} <p className="text-xs text-muted-foreground">
</p> {ultima.casa ? "In casa" : "Trasferta"}
</div> {ultima.mvp ? ` · MVP ${ultima.mvp}` : " · MVP da votare"}
<p className="font-display text-3xl leading-none text-accent"> </p>
{ultima.setNostri}-{ultima.setLoro} </div>
</p> <p className="font-display text-3xl leading-none text-accent">
</div> {ultima.setNostri}-{ultima.setLoro}
<div className="mt-3 flex flex-wrap gap-1.5"> </p>
{ultima.parziali.map((p, i) => ( </div>
<span <div className="mt-3 flex flex-wrap gap-1.5">
key={i} {ultima.parziali.map((p, i) => (
className="rounded-lg bg-secondary px-2 py-1 text-[11px] font-semibold tabular-nums" <span
> key={i}
{p[0]}-{p[1]} className="rounded-lg bg-secondary px-2 py-1 text-[11px] font-semibold tabular-nums"
</span> >
))} {p[0]}-{p[1]}
</div> </span>
</div> ))}
</div>
</>
);
return eventoUltima ? (
<Link
to="/partita/$id"
params={{ id: eventoUltima.id }}
className="premi block rounded-3xl bg-card p-4 shadow-card active:scale-[0.99]"
>
{corpo}
</Link>
) : (
<div className="premi rounded-3xl bg-card p-4 shadow-card">{corpo}</div>
);
})()
) : ( ) : (
<p className="rounded-3xl bg-card p-4 text-xs text-muted-foreground shadow-card"> <p className="rounded-3xl bg-card p-4 text-xs text-muted-foreground shadow-card">
Nessun risultato disponibile. Nessun risultato disponibile.
+30 -5
View File
@@ -1,6 +1,6 @@
import { useState } from "react"; import { useState } from "react";
import { createFileRoute } from "@tanstack/react-router"; import { createFileRoute, Link } from "@tanstack/react-router";
import { Cake, ChevronDown, Crown } from "lucide-react"; import { Cake, ChevronDown, ChevronRight, Crown } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { PageHeader, Section } from "@/components/crapp/ui-bits"; import { PageHeader, Section } from "@/components/crapp/ui-bits";
import { Avatar } from "@/components/crapp/Avatar"; import { Avatar } from "@/components/crapp/Avatar";
@@ -19,6 +19,7 @@ import { Barra } from "@/components/motion/Barra";
import { Numero } from "@/components/motion/Numero"; import { Numero } from "@/components/motion/Numero";
import { useScoutMatches } from "@/lib/scout-store"; import { useScoutMatches } from "@/lib/scout-store";
import { useVotiMvp, vincitoriMvp } from "@/lib/mvp-voti"; import { useVotiMvp, vincitoriMvp } from "@/lib/mvp-voti";
import { useEventi } from "@/lib/eventi";
import { BadgeDrawer } from "@/components/crapp/BadgeDrawer"; import { BadgeDrawer } from "@/components/crapp/BadgeDrawer";
import { import {
badgeDefs, badgeDefs,
@@ -95,6 +96,10 @@ function Squadra() {
const max = ordinati[0] ? valore(ordinati[0], criterio) || 1 : 1; const max = ordinati[0] ? valore(ordinati[0], criterio) || 1 : 1;
const { data: csi } = useCsi(); const { data: csi } = useCsi();
const csiGiocate = csi ? partiteGiocate(csi.partite) : []; const csiGiocate = csi ? partiteGiocate(csi.partite) : [];
const { eventi } = useEventi();
const eventoIdPerData = new Map(
eventi.filter((e) => e.tipo === "partita").map((e) => [e.data, e.id]),
);
const tuttiMatch = csiGiocate.length const tuttiMatch = csiGiocate.length
? csiGiocate.map((p) => ({ ? csiGiocate.map((p) => ({
...matchDaPartitaCsi(p), ...matchDaPartitaCsi(p),
@@ -313,8 +318,9 @@ function Squadra() {
<div className="space-y-3"> <div className="space-y-3">
{tuttiMatch.map((m) => { {tuttiMatch.map((m) => {
const vinta = m.setNostri > m.setLoro; const vinta = m.setNostri > m.setLoro;
return ( const eventoId = eventoIdPerData.get(m.data);
<article key={m.id} className="rounded-3xl bg-card p-4 shadow-card"> const contenuto = (
<>
<div className="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3"> <div className="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3">
<div className="min-w-0"> <div className="min-w-0">
<p className="truncate text-sm font-bold"> <p className="truncate text-sm font-bold">
@@ -337,7 +343,7 @@ function Squadra() {
{m.setNostri}-{m.setLoro} {m.setNostri}-{m.setLoro}
</span> </span>
</div> </div>
<div className="mt-3 flex flex-wrap gap-1.5"> <div className="mt-3 flex flex-wrap items-center gap-1.5">
{m.parziali.map((p, i) => ( {m.parziali.map((p, i) => (
<span <span
key={i} key={i}
@@ -349,7 +355,26 @@ function Squadra() {
{p[0]}-{p[1]} {p[0]}-{p[1]}
</span> </span>
))} ))}
{eventoId && !m.mvp ? (
<span className="ml-auto inline-flex items-center gap-0.5 text-[11px] font-bold uppercase text-accent">
Vota MVP <ChevronRight className="h-3.5 w-3.5" />
</span>
) : null}
</div> </div>
</>
);
return eventoId ? (
<Link
key={m.id}
to="/partita/$id"
params={{ id: eventoId }}
className="premi block rounded-3xl bg-card p-4 shadow-card active:scale-[0.99]"
>
{contenuto}
</Link>
) : (
<article key={m.id} className="rounded-3xl bg-card p-4 shadow-card">
{contenuto}
</article> </article>
); );
})} })}