Enhance ChallengeManagement and EventManagement components: Refactor layout for better readability, implement event registration viewing with score editing functionality, and improve user feedback handling in modals. Update EventRegistrationService to fetch event registrations with user details, ensuring a more interactive admin experience.
This commit is contained in:
@@ -9,7 +9,15 @@ import {
|
||||
adminCancelChallenge,
|
||||
reactivateChallenge,
|
||||
} from "@/actions/admin/challenges";
|
||||
import { Button, Card, Input, Textarea, Alert, Modal, CloseButton } from "@/components/ui";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Input,
|
||||
Textarea,
|
||||
Alert,
|
||||
Modal,
|
||||
CloseButton,
|
||||
} from "@/components/ui";
|
||||
import { Avatar } from "@/components/ui";
|
||||
|
||||
interface Challenge {
|
||||
@@ -441,115 +449,115 @@ export default function ChallengeManagement() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-bold text-gray-300 mb-2">
|
||||
{selectedChallenge.title}
|
||||
</h3>
|
||||
<p className="text-gray-400 mb-4">
|
||||
{selectedChallenge.description}
|
||||
</p>
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-bold text-gray-300 mb-2">
|
||||
{selectedChallenge.title}
|
||||
</h3>
|
||||
<p className="text-gray-400 mb-4">
|
||||
{selectedChallenge.description}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar
|
||||
src={selectedChallenge.challenger.avatar}
|
||||
username={selectedChallenge.challenger.username}
|
||||
size="md"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenger.username}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-gray-500">VS</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar
|
||||
src={selectedChallenge.challenged.avatar}
|
||||
username={selectedChallenge.challenged.username}
|
||||
size="md"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenged.username}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar
|
||||
src={selectedChallenge.challenger.avatar}
|
||||
username={selectedChallenge.challenger.username}
|
||||
size="md"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenger.username}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-gray-500">VS</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar
|
||||
src={selectedChallenge.challenged.avatar}
|
||||
username={selectedChallenge.challenged.username}
|
||||
size="md"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenged.username}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-bold text-pixel-gold mb-2">
|
||||
Sélectionner le gagnant
|
||||
</label>
|
||||
<div className="flex gap-4">
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="winner"
|
||||
value={selectedChallenge.challenger.id}
|
||||
checked={winnerId === selectedChallenge.challenger.id}
|
||||
onChange={(e) => setWinnerId(e.target.value)}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenger.username}
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="winner"
|
||||
value={selectedChallenge.challenged.id}
|
||||
checked={winnerId === selectedChallenge.challenged.id}
|
||||
onChange={(e) => setWinnerId(e.target.value)}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenged.username}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-bold text-pixel-gold mb-2">
|
||||
Commentaire (optionnel)
|
||||
</label>
|
||||
<textarea
|
||||
value={adminComment}
|
||||
onChange={(e) => setAdminComment(e.target.value)}
|
||||
className="w-full p-2 bg-black/60 border border-pixel-gold/30 rounded text-gray-300"
|
||||
rows={3}
|
||||
placeholder="Commentaire pour les joueurs..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-bold text-pixel-gold mb-2">
|
||||
Sélectionner le gagnant
|
||||
</label>
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
onClick={handleValidate}
|
||||
variant="primary"
|
||||
disabled={!winnerId || isPending}
|
||||
className="flex-1"
|
||||
>
|
||||
{isPending ? "Enregistrement..." : "Confirmer le gagnant"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleReject}
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
className="flex-1"
|
||||
>
|
||||
{isPending ? "Rejet..." : "Rejeter le défi"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setSelectedChallenge(null);
|
||||
setWinnerId("");
|
||||
setAdminComment("");
|
||||
}}
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
>
|
||||
Annuler
|
||||
</Button>
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="winner"
|
||||
value={selectedChallenge.challenger.id}
|
||||
checked={winnerId === selectedChallenge.challenger.id}
|
||||
onChange={(e) => setWinnerId(e.target.value)}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenger.username}
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="winner"
|
||||
value={selectedChallenge.challenged.id}
|
||||
checked={winnerId === selectedChallenge.challenged.id}
|
||||
onChange={(e) => setWinnerId(e.target.value)}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
<span className="text-gray-300">
|
||||
{selectedChallenge.challenged.username}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-bold text-pixel-gold mb-2">
|
||||
Commentaire (optionnel)
|
||||
</label>
|
||||
<textarea
|
||||
value={adminComment}
|
||||
onChange={(e) => setAdminComment(e.target.value)}
|
||||
className="w-full p-2 bg-black/60 border border-pixel-gold/30 rounded text-gray-300"
|
||||
rows={3}
|
||||
placeholder="Commentaire pour les joueurs..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
onClick={handleValidate}
|
||||
variant="primary"
|
||||
disabled={!winnerId || isPending}
|
||||
className="flex-1"
|
||||
>
|
||||
{isPending ? "Enregistrement..." : "Confirmer le gagnant"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleReject}
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
className="flex-1"
|
||||
>
|
||||
{isPending ? "Rejet..." : "Rejeter le défi"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setSelectedChallenge(null);
|
||||
setWinnerId("");
|
||||
setAdminComment("");
|
||||
}}
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
>
|
||||
Annuler
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)}
|
||||
@@ -582,67 +590,67 @@ export default function ChallengeManagement() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
id="edit-title"
|
||||
label="Titre"
|
||||
value={editTitle}
|
||||
onChange={(e) => setEditTitle(e.target.value)}
|
||||
required
|
||||
placeholder="Titre du défi"
|
||||
/>
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
id="edit-title"
|
||||
label="Titre"
|
||||
value={editTitle}
|
||||
onChange={(e) => setEditTitle(e.target.value)}
|
||||
required
|
||||
placeholder="Titre du défi"
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
id="edit-description"
|
||||
label="Description"
|
||||
value={editDescription}
|
||||
onChange={(e) => setEditDescription(e.target.value)}
|
||||
required
|
||||
rows={4}
|
||||
placeholder="Description du défi"
|
||||
/>
|
||||
<Textarea
|
||||
id="edit-description"
|
||||
label="Description"
|
||||
value={editDescription}
|
||||
onChange={(e) => setEditDescription(e.target.value)}
|
||||
required
|
||||
rows={4}
|
||||
placeholder="Description du défi"
|
||||
/>
|
||||
|
||||
<Input
|
||||
id="edit-points"
|
||||
label="Récompense (points)"
|
||||
type="number"
|
||||
min="1"
|
||||
value={editPointsReward}
|
||||
onChange={(e) =>
|
||||
setEditPointsReward(parseInt(e.target.value) || 0)
|
||||
<Input
|
||||
id="edit-points"
|
||||
label="Récompense (points)"
|
||||
type="number"
|
||||
min="1"
|
||||
value={editPointsReward}
|
||||
onChange={(e) =>
|
||||
setEditPointsReward(parseInt(e.target.value) || 0)
|
||||
}
|
||||
required
|
||||
placeholder="100"
|
||||
/>
|
||||
|
||||
<div className="flex gap-4 pt-4">
|
||||
<Button
|
||||
onClick={handleUpdate}
|
||||
variant="primary"
|
||||
disabled={
|
||||
isPending ||
|
||||
!editTitle ||
|
||||
!editDescription ||
|
||||
editPointsReward <= 0
|
||||
}
|
||||
required
|
||||
placeholder="100"
|
||||
/>
|
||||
|
||||
<div className="flex gap-4 pt-4">
|
||||
<Button
|
||||
onClick={handleUpdate}
|
||||
variant="primary"
|
||||
disabled={
|
||||
isPending ||
|
||||
!editTitle ||
|
||||
!editDescription ||
|
||||
editPointsReward <= 0
|
||||
}
|
||||
className="flex-1"
|
||||
>
|
||||
{isPending ? "Mise à jour..." : "Enregistrer"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setEditingChallenge(null);
|
||||
setEditTitle("");
|
||||
setEditDescription("");
|
||||
setEditPointsReward(0);
|
||||
}}
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
>
|
||||
Annuler
|
||||
</Button>
|
||||
</div>
|
||||
className="flex-1"
|
||||
>
|
||||
{isPending ? "Mise à jour..." : "Enregistrer"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setEditingChallenge(null);
|
||||
setEditTitle("");
|
||||
setEditDescription("");
|
||||
setEditPointsReward(0);
|
||||
}}
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
>
|
||||
Annuler
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user