diff --git a/backend/src/controllers/tent.controller.ts b/backend/src/controllers/tent.controller.ts
index 5dd067b..2f87a81 100644
--- a/backend/src/controllers/tent.controller.ts
+++ b/backend/src/controllers/tent.controller.ts
@@ -90,7 +90,7 @@ export const toggleTentConfirmation = async (req: Request, res: Response) => {
to: [user1.email, user2.email],
subject: confirmed
? "đ Votre tente a Ă©tĂ© validĂ©e !"
- : "âș Votre tente a Ă©tĂ© dĂ©validĂ©e",
+ : "âș Votre tente a Ă©tĂ© invalidĂ©e",
text: "", // optionnel
html: htmlEmail,
};
@@ -101,7 +101,7 @@ export const toggleTentConfirmation = async (req: Request, res: Response) => {
Ok(res, {
msg: confirmed
? "Tente validée et email envoyé."
- : "Tente dévalidée et email envoyé.",
+ : "Tente invalidée et email envoyé.",
});
} catch (err: any) {
console.error(err);
diff --git a/backend/src/services/challenge.service.ts b/backend/src/services/challenge.service.ts
index 44d7ece..759d874 100644
--- a/backend/src/services/challenge.service.ts
+++ b/backend/src/services/challenge.service.ts
@@ -82,7 +82,29 @@ export const validateChallenge = async ({
throw new Error("Type de challenge non valide");
}
- // 3. Créer l'objet de validation du challenge
+ // 3. Vérifier si ce challenge a déjà été validé pour cette cible
+ const targetColumn =
+ type === "user"
+ ? challengeValidationSchema.target_user_id
+ : type === "team"
+ ? challengeValidationSchema.target_team_id
+ : challengeValidationSchema.target_faction_id;
+
+ const existingValidation = await db
+ .select()
+ .from(challengeValidationSchema)
+ .where(
+ and(
+ eq(challengeValidationSchema.challenge_id, challengeId),
+ eq(targetColumn, targetId)
+ )
+ );
+
+ if (existingValidation.length > 0) {
+ throw new Error("Ce challenge a déjà été validé pour cette cible");
+ }
+
+ // 4. Créer l'objet de validation du challenge
const newChallengeValidationPoints = {
challenge_id: challengeId,
validated_by_admin_id: validatedBy,
@@ -94,7 +116,7 @@ export const validateChallenge = async ({
target_faction_id: target_faction_id,
};
- // 4. Insérer la validation du challenge dans la base de données
+ // 5. Insérer la validation du challenge dans la base de données
const inserted = await db.insert(challengeValidationSchema).values(newChallengeValidationPoints).returning();
return inserted[0];
diff --git a/backend/src/services/tent.service.ts b/backend/src/services/tent.service.ts
index ed9b32b..5f02fce 100644
--- a/backend/src/services/tent.service.ts
+++ b/backend/src/services/tent.service.ts
@@ -131,5 +131,5 @@ export const toggleTentConfirmation = async (
)
);
- return { success: true, message: confirmed ? "Tente validée." : "Tente dévalidée." };
+ return { success: true, message: confirmed ? "Tente validée." : "Tente invalidée." };
};
diff --git a/backend/src/utils/emailtemplates.ts b/backend/src/utils/emailtemplates.ts
index 309068e..3d53f57 100644
--- a/backend/src/utils/emailtemplates.ts
+++ b/backend/src/utils/emailtemplates.ts
@@ -341,7 +341,7 @@ export const templateNotifyTentConfirmation = `
La tente entre {{user1}} et {{user2}} a été
- {{#if confirmed}}validée{{else}}dévalidée{{/if}}
+ {{#if confirmed}}validée{{else}}invalidée{{/if}}
.
diff --git a/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx b/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx
index 2b1661d..c3cccf5 100644
--- a/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx
+++ b/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx
@@ -1,6 +1,6 @@
import { CheckCircle2, Edit, Search, Trash2 } from "lucide-react";
import { useMemo, useState } from "react";
-import Select, { type SingleValue } from "react-select";
+import Select from "react-select";
import Swal from "sweetalert2";
import { type Challenge } from "../../../interfaces/challenge.interface";
@@ -26,7 +26,7 @@ type ValidationTarget = "user" | "team" | "faction";
const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, factions, users }: Props) => {
const [showValidationFormForId, setShowValidationFormForId] = useState(null);
const [validationType, setValidationType] = useState(null);
- const [selectedTargetId, setSelectedTargetId] = useState(null);
+ const [selectedTargetIds, setSelectedTargetIds] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
@@ -62,14 +62,20 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact
}
};
- const handleValidate = async () => {
- if (!showValidationFormForId || !validationType || !selectedTargetId) return;
+ const handleValidationCLick = async (c: Challenge) => {
+ setShowValidationFormForId(c.id);
+ setValidationType(c.category.toLowerCase() as ValidationTarget);
+ }
+ const handleValidate = async () => {
+ if (!showValidationFormForId || !validationType || selectedTargetIds.length === 0) return;
+
+ for (const targetId of selectedTargetIds) {
try {
const res = await validateChallenge({
challengeId: showValidationFormForId,
type: validationType,
- targetId: selectedTargetId,
+ targetId: targetId,
});
Swal.fire({
@@ -82,20 +88,21 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact
setShowValidationFormForId(null);
setValidationType(null);
- setSelectedTargetId(null);
+ setSelectedTargetIds([]);
refreshChallenges();
} catch (err) {
console.error("Erreur lors de la validation du challenge", err);
Swal.fire({
icon: "error",
title: "Erreur â",
- text: "Impossible de valider ce challenge. Réessaie plus tard.",
+ text: err as string,
});
}
+ }
};
return (
-
+
đ Challenges
@@ -145,7 +152,7 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact
Supprimer