Le azioni da referente (/scout, /eventi, sollecito presenze, export CSV scout) non dipendono più da quale giocatore hai scelto di essere in /benvenuto (chiunque poteva scegliere "Ivan Cacciari" senza password), ma da un login reale contro l'account admin di Strapi (già usato per gestire rosa/classifica/storico), verificato via /admin/login. Nuovi src/lib/admin-auth.ts (loginAdmin/logoutAdmin/useAdminSession, sessione locale di 8h) e src/components/crapp/AdminLogin.tsx (form riutilizzabile), raggiungibile da /profilo e dalle schermate riservate. Rimossi adminNomi/ isAdmin da crapp-data.ts. Resta un limite noto: questo protegge solo la UI dell'app, le tabelle Supabase coinvolte hanno ancora RLS aperta e restano scrivibili in diretto con la chiave anon — un fix più ampio (Supabase Auth + RLS reale) è documentato ma non ancora fatto. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
80 lines
2.9 KiB
TypeScript
80 lines
2.9 KiB
TypeScript
import { useState } from "react";
|
|
import { Loader2, Lock } from "lucide-react";
|
|
import { toast } from "sonner";
|
|
import { loginAdmin, logoutAdmin, useAdminSession } from "@/lib/admin-auth";
|
|
|
|
/** Sblocca le funzioni admin (scout, gestione eventi, sollecito presenze) con la password
|
|
* dell'account Strapi dei referenti — non più scegliendo semplicemente il proprio nome. */
|
|
export function AdminLogin() {
|
|
const { attivo, email } = useAdminSession();
|
|
const [inputEmail, setInputEmail] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [inCorso, setInCorso] = useState(false);
|
|
|
|
if (attivo) {
|
|
return (
|
|
<div className="flex items-center justify-between gap-3 rounded-2xl bg-secondary/60 p-3">
|
|
<span className="min-w-0 text-sm">
|
|
<span className="block font-semibold">Admin attivo</span>
|
|
<span className="block truncate text-[11px] text-muted-foreground">{email}</span>
|
|
</span>
|
|
<button
|
|
type="button"
|
|
onClick={() => {
|
|
logoutAdmin();
|
|
toast.success("Uscito dalla modalità admin");
|
|
}}
|
|
className="shrink-0 rounded-full bg-card px-3 py-1.5 text-[11px] font-bold uppercase text-foreground shadow-card"
|
|
>
|
|
Esci
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
async function accedi(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
if (!inputEmail || !password || inCorso) return;
|
|
setInCorso(true);
|
|
const risultato = await loginAdmin(inputEmail, password);
|
|
setInCorso(false);
|
|
if (risultato.ok) {
|
|
setPassword("");
|
|
toast.success("Modalità admin attiva");
|
|
} else {
|
|
toast.error(risultato.errore);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<form onSubmit={accedi} className="space-y-2 rounded-2xl bg-secondary/60 p-3">
|
|
<p className="inline-flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-wide text-muted-foreground">
|
|
<Lock className="h-3.5 w-3.5" /> Accedi come admin (account Strapi)
|
|
</p>
|
|
<input
|
|
type="email"
|
|
value={inputEmail}
|
|
onChange={(e) => setInputEmail(e.target.value)}
|
|
placeholder="Email"
|
|
autoComplete="username"
|
|
className="w-full rounded-xl border border-border bg-background px-3 py-2 text-sm"
|
|
/>
|
|
<input
|
|
type="password"
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
placeholder="Password"
|
|
autoComplete="current-password"
|
|
className="w-full rounded-xl border border-border bg-background px-3 py-2 text-sm"
|
|
/>
|
|
<button
|
|
type="submit"
|
|
disabled={inCorso}
|
|
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-grad py-2.5 text-sm font-bold uppercase text-accent-foreground shadow-pop disabled:opacity-50"
|
|
>
|
|
{inCorso ? <Loader2 className="h-4 w-4 animate-spin" /> : null} Accedi
|
|
</button>
|
|
</form>
|
|
);
|
|
}
|