import { useState } from "react"; import { useLiveQuery } from "dexie-react-hooks"; import { db } from "../database/db"; import { Users, Trash2, Edit2, Check, X, Camera, Dices, Loader2, } from "lucide-react"; import { Card, CardContent } from "../components/ui/card"; import { Button } from "../components/ui/button"; import { Input } from "../components/ui/input"; import { NavigationMenu } from "../components/NavigationMenu"; import { Avatar } from "../components/ui/avatar"; import { resizeImage } from "../utils/image"; import { motion } from "framer-motion"; export default function Players() { const players = useLiveQuery(() => db.players.orderBy("name").toArray()); const [editingId, setEditingId] = useState(null); const [editName, setEditName] = useState(""); const [isGenerating, setIsGenerating] = useState(null); const handleDelete = async (id: string, name: string) => { if (window.confirm(`Êtes-vous sûr de vouloir supprimer ${name} ?`)) { await db.players.delete(id); } }; const startEdit = (id: string, name: string) => { setEditingId(id); setEditName(name); }; const saveEdit = async (id: string) => { if (editName.trim()) { const newName = editName.trim(); const playerToEdit = players?.find((p) => p.id === id); await db.players.update(id, { name: newName }); // Update the player's name in all existing game sessions (history) const sessions = await db.sessions.toArray(); const updatedSessions = sessions .map((session) => { let hasChanges = false; const newPlayers = session.players.map((p) => { // Check by ID or fallback to exact name matching if older data if (p.id === id || (playerToEdit && p.name === playerToEdit.name)) { hasChanges = true; return { ...p, name: newName }; } return p; }); if (hasChanges) { return { ...session, players: newPlayers }; } return null; }) .filter((s) => s !== null) as typeof sessions; if (updatedSessions.length > 0) { await db.sessions.bulkPut(updatedSessions); } } setEditingId(null); }; const updatePlayerAvatarGlobally = async ( playerId: string, avatarData: string, ) => { await db.players.update(playerId, { avatar: avatarData }); // Update historical sessions too if we want the avatar to reflect immediately everywhere const sessions = await db.sessions.toArray(); const updatedSessions = sessions .map((session) => { let hasChanges = false; const newPlayers = session.players.map((p) => { if (p.id === playerId) { hasChanges = true; return { ...p, avatar: avatarData }; } return p; }); if (hasChanges) return { ...session, players: newPlayers }; return null; }) .filter((s) => s !== null) as typeof sessions; if (updatedSessions.length > 0) { await db.sessions.bulkPut(updatedSessions); } }; const handleAvatarChange = async ( playerId: string, event: React.ChangeEvent, ) => { const file = event.target.files?.[0]; if (!file) return; try { const base64Image = await resizeImage(file); await updatePlayerAvatarGlobally(playerId, base64Image); } catch (e) { alert("Erreur lors de l'enregistrement de l'image."); } }; const handleGenerateRandomAvatar = async (playerId: string) => { setIsGenerating(playerId); try { // Seed aléatoire const seed = Math.random().toString(36).substring(7); // Utilisation du style "bottts-neutral" const url = `https://api.dicebear.com/9.x/bottts-neutral/svg?seed=${seed}&backgroundColor=transparent`; const response = await fetch(url); const svgText = await response.text(); // On encode l'SVG proprement pour l'utiliser comme image dans l'app const encodedSvg = `data:image/svg+xml;utf8,${encodeURIComponent(svgText)}`; await updatePlayerAvatarGlobally(playerId, encodedSvg); } catch (e) { alert( "Impossible de générer l'avatar. Vérifiez votre connexion internet.", ); } finally { setIsGenerating(null); } }; return (

Joueurs

{!players || players.length === 0 ? (

Aucun joueur enregistré.

Ils s'ajouteront automatiquement lors de votre prochaine partie.

) : ( players.map((player, index) => ( {/* Decorative blob */}
{editingId === player.id ? (
setEditName(e.target.value)} className="h-12" autoFocus />
) : ( <>
{ const input = document.getElementById( `avatar-upload-${player.id}`, ); input?.click(); }} >
handleAvatarChange(player.id, e)} />
{player.name}
)}
)) )}
); }