Initial commit
This commit is contained in:
commit
48ed7fe65e
209 files changed
+49979
No files matched your search
@@ -0,0 +1,114 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { api } from '../../api.js';
|
||||
import ConfirmModal from '../../components/ConfirmModal.jsx';
|
||||
import { fmt, Badge } from './adminHelpers.jsx';
|
||||
|
||||
export default function UsersSection({ currentUserId }) {
|
||||
const [users, setUsers] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [err, setErr] = useState(null);
|
||||
const [confirmAction, setConfirmAction] = useState(null);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await api.get('/admin/users');
|
||||
setUsers(data);
|
||||
} catch (e) { setErr(e.message); }
|
||||
finally { setLoading(false); }
|
||||
}, []);
|
||||
|
||||
useEffect(() => { load(); }, [load]);
|
||||
|
||||
const toggleRole = (u) => {
|
||||
const newRole = u.role === 'admin' ? 'user' : 'admin';
|
||||
setConfirmAction({
|
||||
title: 'Changer le rôle',
|
||||
message: `Changer le rôle de ${u.display_name || u.email} → ${newRole === 'admin' ? 'Administrateur' : 'Utilisateur'} ?`,
|
||||
confirmLabel: 'Confirmer',
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
await api.patch(`/admin/users/${u.id}/role`, { role: newRole });
|
||||
load();
|
||||
} catch (e) { setErr('Erreur : ' + e.message); }
|
||||
finally { setConfirmAction(null); }
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const deleteUser = (u) => {
|
||||
setConfirmAction({
|
||||
title: 'Supprimer l\'utilisateur',
|
||||
message: `Supprimer définitivement ${u.display_name || u.email} ? Toutes ses données seront effacées.`,
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
await api.del(`/admin/users/${u.id}`);
|
||||
load();
|
||||
} catch (e) { setErr('Erreur : ' + e.message); }
|
||||
finally { setConfirmAction(null); }
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (loading) return <p style={{ color: 'var(--text-muted)' }}>Chargement…</p>;
|
||||
if (err) return <p style={{ color: '#ef4444' }}>{err}</p>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="card">
|
||||
<h3 style={{ margin: '0 0 4px' }}>Comptes utilisateurs</h3>
|
||||
<p className="text-muted" style={{ margin: '0 0 20px', fontSize: 'var(--fs-sm)' }}>
|
||||
{users.length} utilisateur{users.length !== 1 ? 's' : ''} enregistré{users.length !== 1 ? 's' : ''}
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width: 36 }}>ID</th>
|
||||
<th>Nom</th>
|
||||
<th>Email</th>
|
||||
<th>Rôle</th>
|
||||
<th>Créé le</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{users.map(u => (
|
||||
<tr key={u.id}>
|
||||
<td style={{ color: 'var(--text-muted)' }}>{u.id}</td>
|
||||
<td style={{ fontWeight: 500 }}>{u.display_name || <em style={{ color: 'var(--text-muted)' }}>—</em>}</td>
|
||||
<td>{u.email}</td>
|
||||
<td><Badge role={u.role} /></td>
|
||||
<td style={{ color: 'var(--text-muted)', fontSize: 12 }}>{fmt(u.created_at)}</td>
|
||||
<td>
|
||||
<div style={{ display: 'flex', gap: 8 }}>
|
||||
<button
|
||||
className="btn btn-sm btn-outline"
|
||||
onClick={() => toggleRole(u)}
|
||||
disabled={u.id === currentUserId && u.role === 'admin'}
|
||||
title={u.id === currentUserId ? 'Vous ne pouvez pas vous rétrograder' : ''}
|
||||
>
|
||||
{u.role === 'admin' ? '→ Utilisateur' : '→ Admin'}
|
||||
</button>
|
||||
{u.id !== currentUserId && (
|
||||
<button className="btn btn-sm btn-danger" onClick={() => deleteUser(u)}>
|
||||
Supprimer
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ConfirmModal
|
||||
open={!!confirmAction}
|
||||
title={confirmAction?.title}
|
||||
message={confirmAction?.message}
|
||||
confirmLabel={confirmAction?.confirmLabel}
|
||||
onConfirm={confirmAction?.onConfirm}
|
||||
onCancel={() => setConfirmAction(null)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user