Ajoute les suggestions de questions des Citoyens et les emails sur Admin
Build and deploy / deploy (push) Successful in 35s
Build and deploy / deploy (push) Successful in 35s
Chaque Citoyen peut proposer une question pour Le Char depuis /profile (upsert via submit_chariot_question, figée dès la date du Tribunal comme les scores d'Icare). Les Archontes modèrent ces suggestions directement sur /char/questions (ajouter à la banque ou rejeter). /admin affiche maintenant l'email de chaque membre via une nouvelle RPC admin_list_members(), seule façon d'exposer auth.users.email sans passer par la service_role key côté client. Corrige au passage deux bugs découverts pendant les tests : la policy interne de admin_list_members() référençait id/role sans les qualifier, ambigus avec les colonnes du RETURNS TABLE (erreur Postgres 42702) ; et l'auteur d'une suggestion s'affichait toujours comme "un Citoyen" car le embed profiles(...) avait été mal retypé en tableau alors qu'il est retourné en objet à l'exécution.
This commit is contained in:
@@ -12,6 +12,7 @@ type Member = {
|
||||
role: string;
|
||||
pseudo_locked: boolean;
|
||||
avatar_url: string | null;
|
||||
email: string;
|
||||
};
|
||||
|
||||
function MemberRow({ member, isSelf }: { member: Member; isSelf: boolean }) {
|
||||
@@ -78,14 +79,17 @@ function MemberRow({ member, isSelf }: { member: Member; isSelf: boolean }) {
|
||||
|
||||
return (
|
||||
<li className="marble-surface flex flex-col gap-2 rounded-lg border border-gold/25 px-4 py-3 shadow-sm sm:flex-row sm:items-center sm:gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar pseudo={member.pseudo} avatarUrl={member.avatar_url} size="sm" />
|
||||
<input
|
||||
type="text"
|
||||
value={pseudo}
|
||||
onChange={(event) => setPseudo(event.target.value)}
|
||||
className="w-full flex-1 rounded-md border border-gold/30 bg-white/50 px-2 py-1 text-sm text-text-marble outline-none focus:border-gold sm:w-auto"
|
||||
/>
|
||||
<div className="flex flex-1 flex-col gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar pseudo={member.pseudo} avatarUrl={member.avatar_url} size="sm" />
|
||||
<input
|
||||
type="text"
|
||||
value={pseudo}
|
||||
onChange={(event) => setPseudo(event.target.value)}
|
||||
className="w-full flex-1 rounded-md border border-gold/30 bg-white/50 px-2 py-1 text-sm text-text-marble outline-none focus:border-gold sm:w-auto"
|
||||
/>
|
||||
</div>
|
||||
<p className="truncate pl-10 text-xs text-text-mut">{member.email}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
|
||||
@@ -25,10 +25,7 @@ export default async function AdminPage() {
|
||||
redirect("/leaderboard");
|
||||
}
|
||||
|
||||
const { data: members } = await supabase
|
||||
.from("profiles")
|
||||
.select("id, pseudo, role, pseudo_locked, avatar_url")
|
||||
.order("pseudo", { ascending: true });
|
||||
const { data: members } = await supabase.rpc("admin_list_members");
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-3xl px-4 py-8">
|
||||
|
||||
Reference in New Issue
Block a user