Add admin challenge management features: Implement functions for canceling and reactivating challenges, enhance error handling, and update the ChallengeManagement component to support these actions. Update API to retrieve all challenge statuses for admin and improve UI to display active challenges count.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 6m16s

This commit is contained in:
Julien Froidefond
2025-12-15 22:19:58 +01:00
parent 633245c1f1
commit bfaf30ee26
9 changed files with 390 additions and 53 deletions

View File

@@ -306,6 +306,63 @@ export class ChallengeService {
});
}
/**
* Annule un défi (admin seulement)
*/
async adminCancelChallenge(challengeId: string): Promise<Challenge> {
const challenge = await prisma.challenge.findUnique({
where: { id: challengeId },
});
if (!challenge) {
throw new NotFoundError("Défi");
}
// Vérifier que le défi peut être annulé
if (challenge.status === "COMPLETED") {
throw new ValidationError("Un défi complété ne peut pas être annulé");
}
return prisma.challenge.update({
where: { id: challengeId },
data: {
status: "CANCELLED",
},
});
}
/**
* Réactive un défi annulé (admin seulement)
* Remet le défi en PENDING s'il n'avait jamais été accepté, sinon en ACCEPTED
*/
async reactivateChallenge(challengeId: string): Promise<Challenge> {
const challenge = await prisma.challenge.findUnique({
where: { id: challengeId },
});
if (!challenge) {
throw new NotFoundError("Défi");
}
// Vérifier que le défi est annulé
if (challenge.status !== "CANCELLED") {
throw new ValidationError(
"Seuls les défis annulés peuvent être réactivés"
);
}
// Si le défi avait été accepté avant, le remettre en ACCEPTED
// Sinon, le remettre en PENDING
const newStatus = challenge.acceptedAt ? "ACCEPTED" : "PENDING";
return prisma.challenge.update({
where: { id: challengeId },
data: {
status: newStatus,
},
});
}
/**
* Supprime un défi (admin seulement)
*/
@@ -405,7 +462,7 @@ export class ChallengeService {
}
/**
* Récupère les défis en attente de validation admin
* Récupère les défis acceptés en attente de désignation du gagnant
*/
async getPendingValidationChallenges(): Promise<ChallengeWithUsers[]> {
return prisma.challenge.findMany({
@@ -489,6 +546,30 @@ export class ChallengeService {
take: options?.take,
}) as Promise<ChallengeWithUsers[]>;
}
/**
* Compte les défis actifs pour un utilisateur
* - PENDING où l'utilisateur est challenged (en attente de sa réponse)
* - ACCEPTED où l'utilisateur est challenger ou challenged (en cours, en attente de validation)
*/
async getActiveChallengesCount(userId: string): Promise<number> {
return prisma.challenge.count({
where: {
OR: [
// Défis en attente de réponse de l'utilisateur
{
status: "PENDING",
challengedId: userId,
},
// Défis acceptés en cours (en attente de désignation du gagnant)
{
status: "ACCEPTED",
OR: [{ challengerId: userId }, { challengedId: userId }],
},
],
},
});
}
}
export const challengeService = new ChallengeService();