2026-09-06 00:08:58 +02:00
|
|
|
import { useState } from "react";
|
|
|
|
|
import { BellRing, Loader2 } from "lucide-react";
|
2026-08-06 08:36:47 +02:00
|
|
|
import { toast } from "sonner";
|
|
|
|
|
import { cn } from "@/lib/utils";
|
2026-09-05 12:42:24 +02:00
|
|
|
import { Card } from "@/components/crapp/ui-bits";
|
2026-09-03 10:17:03 +02:00
|
|
|
import { nomeCompleto, useGiocatoriSquadra } from "@/lib/giocatori-squadra";
|
2026-09-08 10:00:52 +02:00
|
|
|
import { useGiocatoreBase } from "@/lib/user-store";
|
2026-09-06 12:05:39 +02:00
|
|
|
import { intestazioniAutenticate } from "@/lib/auth";
|
2026-09-06 00:08:58 +02:00
|
|
|
import { useIsAdmin } from "@/lib/ruoli";
|
2026-09-07 14:06:15 +02:00
|
|
|
import {
|
|
|
|
|
mediaPartita,
|
|
|
|
|
sondaggioAperto,
|
|
|
|
|
sondaggioTerminato,
|
|
|
|
|
useCacche,
|
|
|
|
|
useSalvaCacche,
|
|
|
|
|
} from "@/lib/cacche";
|
2026-08-06 08:36:47 +02:00
|
|
|
|
|
|
|
|
const opzioni = [0, 1, 2, 3, 4, 5];
|
|
|
|
|
|
|
|
|
|
/** Sondaggio goliardico pre-partita: quante cacche prima del fischio d'inizio. */
|
2026-09-06 00:08:58 +02:00
|
|
|
export function SondaggioCacche({
|
|
|
|
|
eventoId,
|
|
|
|
|
dataEvento,
|
2026-09-07 14:06:15 +02:00
|
|
|
oraEvento,
|
2026-09-06 00:08:58 +02:00
|
|
|
}: {
|
|
|
|
|
eventoId: string;
|
|
|
|
|
dataEvento: string;
|
2026-09-07 14:06:15 +02:00
|
|
|
oraEvento: string;
|
2026-09-06 00:08:58 +02:00
|
|
|
}) {
|
2026-09-08 10:00:52 +02:00
|
|
|
// Solo `.id` serve qui: `useGiocatoreBase` basta, niente statistiche.
|
|
|
|
|
const io = useGiocatoreBase();
|
2026-08-06 08:36:47 +02:00
|
|
|
const { righe } = useCacche();
|
|
|
|
|
const salva = useSalvaCacche();
|
2026-09-03 10:17:03 +02:00
|
|
|
const { righe: squadra } = useGiocatoriSquadra();
|
2026-09-06 00:08:58 +02:00
|
|
|
const admin = useIsAdmin();
|
|
|
|
|
const [avviso, setAvviso] = useState(false);
|
2026-08-06 08:36:47 +02:00
|
|
|
|
|
|
|
|
const dellaPartita = righe.filter((r) => r.evento_id === eventoId);
|
|
|
|
|
const mia = dellaPartita.find((r) => r.giocatore_id === io?.id);
|
|
|
|
|
const media = mediaPartita(righe, eventoId);
|
|
|
|
|
const classifica = [...dellaPartita]
|
|
|
|
|
.sort((a, b) => b.quantita - a.quantita)
|
|
|
|
|
.slice(0, 3)
|
2026-09-03 10:17:03 +02:00
|
|
|
.map((r) => {
|
|
|
|
|
const g = squadra.find((g) => g.id === r.giocatore_id);
|
|
|
|
|
return { ...r, nome: g ? nomeCompleto(g) : "—" };
|
|
|
|
|
});
|
2026-08-06 08:36:47 +02:00
|
|
|
|
|
|
|
|
async function rispondi(quantita: number) {
|
|
|
|
|
if (!io) return;
|
|
|
|
|
try {
|
|
|
|
|
await salva.mutateAsync({ evento_id: eventoId, giocatore_id: io.id, quantita });
|
|
|
|
|
toast.success("Risposta registrata 💩");
|
|
|
|
|
} catch {
|
|
|
|
|
toast.error("Non sono riuscito a salvare la risposta");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-06 00:08:58 +02:00
|
|
|
async function avvisaTutti() {
|
|
|
|
|
setAvviso(true);
|
|
|
|
|
try {
|
|
|
|
|
const res = await fetch("/api/public/apri-sondaggio", {
|
|
|
|
|
method: "POST",
|
2026-09-06 12:05:39 +02:00
|
|
|
headers: { "Content-Type": "application/json", ...(await intestazioniAutenticate()) },
|
2026-09-06 00:08:58 +02:00
|
|
|
body: JSON.stringify({ eventoId }),
|
|
|
|
|
});
|
|
|
|
|
if (!res.ok) throw new Error();
|
|
|
|
|
const dati = (await res.json()) as { inviate: number; destinatari: number };
|
|
|
|
|
toast.success(
|
|
|
|
|
dati.inviate > 0
|
|
|
|
|
? `Notifica inviata a ${dati.inviate} dispositivi`
|
|
|
|
|
: "Nessun dispositivo con le notifiche attive",
|
|
|
|
|
);
|
|
|
|
|
} catch {
|
|
|
|
|
toast.error("Non sono riuscito a inviare la notifica");
|
|
|
|
|
} finally {
|
|
|
|
|
setAvviso(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-07 14:06:15 +02:00
|
|
|
if (!sondaggioAperto(dataEvento, oraEvento)) {
|
2026-09-06 00:08:58 +02:00
|
|
|
return (
|
|
|
|
|
<Card>
|
|
|
|
|
<p className="text-xs font-bold uppercase tracking-wide text-muted-foreground">
|
|
|
|
|
💩 Sondaggio pre-partita
|
|
|
|
|
</p>
|
|
|
|
|
<p className="mt-1 text-xs text-muted-foreground">
|
2026-09-07 14:06:15 +02:00
|
|
|
{sondaggioTerminato(dataEvento, oraEvento)
|
|
|
|
|
? "Sondaggio chiuso: era aperto fino al fischio d'inizio."
|
|
|
|
|
: "Apre alle 8:00 del giorno della partita: riceverai una notifica."}
|
2026-09-06 00:08:58 +02:00
|
|
|
</p>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-06 08:36:47 +02:00
|
|
|
return (
|
2026-09-05 12:42:24 +02:00
|
|
|
<Card>
|
2026-08-06 08:36:47 +02:00
|
|
|
<div className="flex items-center justify-between gap-2">
|
2026-09-05 12:42:24 +02:00
|
|
|
<p className="text-xs font-bold uppercase tracking-wide text-muted-foreground">
|
2026-08-06 08:36:47 +02:00
|
|
|
💩 Sondaggio pre-partita
|
|
|
|
|
</p>
|
2026-09-05 12:42:24 +02:00
|
|
|
<span className="rounded-full bg-secondary px-2.5 py-1 text-xs font-bold uppercase text-muted-foreground">
|
2026-08-06 08:36:47 +02:00
|
|
|
{dellaPartita.length} risposte
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
2026-09-05 12:42:24 +02:00
|
|
|
<p className="mt-1 text-xs text-muted-foreground">
|
2026-08-06 08:36:47 +02:00
|
|
|
Quante cacche hai fatto prima di questa partita? Dato scientifico fondamentale.
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<div className="mt-3 flex flex-wrap gap-1.5">
|
|
|
|
|
{opzioni.map((n) => (
|
|
|
|
|
<button
|
|
|
|
|
key={n}
|
|
|
|
|
type="button"
|
|
|
|
|
disabled={!io || salva.isPending}
|
|
|
|
|
onClick={() => rispondi(n)}
|
|
|
|
|
className={cn(
|
|
|
|
|
"min-w-11 rounded-xl px-3 py-2 text-sm font-bold tabular-nums transition-transform active:scale-90 disabled:opacity-50",
|
|
|
|
|
mia?.quantita === n
|
|
|
|
|
? "bg-accent text-accent-foreground shadow-pop"
|
|
|
|
|
: "bg-secondary text-foreground",
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
{n === 5 ? "5+" : n}
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-09-05 12:42:24 +02:00
|
|
|
<div className="mt-3 flex flex-wrap items-center gap-2 text-xs">
|
2026-08-06 08:36:47 +02:00
|
|
|
<span className="rounded-full bg-secondary px-2.5 py-1 font-semibold">
|
|
|
|
|
Media squadra {media}
|
|
|
|
|
</span>
|
|
|
|
|
{classifica.map((r, i) => (
|
2026-09-01 13:38:33 +02:00
|
|
|
<span
|
|
|
|
|
key={r.giocatore_id}
|
|
|
|
|
className="rounded-full bg-secondary px-2.5 py-1 font-semibold"
|
|
|
|
|
>
|
2026-08-06 08:36:47 +02:00
|
|
|
{i === 0 ? "🥇" : i === 1 ? "🥈" : "🥉"} {r.nome} · {r.quantita}
|
|
|
|
|
</span>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
2026-09-06 00:08:58 +02:00
|
|
|
|
|
|
|
|
{admin ? (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={avvisaTutti}
|
|
|
|
|
disabled={avviso}
|
|
|
|
|
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"
|
|
|
|
|
>
|
|
|
|
|
{avviso ? <Loader2 className="h-4 w-4 animate-spin" /> : <BellRing className="h-4 w-4" />}
|
|
|
|
|
Avvisa tutti del sondaggio
|
|
|
|
|
</button>
|
|
|
|
|
) : null}
|
2026-09-05 12:42:24 +02:00
|
|
|
</Card>
|
2026-08-06 08:36:47 +02:00
|
|
|
);
|
|
|
|
|
}
|