dcrey7's picture
Upload 522 files
811126d verified
"use client";
import { useState, useEffect } from "react";
import { useParams, useRouter } from "next/navigation";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { ArrowLeft, Play, Copy } from "lucide-react";
import Link from "next/link";
import { toast } from "@/hooks/use-toast";
import "../../styles/background-pattern.css";
interface Player {
id: number;
name: string;
isReady: boolean;
}
interface GroupInfo {
id: number;
name: string;
inviteCode: string;
createdAt: string;
players: Player[];
status: "WAITING" | "PLAYING" | "FINISHED";
}
const MAX_PLAYERS = 8;
export default function GroupLobby() {
const params = useParams();
const router = useRouter();
const [groupInfo, setGroupInfo] = useState<GroupInfo | null>(null);
const [copied, setCopied] = useState(false);
const [currentUserId, setCurrentUserId] = useState<number | null>(null);
const inviteUrl = `${process.env.NEXT_PUBLIC_APP_URL}/join/${params.inviteCode}`;
useEffect(() => {
// Récupérer l'ID et le nom de l'utilisateur depuis les cookies
const userId = document.cookie.match(/userId=(\d+)/)?.[1];
const userName = document.cookie.match(/userName=([^;]+)/)?.[1];
if (!userId || !userName) {
// Rediriger vers la page de création de groupe si l'utilisateur n'est pas identifié
router.push("/create-group");
return;
}
setCurrentUserId(parseInt(userId));
fetchGroupInfo();
// Rafraîchir les informations toutes les 5 secondes
const interval = setInterval(fetchGroupInfo, 5000);
return () => clearInterval(interval);
}, [params.inviteCode]);
// Effet pour rediriger vers la page de jeu quand le statut change
useEffect(() => {
if (groupInfo?.status === "PLAYING") {
router.push(`/game/${params.inviteCode}`);
}
}, [groupInfo?.status, params.inviteCode, router]);
const fetchGroupInfo = async () => {
try {
const response = await fetch(`/api/group/${params.inviteCode}`);
if (!response.ok)
throw new Error("Erreur lors de la récupération du groupe");
const data = await response.json();
setGroupInfo(data);
} catch (error) {
console.error("Erreur:", error);
}
};
const copyInviteLink = () => {
navigator.clipboard.writeText(inviteUrl);
toast({
title: "Lien d'invitation copié !",
description:
"Le lien d'invitation a été copié dans votre presse-papiers.",
});
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const toggleReady = async () => {
if (!currentUserId || !groupInfo) {
console.log("Toggle ready impossible:", { currentUserId, groupInfo });
return;
}
const currentPlayer = groupInfo.players.find((p) => p.id === currentUserId);
if (!currentPlayer) {
console.log("Joueur actuel non trouvé dans le groupe");
return;
}
try {
const response = await fetch(`/api/group/${params.inviteCode}/ready`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userId: currentUserId,
isReady: !currentPlayer.isReady,
}),
});
if (!response.ok)
throw new Error("Erreur lors de la mise à jour du statut");
await fetchGroupInfo();
} catch (error) {
console.error("Erreur:", error);
alert("Impossible de mettre à jour votre statut");
}
};
const startGame = async () => {
try {
const response = await fetch(`/api/group/${params.inviteCode}/start`, {
method: "POST",
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || "Erreur lors du démarrage de la partie");
}
router.push(`/game/${params.inviteCode}`);
} catch (error: any) {
console.error("Erreur:", error);
alert(error.message || "Impossible de démarrer la partie");
}
};
if (!groupInfo) {
return (
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
<div className="text-xl">Chargement...</div>
</div>
);
}
const currentPlayer = currentUserId
? groupInfo.players.find((p) => p.id === currentUserId)
: null;
const allPlayersReady = groupInfo.players.every((p) => p.isReady);
const hasEnoughPlayers = groupInfo.players.length >= 3;
const hasTooManyPlayers = groupInfo.players.length > MAX_PLAYERS;
return (
<div className="min-h-screen relative overflow-hidden">
<div className="background-pattern" />
<div className="background-overlay" />
<div className="background-vignette" />
<div className="relative z-10 p-4">
<div className="max-w-4xl mx-auto bg-gray-100 bg-opacity-90 backdrop-blur-sm rounded-lg shadow-xl p-8">
<div className="flex justify-between items-center mb-8">
<Link href="/">
<Button
variant="outline"
className="border-orange-400 text-orange-600 hover:bg-orange-100"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Retour à l'accueil
</Button>
</Link>
<h1 className="text-4xl font-grobold font-normal text-center text-orange-600">
{groupInfo.name}
</h1>
<div className="text-lg font-grobold font-normal text-orange-600">
Joueurs: {groupInfo.players.length} / {MAX_PLAYERS}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
{groupInfo.players.map((player) => (
<div
key={player.id}
className="flex items-center space-x-4 bg-gray-200 p-4 rounded-lg"
>
<Avatar className="w-16 h-16 border-2 border-orange-400">
<AvatarImage
src={`/avatar${(player.id % 5) + 1}.png`}
alt={player.name}
/>
<AvatarFallback>{player.name[0]}</AvatarFallback>
</Avatar>
<div>
<p className="font-grobold font-normal text-orange-800">
{player.name}
{player.id === currentUserId && " (Vous)"}
</p>
<p
className={`text-${
player.isReady ? "green" : "orange"
}-600`}
>
{player.isReady ? "Prêt" : "En attente"}
</p>
</div>
</div>
))}
</div>
<div className="flex justify-center space-x-4">
{currentPlayer && (
<Button
onClick={toggleReady}
className={`${
currentPlayer.isReady
? "bg-orange-500 hover:bg-orange-600"
: "bg-green-500 hover:bg-green-600"
} text-white text-lg py-6 px-12 font-grobold font-normal`}
>
{currentPlayer.isReady ? "Annuler" : "Je suis prêt !"}
</Button>
)}
<Button
onClick={copyInviteLink}
variant="outline"
className="border-orange-400 text-orange-600 hover:bg-orange-100 py-6 px-6"
>
<Copy className="mr-2 h-5 w-5" />
Inviter des amis
</Button>
</div>
{currentPlayer &&
allPlayersReady &&
hasEnoughPlayers &&
!hasTooManyPlayers && (
<div className="mt-8 text-center">
<Button
onClick={startGame}
className="bg-green-500 hover:bg-green-600 text-white text-lg py-6 px-12 font-grobold font-normal"
>
<Play className="mr-2 h-6 w-6" />
Démarrer la partie
</Button>
</div>
)}
<div className="text-center text-orange-600 mt-4 font-grobold font-normal">
{!hasEnoughPlayers &&
`Il manque ${
3 - groupInfo.players.length
} joueur(s) pour commencer`}
{hasTooManyPlayers &&
`Trop de joueurs. Maximum ${MAX_PLAYERS} autorisés`}
{!allPlayersReady &&
hasEnoughPlayers &&
!hasTooManyPlayers &&
"En attente que tous les joueurs soient prêts"}
</div>
</div>
</div>
</div>
);
}