Refactor UserManagement component layout: Update user display to a grid format for improved responsiveness, enhance user information presentation with clearer stats and action buttons, and streamline the overall UI for better user experience.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m3s

This commit is contained in:
Julien Froidefond
2025-12-16 16:55:40 +01:00
parent ec965cd59d
commit 5eddf36121

View File

@@ -196,108 +196,117 @@ export default function UserManagement() {
Aucun utilisateur trouvé Aucun utilisateur trouvé
</div> </div>
) : ( ) : (
users.map((user) => { <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4">
return ( {users.map((user) => {
<Card key={user.id} variant="default" className="p-3 sm:p-4"> return (
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-2"> <Card key={user.id} variant="default" className="p-3">
<div className="flex gap-2 sm:gap-3 items-center flex-1 min-w-0"> <div className="flex flex-col gap-2">
{/* Avatar */} {/* Header avec avatar et nom */}
<Avatar <div className="flex items-center gap-2">
src={user.avatar} <Avatar
username={user.username} src={user.avatar}
size="sm" username={user.username}
className="flex-shrink-0" size="sm"
borderClassName="border-2 border-pixel-gold/50" className="flex-shrink-0"
/> borderClassName="border-2 border-pixel-gold/50"
<div className="flex-1 min-w-0"> />
<div className="flex items-center gap-1.5 sm:gap-2 flex-wrap"> <div className="flex-1 min-w-0">
<h3 className="text-pixel-gold font-bold text-sm sm:text-base break-words"> <h3 className="text-pixel-gold font-bold text-sm truncate">
{user.username} {user.username}
</h3> </h3>
<span className="text-[10px] sm:text-xs text-gray-500 whitespace-nowrap"> <div className="flex items-center gap-1.5 mt-0.5">
Niveau {user.level} <span className="text-[10px] text-gray-500">
</span> Niv. {user.level}
<span className="text-[10px] sm:text-xs text-gray-500 whitespace-nowrap"> </span>
Score: {formatNumber(user.score)} <span
</span> className={`text-[10px] font-bold px-1.5 py-0.5 rounded border ${
<span user.role === "ADMIN"
className={`text-[10px] sm:text-xs whitespace-nowrap ${ ? "text-pixel-gold border-pixel-gold/50 bg-pixel-gold/10"
user.role === "ADMIN" : "text-gray-500 border-gray-500/30 bg-gray-500/10"
? "text-pixel-gold" }`}
: "text-gray-500" >
}`} {user.role}
> </span>
{user.role} </div>
</span>
</div> </div>
<p className="text-gray-400 text-[10px] sm:text-xs truncate">
{user.email}
</p>
</div> </div>
</div>
<div className="flex gap-2 flex-shrink-0 sm:ml-2">
<button
onClick={() => handleEdit(user)}
className="px-2 sm:px-3 py-1.5 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition whitespace-nowrap"
>
Modifier
</button>
<button
onClick={() => handleDelete(user.id)}
disabled={deletingUserId === user.id}
className="px-2 sm:px-3 py-1.5 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-red-900/30 transition disabled:opacity-50 whitespace-nowrap"
>
{deletingUserId === user.id
? "Suppression..."
: "Supprimer"}
</button>
</div>
</div>
{/* Affichage des stats */} {/* Score en évidence */}
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 text-[10px] sm:text-xs"> <div className="flex items-baseline gap-1.5 px-1">
<div className="flex-1"> <span className="text-[10px] text-gray-400">Score:</span>
<div className="flex justify-between items-center mb-0.5"> <span className="text-lg font-bold text-pixel-gold">
<span className="text-gray-400">HP</span> {formatNumber(user.score)}
<span className="text-gray-400">
{user.hp}/{user.maxHp}
</span> </span>
</div> </div>
<div className="h-1.5 bg-black/60 rounded-full overflow-hidden">
<div {/* Stats HP et XP */}
className="h-full bg-gradient-to-r from-red-600 to-green-500" <div className="space-y-1.5 text-[10px]">
style={{ <div>
width: `${Math.min( <div className="flex justify-between items-center mb-0.5">
100, <span className="text-gray-400">HP</span>
(user.hp / user.maxHp) * 100 <span className="text-gray-400">
)}%`, {user.hp}/{user.maxHp}
}} </span>
/> </div>
<div className="h-1 bg-black/60 rounded-full overflow-hidden">
<div
className="h-full bg-gradient-to-r from-red-600 to-green-500"
style={{
width: `${Math.min(
100,
(user.hp / user.maxHp) * 100
)}%`,
}}
/>
</div>
</div>
<div>
<div className="flex justify-between items-center mb-0.5">
<span className="text-gray-400">XP</span>
<span className="text-gray-400">
{formatNumber(user.xp)}/{formatNumber(user.maxXp)}
</span>
</div>
<div className="h-1 bg-black/60 rounded-full overflow-hidden">
<div
className="h-full bg-gradient-to-r from-blue-600 to-purple-500"
style={{
width: `${Math.min(
100,
(user.xp / user.maxXp) * 100
)}%`,
}}
/>
</div>
</div>
</div>
{/* Email */}
<p className="text-gray-400 text-[10px] truncate px-1">
{user.email}
</p>
{/* Boutons d'action */}
<div className="flex gap-2 pt-1">
<button
onClick={() => handleEdit(user)}
className="flex-1 px-2 py-1 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] tracking-widest rounded hover:bg-pixel-gold/10 transition"
>
Modifier
</button>
<button
onClick={() => handleDelete(user.id)}
disabled={deletingUserId === user.id}
className="flex-1 px-2 py-1 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-[10px] tracking-widest rounded hover:bg-red-900/30 transition disabled:opacity-50"
>
{deletingUserId === user.id ? "..." : "Suppr."}
</button>
</div> </div>
</div> </div>
<div className="flex-1"> </Card>
<div className="flex justify-between items-center mb-0.5"> );
<span className="text-gray-400">XP</span> })}
<span className="text-gray-400"> </div>
{formatNumber(user.xp)}/{formatNumber(user.maxXp)}
</span>
</div>
<div className="h-1.5 bg-black/60 rounded-full overflow-hidden">
<div
className="h-full bg-gradient-to-r from-blue-600 to-purple-500"
style={{
width: `${Math.min(
100,
(user.xp / user.maxXp) * 100
)}%`,
}}
/>
</div>
</div>
</div>
</Card>
);
})
)} )}
{/* Modal d'édition */} {/* Modal d'édition */}