From b419e2f58d555d730cc4af407e954c02a1ce8fe0 Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Tue, 20 Jan 2026 21:49:10 +0100 Subject: [PATCH] feat: add category registration system to club and user --- .../domain/service/CompetitionService.java | 8 ++-- .../ffsaf/domain/service/KeycloakService.java | 12 +++-- .../resources/lang/messages_fr.properties | 18 ++++---- src/main/webapp/src/Keycloak.js | 14 ------ .../competition/CompetitionRegisterAdmin.jsx | 3 +- .../src/pages/competition/CompetitionView.jsx | 45 ++++++++++++++++--- 6 files changed, 64 insertions(+), 36 deletions(-) delete mode 100644 src/main/webapp/src/Keycloak.js 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 d220b14..abcab52 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java @@ -349,7 +349,8 @@ public class CompetitionService { .chain(model -> registerRepository.find("competition.id = ?1 AND membre = ?2", id, model).firstResult() .call(rm -> rm == null ? Uni.createFrom().voidItem() : Mutiny.fetch(rm.getCategoriesInscrites())) - .map(rm -> rm == null ? List.of() : List.of(SimpleRegisterComb.fromModel(rm, List.of())))); + .map(rm -> rm == null ? List.of() : List.of(SimpleRegisterComb.fromModel(rm, List.of()) + .setCategorieInscrite(rm.getCategoriesInscrites())))); } public Uni addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data, @@ -423,7 +424,8 @@ public class CompetitionService { throw new DForbiddenException(trad.t("insc.err1")); })) .chain(combModel -> updateRegister(data, c, combModel, false))) - .map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences())); + .map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()) + .setCategorieInscrite(r.getCategoriesInscrites())); return repository.findById(id) .invoke(Unchecked.consumer(cm -> { @@ -438,7 +440,7 @@ public class CompetitionService { throw new DForbiddenException(trad.t("insc.err2")); })) .chain(combModel -> updateRegister(data, c, combModel, false))) - .map(r -> SimpleRegisterComb.fromModel(r, List.of())); + .map(r -> SimpleRegisterComb.fromModel(r, List.of()).setCategorieInscrite(r.getCategoriesInscrites())); } private Uni updateRegister(RegisterRequestData data, CompetitionModel c, diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java index 63cdfd5..0d66050 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java @@ -381,11 +381,15 @@ public class KeycloakService { } public Optional getUserById(String userId) { - UserResource user = keycloak.realm(realm).users().get(userId); - if (user == null) + try { + UserResource user = keycloak.realm(realm).users().get(userId); + if (user == null) + return Optional.empty(); + else + return Optional.of(user.toRepresentation()); + } catch (Exception e) { return Optional.empty(); - else - return Optional.of(user.toRepresentation()); + } } private String makeLogin(MembreModel model) { diff --git a/src/main/resources/lang/messages_fr.properties b/src/main/resources/lang/messages_fr.properties index 54f6d55..a24c844 100644 --- a/src/main/resources/lang/messages_fr.properties +++ b/src/main/resources/lang/messages_fr.properties @@ -44,8 +44,8 @@ service.momentanement.indisponible=Service momentan asso.introuvable=Association introuvable erreur.lors.calcul.du.trie=Erreur lors du calcul du tri page.out.of.range=Page out of range -le.membre.appartient.pas.a.votre.club=Le membre n°%d n?appartient pas à votre club -email.deja.utilise.par=L?adresse e-mail '%s' est déjà utilisée par %s %s +le.membre.appartient.pas.a.votre.club=Le membre n°%d n'appartient pas à votre club +email.deja.utilise.par=L'adresse e-mail '%s' est déjà utilisée par %s %s try.edit.licence=Pour enregistrer un nouveau membre, veuillez laisser le champ licence vide. (Tentative de modification non autorisée du nom sur la licence %d pour %s %s) email.deja.utilise=Adresse e-mail déjà utilisée regiter.new.membre=Pour enregistrer un nouveau membre, veuillez utiliser le bouton prévu à cet effet. @@ -61,23 +61,23 @@ licence.rm.err1=Impossible de supprimer une licence pour laquelle un paiement es licence.deja.demandee=Licence déjà demandée impossible.de.supprimer.une.licence.deja.validee=Impossible de supprimer une licence déjà validée impossible.de.supprimer.une.licence.deja.payee=Impossible de supprimer une licence déjà payée -vous.ne.pouvez.pas.creer.de.competition=Vous n?êtes pas autorisé à créer une compétition +vous.ne.pouvez.pas.creer.de.competition=Vous n'êtes pas autorisé à créer une compétition user.not.found=Utilisateur %s introuvable inscription.fermee=Inscription fermée -insc.err1=Vous n?êtes pas autorisé à inscrire ce membre (décision de l?administrateur de la compétition) -insc.err2=Vous n?êtes pas autorisé à vous inscrire (décision de l?administrateur de la compétition) -insc.err3=Modification bloquée par l?administrateur de la compétition +insc.err1=Vous n'êtes pas autorisé à inscrire ce membre (décision de l'administrateur de la compétition) +insc.err2=Vous n'êtes pas autorisé à vous inscrire (décision de l'administrateur de la compétition) +insc.err3=Modification bloquée par l'administrateur de la compétition licence.non.trouve=Licence %s introuvable nom.et.prenom.requis=Nom et prénom obligatoires combattant.non.trouve=Combattant %s %s introuvable -le.membre.n.existe.pas=Le membre n°%d n?existe pas +le.membre.n.existe.pas=Le membre n°%d n'existe pas competition.is.not.internal=Competition is not INTERNAL erreur.de.format.des.contacts=Format des contacts invalide competition.not.found=Compétition introuvable saison.non.valid=Saison invalide -demande.d.affiliation.deja.existante=Une demande d?affiliation existe déjà +demande.d.affiliation.deja.existante=Une demande d'affiliation existe déjà affiliation.deja.existante=Affiliation déjà existante licence.membre.n.1.inconnue=Licence du membre n°1 inconnue licence.membre.n.2.inconnue=Licence du membre n°2 inconnue licence.membre.n.3.inconnue=Licence du membre n°3 inconnue -demande.d.affiliation.non.trouve=Demande d?affiliation introuvable \ No newline at end of file +demande.d.affiliation.non.trouve=Demande d'affiliation introuvable \ No newline at end of file diff --git a/src/main/webapp/src/Keycloak.js b/src/main/webapp/src/Keycloak.js deleted file mode 100644 index de4e422..0000000 --- a/src/main/webapp/src/Keycloak.js +++ /dev/null @@ -1,14 +0,0 @@ -import Keycloak from "keycloak-js"; - -const vite_url = import.meta.env.VITE_URL; -const client_id = import.meta.env.VITE_CLIENT_ID; - -const keycloak = new Keycloak({ - url: `${vite_url}/auth-api`, - realm: "safca", - clientId: client_id, -}); - - - -export default keycloak; \ No newline at end of file diff --git a/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx b/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx index 48269b4..e69b816 100644 --- a/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx +++ b/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx @@ -132,7 +132,8 @@ function QuickAdd({sendRegister, source, data2, error2}) { - + a.name.localeCompare(b.name))} categories={categories} + setCategories={setCategories_}/>
diff --git a/src/main/webapp/src/pages/competition/CompetitionView.jsx b/src/main/webapp/src/pages/competition/CompetitionView.jsx index a8291ba..a9cebe6 100644 --- a/src/main/webapp/src/pages/competition/CompetitionView.jsx +++ b/src/main/webapp/src/pages/competition/CompetitionView.jsx @@ -3,9 +3,9 @@ import {useLoadingSwitcher} from "../../hooks/useLoading.jsx"; import {useFetch} from "../../hooks/useFetch.js"; import {AxiosError} from "../../components/AxiosError.jsx"; import {useAuth} from "../../hooks/useAuth.jsx"; -import {apiAxios, getToastMessage, isClubAdmin} from "../../utils/Tools.js"; +import {apiAxios, applyOverCategory, getCatName, getToastMessage, isClubAdmin} from "../../utils/Tools.js"; import {ThreeDots} from "react-loader-spinner"; -import {useEffect, useState} from "react"; +import React, {useEffect, useState} from "react"; import {toast} from "react-toastify"; import {useTranslation} from "react-i18next"; import i18n from "i18next"; @@ -97,15 +97,18 @@ function SelfRegister({data2}) { const {id} = useParams() const setLoading = useLoadingSwitcher() const {data, refresh, error} = useFetch(`/competition/${id}/register/user`, setLoading, 1) + const {data: data3, error: error2} = useFetch(`/competition/${id}/categories`, setLoading, 1) const {t} = useTranslation(); const [weight, setWeight] = useState("") const [cat, setCat] = useState(0) + const [categories, setCategories] = useState([]) useEffect(() => { if (data && data.length > 0) { setWeight(data[0].weight || "") setCat(data[0].overCategory || 0) + setCategories(data[0].categoriesInscrites || []) } }, [data]); @@ -129,14 +132,27 @@ function SelfRegister({data2}) { const handleSubmit = () => { sendSubmit({ - licence: 0, fname: "", lname: "", weight: weight, overCategory: cat, lockEdit: false, id: null + licence: 0, fname: "", lname: "", weight: weight, overCategory: cat, lockEdit: false, id: null, categoriesInscrites: categories }) } + const setCategories_ = (e, catId) => { + if (e.target.checked) { + if (!categories.includes(catId)) { + setCategories([...categories, catId]) + } + } else { + setCategories(categories.filter(c => c !== catId)) + } + } + + const currenCat = data?.length > 0 && data[0]?.categorie !== "" ? applyOverCategory(data[0]?.categorie, cat) : ""; + const availableCats = data3 ? (currenCat !== "" ? data3.filter(c => c.categories.includes(currenCat)) : data3).sort((a, b) => a.name.localeCompare(b.name)) : [] + return <> {data ? data.length > 0 - ?
+ ?

{t('comp.monInscription')}

{t("comp.modal.poids")} @@ -144,7 +160,7 @@ function SelfRegister({data2}) { name="weight" aria-describedby="weight" value={weight} onChange={e => setWeight(e.target.value)}/>
-
{t('comp.catégorieNormalisée')}: {data[0].categorie}
+
{t('comp.catégorieNormalisée')}: {getCatName(data[0].categorie)}
{t("comp.modal.surclassement")} setCategories_(e, cat.id)}/> + +
+
)} + } +
+