Boulangerie_Website/frontend/src/pages/AdminUsersPage.jsx
Louis Mazin 1c2ed65db8 clean
2026-09-15 20:35:07 +02:00

172 lines
4.8 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { userApi } from '../api/users';
const AdminUsersPage = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [inviteLink, setInviteLink] = useState('');
const [isCopied, setIsCopied] = useState(false);
const generateInviteLink = async () => {
try {
setError('');
const invitation = await userApi.createInvitation();
const newInviteLink = `${window.location.origin}/register?invite=${invitation.token}`;
setInviteLink(newInviteLink);
setIsCopied(false);
} catch (error) {
setError('Erreur lors de la génération du lien d\'invitation');
console.error(error);
}
};
const copyToClipboard = () => {
if (inviteLink) {
navigator.clipboard.writeText(inviteLink).then(() => {
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
}).catch((error) => {
setError('Impossible de copier le lien.');
console.error(error);
});
}
};
useEffect(() => {
const loadUsers = async () => {
try {
setLoading(true);
const users = await userApi.getUsers();
setUsers(users);
} catch (requestError) {
setError('Erreur lors du chargement des utilisateurs');
console.error(requestError);
} finally {
setLoading(false);
}
};
loadUsers();
}, []);
const handleDeleteUser = async (userId) => {
if (!window.confirm('Êtes-vous sûr de vouloir supprimer cet utilisateur ?')) {
return;
}
try {
await userApi.deleteUser(userId);
setUsers(users.filter(user => user.id !== userId));
} catch (err) {
setError('Erreur lors de la suppression de l\'utilisateur');
console.error(err);
}
};
const handleMakeAdmin = async (userId) => {
if (!window.confirm('Êtes-vous sûr de vouloir promouvoir cet utilisateur ?')) {
return;
}
try {
await userApi.promoteUser(userId);
setUsers(users.map(user =>
user.id === userId ? { ...user, is_admin: true } : user
));
} catch (err) {
setError('Erreur lors de la promotion de l\'utilisateur');
console.error(err);
}
};
if (loading) {
return (
<div className="card admin-page">
<h2>Gestion des comptes</h2>
<p>Chargement des utilisateurs...</p>
</div>
);
}
return (
<div className="card admin-page">
<h2>Gestion des comptes</h2>
{error && <div className="alert alert-danger">{error}</div>}
<div className="admin-toolbar">
<button
onClick={generateInviteLink}
className="btn btn-primary"
>
Inviter un utilisateur
</button>
{inviteLink && (
<div className="invite-link-box">
<input
type="text"
value={inviteLink}
readOnly
className="invite-link-input"
/>
<button
onClick={copyToClipboard}
className="btn btn-secondary"
>
{isCopied ? 'Copié!' : 'Copier'}
</button>
</div>
)}
</div>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Nom d'utilisateur</th>
<th>Rôle</th>
<th>Inscrit le</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{users.map((user) => (
<tr key={user.id}>
<td>{user.username}</td>
<td>
{user.is_admin ? (
<span style={{ color: 'var(--accent)', fontWeight: '500' }}>Administrateur</span>
) : (
<span style={{ color: 'var(--text)', fontWeight: '500' }}>Utilisateur</span>
)}
</td>
<td>{new Date(user.date_joined).toLocaleDateString('fr-FR')}</td>
<td>
<div className="btn-group">
{!user.is_admin && (
<button
onClick={() => handleMakeAdmin(user.id)}
className="btn btn-secondary btn-small"
>
Promouvoir
</button>
)}
<button
onClick={() => handleDeleteUser(user.id)}
className="btn btn-danger btn-small"
>
Supprimer
</button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
export default AdminUsersPage;