import { useEffect, useState } from 'react' import { ShieldCheck, UserPlus, Trash2, Loader2, Crown, Mail } from 'lucide-react' import { useApp } from '../lib/AppContext' import { useFeedback } from '../lib/feedback' import { MemberRole, ROLE_LABELS } from '../lib/types' import { AdminUser, adminListUsers, adminCreateUser, adminDeleteUser, adminUpdateUser } from '../lib/admin' import { Modal, Select, EmptyState } from '../components/ui' import PageHeader from '../components/PageHeader' export default function Admin(): JSX.Element { const { profile } = useApp() const { toast, confirm } = useFeedback() const [users, setUsers] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [creating, setCreating] = useState(false) const load = async (): Promise => { setLoading(true) setError('') try { setUsers(await adminListUsers()) } catch (e) { setError((e as Error).message) } finally { setLoading(false) } } useEffect(() => { load() }, []) const setRole = async (u: AdminUser, role: MemberRole): Promise => { setUsers((list) => list.map((x) => (x.id === u.id ? { ...x, role } : x))) try { await adminUpdateUser(u.id, { role }) } catch (e) { setError((e as Error).message) load() } } const toggleAdmin = async (u: AdminUser): Promise => { try { await adminUpdateUser(u.id, { is_admin: !u.is_admin }) setUsers((list) => list.map((x) => (x.id === u.id ? { ...x, is_admin: !u.is_admin } : x))) } catch (e) { setError((e as Error).message) } } const remove = async (u: AdminUser): Promise => { const ok = await confirm({ title: 'Supprimer ce compte ?', message: `${u.full_name} (${u.email}) sera définitivement supprimé.`, danger: true, confirmLabel: 'Supprimer' }) if (!ok) return try { await adminDeleteUser(u.id) setUsers((list) => list.filter((x) => x.id !== u.id)) toast('Compte supprimé.', 'success') } catch (e) { setError((e as Error).message) } } return (
{error && (
{error}
)} {loading ? (
) : users.length === 0 ? ( } text="Aucun compte." /> ) : (
{users.map((u) => { const isMe = u.id === profile?.id return ( ) })}
Membre Rôle Admin Actions
{u.full_name} {isMe && (moi)}
{u.email}
)}
{creating && ( setCreating(false)} onCreated={async () => { setCreating(false) await load() toast('Compte créé.', 'success') }} /> )}
) } function CreateUserModal({ onClose, onCreated }: { onClose: () => void onCreated: () => Promise }): JSX.Element { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [fullName, setFullName] = useState('') const [role, setRole] = useState('programmer') const [isAdmin, setIsAdmin] = useState(false) const [busy, setBusy] = useState(false) const [error, setError] = useState('') const submit = async (): Promise => { setError('') if (!email.trim() || password.length < 6) { setError('Email valide et mot de passe (6+ caractères) requis.') return } setBusy(true) try { await adminCreateUser({ email: email.trim(), password, full_name: fullName.trim(), role, is_admin: isAdmin }) await onCreated() } catch (e) { setError((e as Error).message) setBusy(false) } } return ( setFullName(e.target.value)} /> setEmail(e.target.value)} /> setPassword(e.target.value)} /> {error &&

{error}

}

Communique l'email et le mot de passe provisoire au membre.

) }