"use client"; import { useState, useEffect, useTransition } from "react"; import Avatar from "./Avatar"; import { updateUser, deleteUser } from "@/actions/admin/users"; interface User { id: string; username: string; email: string; role: string; score: number; level: number; hp: number; maxHp: number; xp: number; maxXp: number; avatar: string | null; createdAt: string; } interface EditingUser { userId: string; username: string | null; avatar: string | null; hpDelta: number; xpDelta: number; score: number | null; level: number | null; role: string | null; } export default function UserManagement() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [editingUser, setEditingUser] = useState(null); const [saving, setSaving] = useState(false); const [deletingUserId, setDeletingUserId] = useState(null); const [, startTransition] = useTransition(); const [uploadingAvatar, setUploadingAvatar] = useState(null); useEffect(() => { fetchUsers(); }, []); const fetchUsers = async () => { try { const response = await fetch("/api/admin/users"); if (response.ok) { const data = await response.json(); setUsers(data); } } catch (error) { console.error("Error fetching users:", error); } finally { setLoading(false); } }; const handleEdit = (user: User) => { setEditingUser({ userId: user.id, username: user.username, avatar: user.avatar, hpDelta: 0, xpDelta: 0, score: user.score, level: user.level, role: user.role, }); }; const handleSave = async () => { if (!editingUser) return; setSaving(true); startTransition(async () => { try { const body: { username?: string; avatar?: string | null; hpDelta?: number; xpDelta?: number; score?: number; level?: number; role?: string; } = {}; if (editingUser.username !== null) { body.username = editingUser.username; } if (editingUser.avatar !== undefined) { body.avatar = editingUser.avatar; } if (editingUser.hpDelta !== 0) { body.hpDelta = editingUser.hpDelta; } if (editingUser.xpDelta !== 0) { body.xpDelta = editingUser.xpDelta; } if (editingUser.score !== null) { body.score = editingUser.score; } if (editingUser.level !== null) { body.level = editingUser.level; } if (editingUser.role !== null) { body.role = editingUser.role; } const result = await updateUser(editingUser.userId, body); if (result.success) { await fetchUsers(); setEditingUser(null); } else { alert(result.error || "Erreur lors de la mise à jour"); } } catch (error) { console.error("Error updating user:", error); alert("Erreur lors de la mise à jour"); } finally { setSaving(false); } }); }; const handleCancel = () => { setEditingUser(null); }; const handleDelete = async (userId: string) => { if ( !confirm( "Êtes-vous sûr de vouloir supprimer cet utilisateur ? Cette action est irréversible." ) ) { return; } setDeletingUserId(userId); try { const result = await deleteUser(userId); if (result.success) { await fetchUsers(); } else { alert(result.error || "Erreur lors de la suppression"); } } catch (error) { console.error("Error deleting user:", error); alert("Erreur lors de la suppression"); } finally { setDeletingUserId(null); } }; const formatNumber = (num: number) => { return num.toLocaleString("en-US"); }; if (loading) { return
Chargement...
; } return (
{users.length === 0 ? (
Aucun utilisateur trouvé
) : ( users.map((user) => { const isEditing = editingUser?.userId === user.id; const previewHp = isEditing ? Math.max(0, Math.min(user.maxHp, user.hp + editingUser.hpDelta)) : user.hp; const previewXp = isEditing ? Math.max(0, user.xp + editingUser.xpDelta) : user.xp; const displayAvatar = isEditing ? editingUser.avatar : user.avatar; const displayUsername = isEditing ? editingUser.username || user.username : user.username; return (
{/* Avatar */}

{displayUsername}

Niveau {user.level} Score: {formatNumber(user.score)} {user.role}

{user.email}

{!isEditing && (
)}
{isEditing ? (
{/* Username Section */}
setEditingUser({ ...editingUser, username: e.target.value, }) } className="w-full px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm" placeholder="Nom d'utilisateur" />
{/* Avatar Section */}
{/* Preview */}
{uploadingAvatar === user.id && (
Upload...
)}
{/* Avatars par défaut */}
{[ "/avatar-1.jpg", "/avatar-2.jpg", "/avatar-3.jpg", "/avatar-4.jpg", "/avatar-5.jpg", "/avatar-6.jpg", ].map((defaultAvatar) => ( ))}
{/* Custom Upload */}
{ const file = e.target.files?.[0]; if (!file) return; setUploadingAvatar(user.id); try { const formData = new FormData(); formData.append("file", file); const response = await fetch( "/api/admin/avatars/upload", { method: "POST", body: formData, } ); if (response.ok) { const data = await response.json(); setEditingUser({ ...editingUser, avatar: data.url, }); } else { alert("Erreur lors de l'upload de l'image"); } } catch (error) { console.error("Error uploading image:", error); alert("Erreur lors de l'upload de l'image"); } finally { setUploadingAvatar(null); if (e.target) { e.target.value = ""; } } }} className="hidden" id={`avatar-upload-${user.id}`} />
{/* HP Section */}
{previewHp} / {user.maxHp}
setEditingUser({ ...editingUser, hpDelta: parseInt(e.target.value) || 0, }) } className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center" />
{/* XP Section */}
{formatNumber(previewXp)} / {formatNumber(user.maxXp)}
setEditingUser({ ...editingUser, xpDelta: parseInt(e.target.value) || 0, }) } className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center" />
{/* Score Section */}
setEditingUser({ ...editingUser, score: parseInt(e.target.value) || 0, }) } className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center" />
{/* Level Section */}
setEditingUser({ ...editingUser, level: Math.max(1, parseInt(e.target.value) || 1), }) } className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center" />
{/* Role Section */}
) : (
HP {user.hp}/{user.maxHp}
XP {formatNumber(user.xp)}/{formatNumber(user.maxXp)}
)}
); }) )}
); }