From 9954dd002cf738d643fa806fb77432a7e39eb1dc Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Thu, 5 Feb 2026 23:53:49 +0100 Subject: [PATCH] feat: add config for preset in category + filter on select comb --- .../ffsaf/domain/entity/CombEntity.java | 17 +++++++-- .../ffsaf/rest/data/PresetData.java | 2 + .../titionfire/ffsaf/ws/recv/RCategorie.java | 6 +++ .../titionfire/ffsaf/ws/recv/RRegister.java | 23 ++++++++---- .../titionfire/ffsaf/ws/send/SRegister.java | 21 ++++++----- .../src/components/cm/ListPresetSelect.jsx | 37 +++++++++++++++++++ .../src/pages/competition/editor/CMAdmin.jsx | 13 ++++++- .../editor/CategoryAdminContent.jsx | 7 ++-- .../editor/SelectCombModalContent.jsx | 15 ++++++-- 9 files changed, 113 insertions(+), 28 deletions(-) create mode 100644 src/main/webapp/src/components/cm/ListPresetSelect.jsx diff --git a/src/main/java/fr/titionfire/ffsaf/domain/entity/CombEntity.java b/src/main/java/fr/titionfire/ffsaf/domain/entity/CombEntity.java index 8083b58..b34bc13 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/entity/CombEntity.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/entity/CombEntity.java @@ -1,5 +1,6 @@ package fr.titionfire.ffsaf.domain.entity; +import fr.titionfire.ffsaf.data.model.CatPresetModel; import fr.titionfire.ffsaf.data.model.CompetitionGuestModel; import fr.titionfire.ffsaf.data.model.MembreModel; import fr.titionfire.ffsaf.data.model.RegisterModel; @@ -28,6 +29,7 @@ public class CombEntity { int overCategory; Integer weight; List teamMembers; + List categoriesInscrites; public static CombEntity fromModel(MembreModel model) { if (model == null) @@ -36,7 +38,7 @@ public class CombEntity { return new CombEntity(model.getId(), model.getLname(), model.getFname(), model.getCategorie(), model.getClub() == null ? null : model.getClub().getClubId(), model.getClub() == null ? "Sans club" : model.getClub().getName(), model.getGenre(), model.getCountry(), - 0, null, new ArrayList<>()); + 0, null, new ArrayList<>(), new ArrayList<>()); } @@ -47,7 +49,15 @@ public class CombEntity { return new CombEntity(model.getId() * -1, model.getLname(), model.getFname(), model.getCategorie(), null, model.getClub(), model.getGenre(), model.getCountry(), 0, model.getWeight(), Stream.concat(model.getComb().stream().map(CombEntity::fromModel), - model.getGuest().stream().map(CombEntity::fromModel)).toList()); + model.getGuest().stream().map(CombEntity::fromModel)).toList(), + new ArrayList<>()); + } + + public CombEntity addCategoriesInscrites(List categoriesInscrites) { + if (categoriesInscrites == null) + return this; + this.categoriesInscrites = categoriesInscrites.stream().map(CatPresetModel::getId).toList(); + return this; } public static CombEntity fromModel(RegisterModel registerModel) { @@ -58,6 +68,7 @@ public class CombEntity { return new CombEntity(model.getId(), model.getLname(), model.getFname(), registerModel.getCategorie(), registerModel.getClub2() == null ? null : registerModel.getClub2().getClubId(), registerModel.getClub2() == null ? "Sans club" : registerModel.getClub2().getName(), model.getGenre(), - model.getCountry(), registerModel.getOverCategory(), registerModel.getWeight(), new ArrayList<>()); + model.getCountry(), registerModel.getOverCategory(), registerModel.getWeight(), new ArrayList<>(), + new ArrayList<>()); } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/data/PresetData.java b/src/main/java/fr/titionfire/ffsaf/rest/data/PresetData.java index 60ec743..1993cda 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/data/PresetData.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/data/PresetData.java @@ -4,10 +4,12 @@ import fr.titionfire.ffsaf.data.model.CatPresetModel; import io.quarkus.runtime.annotations.RegisterForReflection; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.List; @Data +@NoArgsConstructor @AllArgsConstructor @RegisterForReflection public class PresetData { diff --git a/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java b/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java index ff8c81c..2f7dcf2 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java @@ -250,6 +250,12 @@ public class RCategorie { .replaceWithVoid(); } + @WSReceiver(code = "listPreset", permission = PermLevel.VIEW) + public Uni> listPreset(WebSocketConnection connection, Object o) { + return catPresetRepository.list("competition.uuid", connection.pathParam("uuid")) + .map(presets -> presets.stream().map(PresetData::fromModel).toList()); + } + @WSReceiver(code = "createClassementMatchs", permission = PermLevel.TABLE) public Uni createClassementMatchs(WebSocketConnection connection, Long categoryId) { return getById(categoryId, connection) diff --git a/src/main/java/fr/titionfire/ffsaf/ws/recv/RRegister.java b/src/main/java/fr/titionfire/ffsaf/ws/recv/RRegister.java index c1f7f7c..29f2374 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/recv/RRegister.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/recv/RRegister.java @@ -6,6 +6,7 @@ import fr.titionfire.ffsaf.ws.PermLevel; import io.quarkus.hibernate.reactive.panache.common.WithSession; import io.quarkus.runtime.annotations.RegisterForReflection; import io.quarkus.websockets.next.WebSocketConnection; +import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -24,14 +25,20 @@ public class RRegister { @WSReceiver(code = "getRegister", permission = PermLevel.TABLE) public Uni> getRegister(WebSocketConnection connection, Object o) { + ArrayList combEntities = new ArrayList<>(); return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult() - .call(cm -> Mutiny.fetch(cm.getInsc())) - .call(cm -> Mutiny.fetch(cm.getGuests())) - .map(cm -> { - ArrayList combEntities = new ArrayList<>(); - combEntities.addAll(cm.getInsc().stream().map(CombEntity::fromModel).toList()); - combEntities.addAll(cm.getGuests().stream().map(CombEntity::fromModel).toList()); - return combEntities; - }); + .call(cm -> Mutiny.fetch(cm.getInsc()) + .onItem().transformToMulti(Multi.createFrom()::iterable) + .call(r -> Mutiny.fetch(r.getCategoriesInscrites())) + .map(r -> CombEntity.fromModel(r).addCategoriesInscrites(r.getCategoriesInscrites())) + .collect().asList() + .invoke(combEntities::addAll)) + .call(cm -> Mutiny.fetch(cm.getGuests()) + .onItem().transformToMulti(Multi.createFrom()::iterable) + .call(r -> Mutiny.fetch(r.getCategoriesInscrites())) + .map(r -> CombEntity.fromModel(r).addCategoriesInscrites(r.getCategoriesInscrites())) + .collect().asList() + .invoke(combEntities::addAll)) + .replaceWith(combEntities); } } diff --git a/src/main/java/fr/titionfire/ffsaf/ws/send/SRegister.java b/src/main/java/fr/titionfire/ffsaf/ws/send/SRegister.java index 45920da..09ec345 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/send/SRegister.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/send/SRegister.java @@ -14,6 +14,7 @@ import io.quarkus.websockets.next.UserData; import io.smallrye.mutiny.Uni; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.hibernate.reactive.mutiny.Mutiny; import java.util.List; import java.util.UUID; @@ -30,18 +31,20 @@ public class SRegister { CardService cardService; public Uni sendRegister(String uuid, RegisterModel registerModel) { - return send(uuid, "sendRegister", CombEntity.fromModel(registerModel)) - .call(__ -> cardService.addTeamCartToNewComb(registerModel.getMembre().getId(), - registerModel.getClub2().getClubId(), registerModel.getClub2().getName(), - registerModel.getCompetition()) - .chain(cardModels -> send(uuid, "sendCards", cardModels))); + return Mutiny.fetch(registerModel.getCategoriesInscrites()).chain(o -> + send(uuid, "sendRegister", CombEntity.fromModel(registerModel).addCategoriesInscrites(o)) + .call(__ -> cardService.addTeamCartToNewComb(registerModel.getMembre().getId(), + registerModel.getClub2().getClubId(), registerModel.getClub2().getName(), + registerModel.getCompetition()) + .chain(cardModels -> send(uuid, "sendCards", cardModels)))); } public Uni sendRegister(String uuid, CompetitionGuestModel model) { - return send(uuid, "sendRegister", CombEntity.fromModel(model)) - .call(__ -> cardService.addTeamCartToNewComb(model.getId() * -1, - null, model.getClub(), model.getCompetition()) - .chain(cardModels -> send(uuid, "sendCards", cardModels))); + return Mutiny.fetch(model.getCategoriesInscrites()).chain(o -> + send(uuid, "sendRegister", CombEntity.fromModel(model).addCategoriesInscrites(o)) + .call(__ -> cardService.addTeamCartToNewComb(model.getId() * -1, + null, model.getClub(), model.getCompetition()) + .chain(cardModels -> send(uuid, "sendCards", cardModels)))); } public Uni sendRegisterRemove(String uuid, Long combId) { diff --git a/src/main/webapp/src/components/cm/ListPresetSelect.jsx b/src/main/webapp/src/components/cm/ListPresetSelect.jsx new file mode 100644 index 0000000..eb7b371 --- /dev/null +++ b/src/main/webapp/src/components/cm/ListPresetSelect.jsx @@ -0,0 +1,37 @@ +import {useRequestWS} from "../../hooks/useWS.jsx"; +import {AxiosError} from "../AxiosError.jsx"; +import {useTranslation} from "react-i18next"; +import React, {useId} from "react"; + +export function ListPresetSelect({disabled, value, onChange}) { + const id = useId() + const {data, error} = useRequestWS("listPreset", {}, null); + const {t} = useTranslation(); + return <> + {data + ?
+ + +
+ : error + ? + : + } + +} + +function Def() { + const {t} = useTranslation(); + + return
+ + +
; +} diff --git a/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx b/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx index 2ba76e1..1cdcf1e 100644 --- a/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx +++ b/src/main/webapp/src/pages/competition/editor/CMAdmin.jsx @@ -19,6 +19,7 @@ import {copyStyles} from "../../../utils/copyStyles.js"; import {StateWindow} from "./StateWindow.jsx"; import {CombName, useCombs} from "../../../hooks/useComb.jsx"; import {useCards, useCardsDispatch} from "../../../hooks/useCard.jsx"; +import {ListPresetSelect} from "../../../components/cm/ListPresetSelect.jsx"; const vite_url = import.meta.env.VITE_URL; @@ -610,6 +611,7 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) { const [fullClassement, setFullClassement] = useState(false) const [size, setSize] = useState(4) const [loserMatch, setLoserMatch] = useState(1) + const [preset, setPreset] = useState(-1) const {t} = useTranslation("cm"); const {sendRequest} = useWS(); @@ -621,6 +623,7 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) { setTournoi((state.type & 2) !== 0); setClassement(state.treeAreClassement !== undefined && state.treeAreClassement !== false); setFullClassement(state.fullClassement !== undefined && state.fullClassement !== false); + setPreset(state.preset?.id || -1); let trees_ = [] for (let i = 0; i < state?.raw_trees?.length; i++) { @@ -674,7 +677,8 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) { liceName: lice.trim(), type: nType, treeAreClassement: classement, - fullClassement: fullClassement + fullClassement: fullClassement, + preset: {id: preset !== -1 ? preset : null} } let nbMatch = -1; @@ -745,7 +749,10 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) { toast.promise(sendRequest('createCategory', { name: name.trim(), liceName: lice.trim(), - type: nType + type: nType, + treeAreClassement: classement, + fullClassement: fullClassement, + preset: {id: preset !== -1 ? preset : null} }), getToastMessage("toast.createCategory", "cm") ).then(id => { if (tournoi) { @@ -774,6 +781,8 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) { onChange={e => setName(e.target.value)}/> + +
- +
{cat && } @@ -177,7 +177,7 @@ export function CategoryContent({cat, catId, setCat, menuActions}) { } -function AddComb({groups, setGroups, removeGroup, menuActions}) { +function AddComb({groups, setGroups, removeGroup, menuActions, cat}) { const {data, setData} = useRequestWS("getRegister", null) const combDispatch = useCombsDispatch() const {dispatch} = useWS() @@ -243,7 +243,8 @@ function AddComb({groups, setGroups, removeGroup, menuActions}) { diff --git a/src/main/webapp/src/pages/competition/editor/SelectCombModalContent.jsx b/src/main/webapp/src/pages/competition/editor/SelectCombModalContent.jsx index 53fdb59..49cc6ef 100644 --- a/src/main/webapp/src/pages/competition/editor/SelectCombModalContent.jsx +++ b/src/main/webapp/src/pages/competition/editor/SelectCombModalContent.jsx @@ -1,10 +1,11 @@ import {useCountries} from "../../../hooks/useCountries.jsx"; -import {useEffect, useReducer, useRef, useState} from "react"; +import React, {useEffect, useReducer, useRef, useState} from "react"; import {CatList, getCatName, getToastMessage} from "../../../utils/Tools.js"; import {CombName} from "../../../hooks/useComb.jsx"; import {useWS} from "../../../hooks/useWS.jsx"; import {useTranslation} from "react-i18next"; import {toast} from "react-toastify"; +import {ListPresetSelect} from "../../../components/cm/ListPresetSelect.jsx"; function SelectReducer(state, action) { switch (action.type) { @@ -59,7 +60,7 @@ function SelectReducer(state, action) { } } -export function SelectCombModalContent({data, groups, setGroups, teamMode = false}) { +export function SelectCombModalContent({data, groups, setGroups, teamMode = false, defaultPreset = -1}) { const country = useCountries('fr') const {t} = useTranslation("cm"); const {sendRequest, dispatch} = useWS() @@ -77,6 +78,11 @@ export function SelectCombModalContent({data, groups, setGroups, teamMode = fals const [weightMax, setWeightMax] = useState(0) const [team, setTeam] = useState(false) const [teamName, setTeamName] = useState(""); + const [preset, setPreset] = useState(-1) + + useEffect(() => { + setPreset(defaultPreset) + }, [defaultPreset]) const handleSubmit = (e) => { e.preventDefault(); @@ -149,7 +155,8 @@ export function SelectCombModalContent({data, groups, setGroups, teamMode = fals && (weightMin === 0 || comb.weight !== null && comb.weight >= weightMin) && (weightMax === 0 || comb.weight !== null && comb.weight <= weightMax) && (teamMode && (comb.teamMembers == null || comb.teamMembers.length === 0) || !teamMode - && ((comb.teamMembers == null || comb.teamMembers.length === 0) !== team))) { + && ((comb.teamMembers == null || comb.teamMembers.length === 0) !== team)) + && (preset === -1 || comb.categoriesInscrites.includes(preset))) { dataOut[id] = dataIn[id]; } } @@ -215,6 +222,8 @@ export function SelectCombModalContent({data, groups, setGroups, teamMode = fals
+ +