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 + + + {showUnvalidationFormForId === group.challenge_id && ( + + +

❌ Invalider le challenge

+ +