Apre il voto MVP due ore dopo l'inizio e lo riserva ai presenti.

La votazione non dipendeva dal tempo ma dal risultato: compariva solo con un
referto CSI o uno scout salvato, e chiunque avesse un profilo poteva votare.
Ora `votoMvpAperto()` la apre due ore dopo `data`+`ora` dell'evento, il pannello
sta in una sezione sua e votano — e sono votabili — solo i presenti (o in
ritardo) di quell'evento.

I voti passano dall'id scout/CSI a quello dell'evento CrAPP: home e classifica
leggono il vincitore tramite la mappa data → evento che avevano già. Le regole
sono applicative, non RLS: chi scrive su PostgREST le aggira, come già annotato
tra i limiti noti del modulo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-06 22:11:26 +02:00
co-authored by Claude Opus 5
parent da669db1eb
commit f149d02e9a
8 changed files with 105 additions and 27 deletions
+7 -6
View File
@@ -56,12 +56,13 @@ function Classifica() {
const eventoIdPerData = new Map(
eventi.filter((e) => e.tipo === "partita").map((e) => [e.data, e.id]),
);
// I voti MVP sono legati all'evento CrAPP, non al referto CSI né allo scout.
const mvpPerData = (data: string) => mvpPerMatch[eventoIdPerData.get(data) ?? ""] ?? "";
const tuttiMatch = csiGiocate.length
? csiGiocate.map((p) => ({
...matchDaPartitaCsi(p),
mvp: mvpPerMatch[p.id] ?? "",
scout: false,
}))
? csiGiocate.map((p) => {
const m = matchDaPartitaCsi(p);
return { ...m, mvp: mvpPerData(m.data), scout: false };
})
: scoutMatches.map((m) => ({
id: m.id,
data: m.data,
@@ -70,7 +71,7 @@ function Classifica() {
setNostri: m.setNostri,
setLoro: m.setLoro,
parziali: m.parziali,
mvp: mvpPerMatch[m.id] ?? "",
mvp: mvpPerData(m.data),
scout: true,
}));
+7 -7
View File
@@ -49,15 +49,15 @@ function Index() {
const votiMvp = useVotiMvp();
const mvpPerMatch = vincitoriMvp(votiMvp.data ?? []);
const csiGiocate = csi ? partiteGiocate(csi.partite) : [];
const ultima = csiGiocate[0]
? { ...matchDaPartitaCsi(csiGiocate[0]), mvp: mvpPerMatch[csiGiocate[0].id] ?? "" }
: scoutMatches[0]
? { ...scoutMatches[0], mvp: mvpPerMatch[scoutMatches[0].id] ?? "" }
: null;
const ultimaBase = csiGiocate[0] ? matchDaPartitaCsi(csiGiocate[0]) : (scoutMatches[0] ?? null);
const obiettivi = useObiettivi();
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)
const eventoUltima = ultimaBase
? (eventi.find((e) => e.tipo === "partita" && e.data === ultimaBase.data) ?? null)
: null;
// I voti MVP sono legati all'evento CrAPP, non al referto CSI né allo scout.
const ultima = ultimaBase
? { ...ultimaBase, mvp: (eventoUltima && mvpPerMatch[eventoUltima.id]) ?? "" }
: null;
if (!giocatore) return null;
+6 -4
View File
@@ -169,14 +169,16 @@ function PartitaDetail() {
</div>
))}
</div>
<p className="mt-3 text-center text-xs font-semibold text-muted-foreground">
MVP eletto dalla squadra
</p>
<VotazioneMvp matchId={match.id} />
</div>
</Section>
) : null}
<Section titolo="MVP eletto dalla squadra">
<div className="rounded-3xl bg-card p-5 shadow-card">
<VotazioneMvp evento={evento} />
</div>
</Section>
{match ? (
<Section titolo="Badge votati dai compagni">
<VotoSocial matchId={match.id} />