Apre il sondaggio pre-partita alle 8:00 con avviso push manuale.

Il sondaggio cacche era votabile in qualsiasi momento, anche settimane
prima della partita. Ora `sondaggioAperto()` lo sblocca alle 8:00 del
giorno della partita e prima la card mostra solo l'avviso di apertura.

Aggiunge la route `POST /api/public/apri-sondaggio` e, per gli
amministratori, il pulsante «Avvisa tutti del sondaggio» nella card:
manda la push a tutti i dispositivi iscritti, con lo stesso meccanismo
del sollecito presenze. Nessun invio automatico.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-06 00:08:58 +02:00
co-authored by Claude Opus 5
parent a7d0f5af5b
commit 73902cc0a4
10 changed files with 173 additions and 7 deletions
+60 -2
View File
@@ -1,18 +1,29 @@
import { useState } from "react";
import { BellRing, Loader2 } from "lucide-react";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import { Card } from "@/components/crapp/ui-bits";
import { nomeCompleto, useGiocatoriSquadra } from "@/lib/giocatori-squadra";
import { useGiocatoreCorrente } from "@/lib/user-store";
import { mediaPartita, useCacche, useSalvaCacche } from "@/lib/cacche";
import { useIsAdmin } from "@/lib/ruoli";
import { mediaPartita, sondaggioAperto, useCacche, useSalvaCacche } from "@/lib/cacche";
const opzioni = [0, 1, 2, 3, 4, 5];
/** Sondaggio goliardico pre-partita: quante cacche prima del fischio d'inizio. */
export function SondaggioCacche({ eventoId }: { eventoId: string }) {
export function SondaggioCacche({
eventoId,
dataEvento,
}: {
eventoId: string;
dataEvento: string;
}) {
const io = useGiocatoreCorrente();
const { righe } = useCacche();
const salva = useSalvaCacche();
const { righe: squadra } = useGiocatoriSquadra();
const admin = useIsAdmin();
const [avviso, setAvviso] = useState(false);
const dellaPartita = righe.filter((r) => r.evento_id === eventoId);
const mia = dellaPartita.find((r) => r.giocatore_id === io?.id);
@@ -35,6 +46,41 @@ export function SondaggioCacche({ eventoId }: { eventoId: string }) {
}
}
async function avvisaTutti() {
setAvviso(true);
try {
const res = await fetch("/api/public/apri-sondaggio", {
method: "POST",
headers: { "Content-Type": "application/json" },
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);
}
}
if (!sondaggioAperto(dataEvento)) {
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">
Apre alle 8:00 del giorno della partita: riceverai una notifica.
</p>
</Card>
);
}
return (
<Card>
<div className="flex items-center justify-between gap-2">
@@ -81,6 +127,18 @@ export function SondaggioCacche({ eventoId }: { eventoId: string }) {
</span>
))}
</div>
{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}
</Card>
);
}