Files
got-gaming/components/challenges/ChallengeCard.tsx

184 lines
5.1 KiB
TypeScript

"use client";
import { Card, Button, Avatar, Badge } from "@/components/ui";
interface ChallengeCardProps {
challenge: {
id: string;
challenger: {
id: string;
username: string;
avatar: string | null;
};
challenged: {
id: string;
username: string;
avatar: string | null;
};
title: string;
description: string;
pointsReward: number;
status: string;
adminComment: string | null;
winner?: {
id: string;
username: string;
} | null;
createdAt: string;
acceptedAt: string | null;
completedAt: string | null;
};
currentUserId?: string;
onAccept?: (challengeId: string) => void;
onCancel?: (challengeId: string) => void;
isPending?: boolean;
}
const getStatusLabel = (status: string) => {
switch (status) {
case "PENDING":
return "En attente d'acceptation";
case "ACCEPTED":
return "En cours - En attente de désignation du gagnant";
case "COMPLETED":
return "Complété";
case "REJECTED":
return "Rejeté";
case "CANCELLED":
return "Annulé";
default:
return status;
}
};
const getStatusVariant = (
status: string
): "default" | "success" | "warning" | "danger" | "info" => {
switch (status) {
case "PENDING":
return "warning";
case "ACCEPTED":
return "info";
case "COMPLETED":
return "success";
case "REJECTED":
return "danger";
case "CANCELLED":
return "default";
default:
return "default";
}
};
export default function ChallengeCard({
challenge,
currentUserId,
onAccept,
onCancel,
isPending = false,
}: ChallengeCardProps) {
const isChallenger = challenge.challenger.id === currentUserId;
const isChallenged = challenge.challenged.id === currentUserId;
const canAccept = challenge.status === "PENDING" && isChallenged;
const canCancel =
(challenge.status === "PENDING" || challenge.status === "ACCEPTED") &&
(isChallenger || isChallenged);
return (
<Card variant="dark" className="p-6">
<div className="flex items-start justify-between gap-4">
<div className="flex-1">
<div className="flex items-center gap-2 mb-2 flex-wrap">
<h3 className="text-lg font-bold text-pixel-gold">
{challenge.title}
</h3>
<Badge variant={getStatusVariant(challenge.status)} size="xs">
{getStatusLabel(challenge.status)}
</Badge>
</div>
<p className="text-gray-300 mb-4">{challenge.description}</p>
<div className="flex items-center gap-4 mb-2 flex-wrap">
<div className="flex items-center gap-2">
<Avatar
src={challenge.challenger.avatar}
username={challenge.challenger.username}
size="sm"
/>
<span className="text-sm text-gray-300">
{challenge.challenger.username}
</span>
</div>
<span className="text-gray-500">VS</span>
<div className="flex items-center gap-2">
<Avatar
src={challenge.challenged.avatar}
username={challenge.challenged.username}
size="sm"
/>
<span className="text-sm text-gray-300">
{challenge.challenged.username}
</span>
</div>
</div>
<div className="text-sm text-gray-400">
Récompense:{" "}
<span className="text-pixel-gold font-bold">
{challenge.pointsReward} points
</span>
</div>
{challenge.winner && (
<div className="text-sm text-green-400 mt-2">
🏆 Gagnant: {challenge.winner.username}
</div>
)}
{challenge.adminComment && (
<div className="text-xs text-gray-500 mt-2 italic">
Admin: {challenge.adminComment}
</div>
)}
<div className="text-xs text-gray-500 mt-2">
Créé le: {new Date(challenge.createdAt).toLocaleDateString("fr-FR")}
{challenge.acceptedAt &&
` • Accepté le: ${new Date(challenge.acceptedAt).toLocaleDateString("fr-FR")}`}
{challenge.completedAt &&
` • Complété le: ${new Date(challenge.completedAt).toLocaleDateString("fr-FR")}`}
</div>
</div>
<div className="flex flex-col gap-2">
{canAccept && onAccept && (
<Button
onClick={() => onAccept(challenge.id)}
variant="primary"
size="sm"
disabled={isPending}
>
Accepter
</Button>
)}
{canCancel && onCancel && (
<Button
onClick={() => {
if (confirm("Êtes-vous sûr de vouloir annuler ce défi ?")) {
onCancel(challenge.id);
}
}}
variant="secondary"
size="sm"
disabled={isPending}
>
Annuler
</Button>
)}
</div>
</div>
</Card>
);
}