From 0fc871bd46867b547a12e86144ad1baa43dc3fd1 Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Thu, 21 Aug 2025 11:11:04 +0200 Subject: [PATCH] feat: ban competition + competition list sort --- .../domain/service/CompetitionService.java | 19 +++++++- .../ffsaf/rest/CompetitionEndpoints.java | 4 +- .../src/pages/competition/CompetitionEdit.jsx | 18 ++++---- .../src/pages/competition/CompetitionList.jsx | 19 ++++++-- .../competition/CompetitionRegisterAdmin.jsx | 43 +++++++++++++++++-- .../src/pages/competition/CompetitionRoot.jsx | 2 +- 6 files changed, 85 insertions(+), 20 deletions(-) diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java index f1350ab..52c0db5 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java @@ -264,6 +264,12 @@ public class CompetitionService { if ("admin".equals(source)) return permService.hasEditPerm(securityCtx, id) .chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname()) + .call(combModel -> { + if (c.getBanMembre() == null) + c.setBanMembre(new ArrayList<>()); + c.getBanMembre().remove(combModel.getId()); + return Panache.withTransaction(() -> repository.persist(c)); + }) .chain(combModel -> updateRegister(data, c, combModel, true))) .chain(r -> Mutiny.fetch(r.getMembre().getLicences()) .map(licences -> SimpleRegisterComb.fromModel(r, licences))); @@ -368,9 +374,20 @@ public class CompetitionService { } } - public Uni removeRegisterComb(SecurityCtx securityCtx, Long id, Long combId, String source) { + public Uni removeRegisterComb(SecurityCtx securityCtx, Long id, Long combId, String source, boolean ban) { if ("admin".equals(source)) return permService.hasEditPerm(securityCtx, id) + .chain(cm -> { + if (cm.getBanMembre() == null) + cm.setBanMembre(new ArrayList<>()); + if (ban) { + if (!cm.getBanMembre().contains(combId)) + cm.getBanMembre().add(combId); + } else { + cm.getBanMembre().remove(combId); + } + return Panache.withTransaction(() -> repository.persist(cm)); + }) .chain(c -> deleteRegister(combId, c, true)); if ("club".equals(source)) return repository.findById(id) diff --git a/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java index fe74f04..82fccc0 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java @@ -59,8 +59,8 @@ public class CompetitionEndpoints { @Produces(MediaType.APPLICATION_JSON) @Operation(hidden = true) public Uni removeRegisterComb(@PathParam("id") Long id, @PathParam("comb_id") Long combId, - @PathParam("source") String source) { - return service.removeRegisterComb(securityCtx, id, combId, source); + @PathParam("source") String source, @QueryParam("ban") boolean ban) { + return service.removeRegisterComb(securityCtx, id, combId, source, ban); } @GET diff --git a/src/main/webapp/src/pages/competition/CompetitionEdit.jsx b/src/main/webapp/src/pages/competition/CompetitionEdit.jsx index ffed104..88289e9 100644 --- a/src/main/webapp/src/pages/competition/CompetitionEdit.jsx +++ b/src/main/webapp/src/pages/competition/CompetitionEdit.jsx @@ -23,11 +23,11 @@ export function CompetitionEdit() { toast.promise( apiAxios.delete(`/competition/${id}`), { - pending: "Suppression de la competition en cours...", - success: "Competition supprimé avec succès 🎉", + pending: "Suppression de la compétition en cours...", + success: "Compétition supprimé avec succès 🎉", error: { render({data}) { - return errFormater(data, "Échec de la suppression de la competition") + return errFormater(data, "Échec de la suppression de la compétition") } }, } @@ -47,18 +47,18 @@ export function CompetitionEdit() { {data.id !== null && } + onClick={_ => navigate(`/competition/${data.id}/register?type=${data.registerMode}`)}>Voir/Modifier les participants} {data.id !== null && data.system === "SAFCA" && } {data.id !== null && <>
- } @@ -301,7 +301,7 @@ function Content({data}) { return
-
{data.id ? "Edition competition" : "Création competition"}
+
{data.id ? "Edition compétition" : "Création compétition"}
@@ -330,7 +330,7 @@ function Content({data}) {

diff --git a/src/main/webapp/src/pages/competition/CompetitionList.jsx b/src/main/webapp/src/pages/competition/CompetitionList.jsx index dad9d94..3c00b92 100644 --- a/src/main/webapp/src/pages/competition/CompetitionList.jsx +++ b/src/main/webapp/src/pages/competition/CompetitionList.jsx @@ -31,12 +31,23 @@ function MakeCentralPanel({data, navigate}) { return <> {userinfo?.roles?.includes("create_compet") && -
- -
} +
+ +
}
+

Compétition future

- {data.map(req => ())} + {data.filter(req => new Date(req.toDate.split('T')[0]) >= new Date()).sort((a, b) => { + return new Date(a.date.split('T')[0]) - new Date(b.date.split(')T')[0]) + }).map(req => ())} +
+
+
+

Compétition passée

+
+ {data.filter(req => new Date(req.toDate.split('T')[0]) < new Date()).sort((a, b) => { + return new Date(b.date.split('T')[0]) - new Date(a.date.split(')T')[0]) + }).map(req => ())}
diff --git a/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx b/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx index 25106bb..c514db1 100644 --- a/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx +++ b/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx @@ -1,4 +1,4 @@ -import {useNavigate, useParams} from "react-router-dom"; +import {useNavigate, useParams, useSearchParams} from "react-router-dom"; import {LoadingProvider, useLoadingSwitcher} from "../../hooks/useLoading.jsx"; import {useFetch} from "../../hooks/useFetch.js"; import {AxiosError} from "../../components/AxiosError.jsx"; @@ -8,7 +8,7 @@ import {apiAxios} from "../../utils/Tools.js"; import {toast} from "react-toastify"; import {SimpleReducer} from "../../utils/SimpleReducer.jsx"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; -import {faAdd, faTrashCan} from "@fortawesome/free-solid-svg-icons"; +import {faAdd, faGavel, faTrashCan} from "@fortawesome/free-solid-svg-icons"; import "./CompetitionRegisterAdmin.css" export function CompetitionRegisterAdmin({source}) { @@ -407,7 +407,15 @@ function FiltreBar({data, clubFilter, setClubFilter, catFilter, setCatFilter, so } function MakeCentralPanel({data, dispatch, id, setModalState, source}) { + const [searchParams] = useSearchParams(); + const registerType = searchParams.get("type") || "FREE"; + return <> + {(registerType === "FREE" || registerType === "CLUB_ADMIN") && source === "admin" && + Tips 1: Il est possible de bannir un combattant, ce qui l'empêchera d'être réinscrit par un autre moyen que par un administrateur de cette compétition. + Pour cela, cliquez sur la petite à côté de son nom.
+ Tips 2: Il est aussi possible de verrouiller les modifications de son inscription depuis sa fiche, ce qui l'empêchera d'être modifié/supprimé par lui-même et/ou un responsable de club. +
}
{data.map((req, index) => (
@@ -432,13 +440,42 @@ function MakeCentralPanel({data, dispatch, id, setModalState, source}) {
+ {(registerType === "FREE" || registerType === "CLUB_ADMIN") && source === "admin" && + }