From 29a11849940741fb08ce1d60776e8abd9f2822f1 Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Thu, 1 Jan 2026 19:43:25 +0100 Subject: [PATCH 1/4] feat: add Result Privacy membre setting --- .../ffsaf/data/model/CombModel.java | 9 + .../data/model/CompetitionGuestModel.java | 16 +- .../ffsaf/data/model/MatchModel.java | 46 +- .../ffsaf/data/model/MembreModel.java | 56 ++- .../ffsaf/domain/entity/MembreEntity.java | 64 --- .../ffsaf/domain/service/ResultService.java | 424 ++++++++++-------- .../ffsaf/rest/ExternalResultEndpoints.java | 5 +- .../ffsaf/rest/data/ResultCategoryData.java | 12 +- .../ffsaf/rest/data/SimpleMembre.java | 25 +- .../titionfire/ffsaf/utils/ResultPrivacy.java | 8 + src/main/webapp/src/components/Nav.jsx | 4 +- 11 files changed, 380 insertions(+), 289 deletions(-) create mode 100644 src/main/java/fr/titionfire/ffsaf/data/model/CombModel.java delete mode 100644 src/main/java/fr/titionfire/ffsaf/domain/entity/MembreEntity.java create mode 100644 src/main/java/fr/titionfire/ffsaf/utils/ResultPrivacy.java diff --git a/src/main/java/fr/titionfire/ffsaf/data/model/CombModel.java b/src/main/java/fr/titionfire/ffsaf/data/model/CombModel.java new file mode 100644 index 0000000..f8fe1f7 --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/data/model/CombModel.java @@ -0,0 +1,9 @@ +package fr.titionfire.ffsaf.data.model; + +import fr.titionfire.ffsaf.utils.ResultPrivacy; + +public interface CombModel { + Long getCombId(); + String getName(); + String getName(MembreModel model, ResultPrivacy privacy); +} diff --git a/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java b/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java index 697de65..4868c3a 100644 --- a/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java +++ b/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java @@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.data.model; import fr.titionfire.ffsaf.utils.Categorie; import fr.titionfire.ffsaf.utils.Genre; +import fr.titionfire.ffsaf.utils.ResultPrivacy; import io.quarkus.runtime.annotations.RegisterForReflection; import jakarta.persistence.*; import lombok.AllArgsConstructor; @@ -17,7 +18,7 @@ import lombok.Setter; @Entity @Table(name = "competition_guest") -public class CompetitionGuestModel { +public class CompetitionGuestModel implements CombModel { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; @@ -44,7 +45,18 @@ public class CompetitionGuestModel { this.lname = s.substring(s.indexOf(" ") + 1); } + @Override + public Long getCombId() { + return this.id * -1; + } + + @Override public String getName() { - return fname + " " + lname; + return this.fname + " " + this.lname; + } + + @Override + public String getName(MembreModel model, ResultPrivacy privacy) { + return getName(); } } diff --git a/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java b/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java index a6b9d73..7fb7b9a 100644 --- a/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java +++ b/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java @@ -1,6 +1,7 @@ package fr.titionfire.ffsaf.data.model; import fr.titionfire.ffsaf.utils.CompetitionSystem; +import fr.titionfire.ffsaf.utils.ResultPrivacy; import fr.titionfire.ffsaf.utils.ScoreEmbeddable; import io.quarkus.runtime.annotations.RegisterForReflection; import jakarta.persistence.*; @@ -9,6 +10,7 @@ import lombok.*; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Objects; @Getter @Setter @@ -65,19 +67,35 @@ public class MatchModel { @JoinColumn(name = "match", referencedColumnName = "id") List cardboard = new ArrayList<>(); + public String getC1Name(MembreModel model, ResultPrivacy privacy) { + if (c1_id != null) + return c1_id.getName(model, privacy); + if (c1_guest != null) + return c1_guest.getName(model, privacy); + return ""; + } + + public String getC2Name(MembreModel model, ResultPrivacy privacy) { + if (c2_id != null) + return c2_id.getName(model, privacy); + if (c2_guest != null) + return c2_guest.getName(model, privacy); + return ""; + } + public String getC1Name() { if (c1_id != null) - return c1_id.fname + " " + c1_id.lname; + return c1_id.getName(); if (c1_guest != null) - return c1_guest.fname + " " + c1_guest.lname; + return c1_guest.getName(); return ""; } public String getC2Name() { if (c2_id != null) - return c2_id.fname + " " + c2_id.lname; + return c2_id.getName(); if (c2_guest != null) - return c2_guest.fname + " " + c2_guest.lname; + return c2_guest.getName(); return ""; } @@ -94,4 +112,24 @@ public class MatchModel { } return sum; } + + public boolean isC1(Object comb) { + if (comb instanceof Long id_) { + if (id_ >= 0) + return Objects.equals(this.c1_id != null ? this.c1_id.getId() : null, id_); + else + return Objects.equals(this.c1_guest != null ? this.c1_guest.getId() : null, -id_); + } + return Objects.equals(this.c1_id, comb) || Objects.equals(this.c1_guest, comb); + } + + public boolean isC2(Object comb) { + if (comb instanceof Long id_) { + if (id_ >= 0) + return Objects.equals(this.c2_id != null ? this.c2_id.getId() : null, id_); + else + return Objects.equals(this.c2_guest != null ? this.c2_guest.getId() : null, -id_); + } + return Objects.equals(this.c2_id, comb) || Objects.equals(this.c2_guest, comb); + } } diff --git a/src/main/java/fr/titionfire/ffsaf/data/model/MembreModel.java b/src/main/java/fr/titionfire/ffsaf/data/model/MembreModel.java index 218c8c9..d83f232 100644 --- a/src/main/java/fr/titionfire/ffsaf/data/model/MembreModel.java +++ b/src/main/java/fr/titionfire/ffsaf/data/model/MembreModel.java @@ -1,9 +1,6 @@ package fr.titionfire.ffsaf.data.model; -import fr.titionfire.ffsaf.utils.Categorie; -import fr.titionfire.ffsaf.utils.Genre; -import fr.titionfire.ffsaf.utils.GradeArbitrage; -import fr.titionfire.ffsaf.utils.RoleAsso; +import fr.titionfire.ffsaf.utils.*; import io.quarkus.runtime.annotations.RegisterForReflection; import jakarta.persistence.*; import lombok.*; @@ -11,6 +8,7 @@ import org.eclipse.microprofile.openapi.annotations.media.Schema; import java.util.Date; import java.util.List; +import java.util.Objects; @Getter @Setter @@ -21,23 +19,23 @@ import java.util.List; @Entity @Table(name = "membre") -public class MembreModel implements LoggableModel { +public class MembreModel implements LoggableModel, CombModel { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Access(AccessType.PROPERTY) - @Schema(description = "L'identifiant du membre.", example = "1") + @Schema(description = "L'identifiant du membre.", examples = "1") Long id; - @Schema(description = "L'identifiant long du membre (userID).", example = "e81d1d35-d897-421e-8086-6c5e74d13c6e") + @Schema(description = "L'identifiant long du membre (userID).", examples = "e81d1d35-d897-421e-8086-6c5e74d13c6e") String userId; - @Schema(description = "Le nom du membre.", example = "Dupont") + @Schema(description = "Le nom du membre.", examples = "Dupont") String lname; - @Schema(description = "Le prénom du membre.", example = "Jean") + @Schema(description = "Le prénom du membre.", examples = "Jean") String fname; - @Schema(description = "La catégorie du membre.", example = "SENIOR") + @Schema(description = "La catégorie du membre.", examples = "SENIOR") Categorie categorie; @ManyToOne(fetch = FetchType.EAGER) @@ -45,29 +43,30 @@ public class MembreModel implements LoggableModel { @Schema(description = "Le club du membre.") ClubModel club; - @Schema(description = "Le genre du membre.", example = "H") + @Schema(description = "Le genre du membre.", examples = "H") Genre genre; - @Schema(description = "Le numéro de licence du membre.", example = "12345") + @Schema(description = "Le numéro de licence du membre.", examples = "12345") Integer licence; - @Schema(description = "Le pays du membre.", example = "FR") + @Schema(description = "Le pays du membre.", examples = "FR") String country; @Schema(description = "La date de naissance du membre.") Date birth_date; - @Schema(description = "L'adresse e-mail du membre.", example = "jean.dupont@example.com") + @Schema(description = "L'adresse e-mail du membre.", examples = "jean.dupont@examples.com") String email; - @Schema(description = "Le rôle du membre dans l'association.", example = "MEMBRE") + @Schema(description = "Le rôle du membre dans l'association.", examples = "MEMBRE") RoleAsso role; - @Schema(description = "Le grade d'arbitrage du membre.", example = "NA") + @Schema(description = "Le grade d'arbitrage du membre.", examples = "NA") GradeArbitrage grade_arbitrage; - @Schema(hidden = true) - String url_photo; + @Schema(description = "La confidentialité de ces résultats", examples = "PUBLIC") + @Column(nullable = false, columnDefinition = "smallint default 0") + ResultPrivacy resultPrivacy = ResultPrivacy.PUBLIC; @OneToMany(mappedBy = "membre", fetch = FetchType.LAZY, cascade = CascadeType.ALL) @Schema(description = "Les licences du membre. (optionnel)") @@ -100,4 +99,25 @@ public class MembreModel implements LoggableModel { ", grade_arbitrage=" + grade_arbitrage + '}'; } + + @Override + public Long getCombId() { + return this.id; + } + + @Override + public String getName() { + return this.fname + " " + this.lname; + } + + @Override + public String getName(MembreModel model, ResultPrivacy privacy) { + if (model == null || !Objects.equals(this.getId(), model.getId())) { + if (model == null && this.getResultPrivacy() != ResultPrivacy.PUBLIC) + return "Anonyme"; + if (this.getResultPrivacy().ordinal() > privacy.ordinal()) + return "Anonyme"; + } + return getName(); + } } diff --git a/src/main/java/fr/titionfire/ffsaf/domain/entity/MembreEntity.java b/src/main/java/fr/titionfire/ffsaf/domain/entity/MembreEntity.java deleted file mode 100644 index f979fb4..0000000 --- a/src/main/java/fr/titionfire/ffsaf/domain/entity/MembreEntity.java +++ /dev/null @@ -1,64 +0,0 @@ -package fr.titionfire.ffsaf.domain.entity; - -import fr.titionfire.ffsaf.data.model.MembreModel; -import fr.titionfire.ffsaf.utils.Categorie; -import fr.titionfire.ffsaf.utils.Genre; -import fr.titionfire.ffsaf.utils.GradeArbitrage; -import fr.titionfire.ffsaf.utils.RoleAsso; -import io.quarkus.runtime.annotations.RegisterForReflection; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; - -import java.util.Date; - -@Data -@Builder -@AllArgsConstructor -@RegisterForReflection -public class MembreEntity { - private long id; - private String lname = ""; - private String fname = ""; - private Categorie categorie; - private ClubEntity club; - private Genre genre; - private Integer licence; - private String country; - private Date birth_date; - private String email; - private RoleAsso role; - private GradeArbitrage grade_arbitrage; - private String url_photo; - - - public static MembreEntity fromModel(MembreModel model) { - if (model == null) - return null; - - return new MembreEntityBuilder() - .id(model.getId()) - .lname(model.getLname()) - .fname(model.getFname()) - .categorie(model.getCategorie()) - .club(ClubEntity.fromModel(model.getClub())) - .genre(model.getGenre()) - .licence(model.getLicence()) - .country(model.getCountry()) - .birth_date(model.getBirth_date()) - .email(model.getEmail()) - .role(model.getRole()) - .grade_arbitrage(model.getGrade_arbitrage()) - .url_photo(model.getUrl_photo()) - .build(); - } - - public static String getFullName(MembreModel model) { - return model.getFname() + " " + model.getLname(); - } - public String getFullName() { - return this.fname + " " + this.lname; - } - - -} diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java index e83009c..6b7afeb 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java @@ -3,6 +3,7 @@ package fr.titionfire.ffsaf.domain.service; import fr.titionfire.ffsaf.data.model.*; import fr.titionfire.ffsaf.data.repository.*; import fr.titionfire.ffsaf.rest.data.ResultCategoryData; +import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.utils.*; import io.quarkus.hibernate.reactive.panache.common.WithSession; @@ -16,9 +17,8 @@ import lombok.Builder; import org.hibernate.reactive.mutiny.Mutiny; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; @WithSession @@ -48,6 +48,50 @@ public class ResultService { private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("lang.String"); + private static final HashMap combTempIds = new HashMap<>(); + + private static String getCombTempId(Long key) { + synchronized (combTempIds) { + if (!combTempIds.containsKey(key)) { + combTempIds.put(key, UUID.randomUUID().toString()); + } + return combTempIds.get(key); + } + } + + private static Long getCombTempId(String value) { + synchronized (combTempIds) { + for (Map.Entry entry : combTempIds.entrySet()) { + if (entry.getValue().equals(value)) { + return entry.getKey(); + } + } + return null; + } + } + + private static final HashMap clubTempIds = new HashMap<>(); + + private static Long getClubTempId(String key) { + synchronized (clubTempIds) { + if (!clubTempIds.containsKey(key)) { + clubTempIds.put(key, (System.currentTimeMillis() + clubTempIds.size()) * -1); + } + return clubTempIds.get(key); + } + } + + private static String getClubTempId(Long value) { + synchronized (clubTempIds) { + for (Map.Entry entry : clubTempIds.entrySet()) { + if (entry.getValue().equals(value)) { + return entry.getKey(); + } + } + return null; + } + } + public Uni> getList(SecurityCtx securityCtx) { return membreService.getByAccountId(securityCtx.getSubject()) .chain(m -> registerRepository.list("membre = ?1", m)) @@ -70,11 +114,10 @@ public class ResultService { } public Uni> getCategory(String uuid, SecurityCtx securityCtx) { + AtomicReference membreModel = new AtomicReference<>(); return hasAccess(uuid, securityCtx) - .chain(m -> categoryRepository.list("compet.uuid = ?1", uuid) - .chain(cats -> matchRepository.list( - "(c1_id = ?1 OR c2_id = ?1 OR True) AND category IN ?2", //TODO rm OR True - m.getMembre(), cats))) + .invoke(m -> membreModel.set(m.getMembre())) + .chain(m -> matchRepository.list("category.compet.uuid = ?1", uuid)) .map(matchModels -> { HashMap> map = new HashMap<>(); for (MatchModel matchModel : matchModels) { @@ -88,12 +131,11 @@ public class ResultService { .onItem() .transformToMulti(Multi.createFrom()::iterable) .onItem().call(list -> Mutiny.fetch(list.get(0).getCategory().getTree())) - .onItem().transform(this::getData) + .onItem().transform(list -> getData(list, membreModel.get())) .collect().asList(); - } - private ResultCategoryData getData(List matchModels) { + private ResultCategoryData getData(List matchModels, MembreModel membreModel) { ResultCategoryData out = new ResultCategoryData(); CategoryModel categoryModel = matchModels.get(0).getCategory(); @@ -102,12 +144,12 @@ public class ResultService { out.setLiceName(categoryModel.getLiceName() == null ? new String[]{} : categoryModel.getLiceName().split(";")); out.setGenTime(System.currentTimeMillis()); - getArray2(matchModels, out); - getTree(categoryModel.getTree(), out); + getArray2(matchModels, membreModel, out); + getTree(categoryModel.getTree(), membreModel, out); return out; } - private void getArray2(List matchModels_, ResultCategoryData out) { + private void getArray2(List matchModels_, MembreModel membreModel, ResultCategoryData out) { List matchModels = matchModels_.stream().filter(o -> o.getCategory_ord() >= 0).toList(); HashMap> matchMap = new HashMap<>(); @@ -121,31 +163,30 @@ public class ResultService { matchMap.forEach((c, matchEntities) -> { List matchs = matchEntities.stream() .sorted(Comparator.comparing(MatchModel::getCategory_ord)) - .map(ResultCategoryData.PouleArrayData::fromModel) + .map(o -> ResultCategoryData.PouleArrayData.fromModel(o, membreModel, + ResultPrivacy.REGISTERED_ONLY_NO_DETAILS)) .toList(); List rankArray = matchEntities.stream() - .flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name())) + .flatMap(m -> Stream.of(m.getC1_id(), m.getC2_id(), m.getC1_guest(), m.getC2_guest())) .distinct() - .map(combName -> { + .filter(Objects::nonNull) + .map(comb -> { AtomicInteger w = new AtomicInteger(0); AtomicInteger pointMake = new AtomicInteger(0); AtomicInteger pointTake = new AtomicInteger(0); matchEntities.stream() - .filter(m -> m.isEnd() && (m.getC1Name().equals(combName) || m.getC2Name() - .equals(combName))) + .filter(m -> m.isEnd() && (m.isC1(comb) || m.isC2(comb))) .forEach(matchModel -> { int win = matchModel.win(); - if ((matchModel.getC1Name() - .equals(combName) && win > 0) || matchModel.getC2Name() - .equals(combName) && win < 0) + if ((matchModel.isC1(comb) && win > 0) || matchModel.isC2(comb) && win < 0) w.getAndIncrement(); for (ScoreEmbeddable score : matchModel.getScores()) { if (score.getS1() <= -900 || score.getS2() <= -900) continue; - if (matchModel.getC1Name().equals(combName)) { + if (matchModel.isC1(comb)) { pointMake.addAndGet(score.getS1()); pointTake.addAndGet(score.getS2()); } else { @@ -156,7 +197,8 @@ public class ResultService { }); float pointRate = (pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get(); - return new ResultCategoryData.RankArray(0, combName, w.get(), + return new ResultCategoryData.RankArray(0, + comb.getName(membreModel, ResultPrivacy.REGISTERED_ONLY_NO_DETAILS), w.get(), pointMake.get(), pointTake.get(), pointRate); }) .sorted(Comparator @@ -180,29 +222,30 @@ public class ResultService { }); } - private static void convertTree(TreeModel src, TreeNode dst) { - dst.setData(ResultCategoryData.TreeData.from(src.getMatch())); + private static void convertTree(TreeModel src, TreeNode dst, MembreModel membreModel, + ResultPrivacy privacy) { + dst.setData(ResultCategoryData.TreeData.from(src.getMatch(), membreModel, privacy)); if (src.getLeft() != null) { dst.setLeft(new TreeNode<>()); - convertTree(src.getLeft(), dst.getLeft()); + convertTree(src.getLeft(), dst.getLeft(), membreModel, privacy); } if (src.getRight() != null) { dst.setRight(new TreeNode<>()); - convertTree(src.getRight(), dst.getRight()); + convertTree(src.getRight(), dst.getRight(), membreModel, privacy); } } public Uni getCategoryPublic(String uuid, long poule) { return matchRepository.list("category.compet.uuid = ?1 AND category.id = ?2", uuid, poule) .call(list -> Mutiny.fetch(list.get(0).getCategory().getTree())) - .map(this::getData); + .map(list -> getData(list, null)); } - private void getTree(List treeModels, ResultCategoryData out) { + private void getTree(List treeModels, MembreModel membreModel, ResultCategoryData out) { ArrayList> trees = new ArrayList<>(); treeModels.stream().filter(t -> t.getLevel() != 0).forEach(treeModel -> { TreeNode root = new TreeNode<>(); - convertTree(treeModel, root); + convertTree(treeModel, root, membreModel, ResultPrivacy.REGISTERED_ONLY_NO_DETAILS); trees.add(root); }); out.setTrees(trees); @@ -210,14 +253,14 @@ public class ResultService { public Uni getAllCombArray(String uuid, SecurityCtx securityCtx) { return hasAccess(uuid, securityCtx) - .chain(__ -> getAllCombArray(uuid)); + .chain(r -> getAllCombArray_(uuid, r.getMembre())); } public Uni getAllCombArrayPublic(String uuid) { - return getAllCombArray(uuid); + return getAllCombArray_(uuid, null); } - public Uni getAllCombArray(String uuid) { + private Uni getAllCombArray_(String uuid, MembreModel membreModel) { return registerRepository.list("competition.uuid = ?1", uuid) .chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid) .map(matchModels -> new Pair<>(registers, matchModels))) @@ -228,57 +271,42 @@ public class ResultService { CombsArrayData.CombsArrayDataBuilder builder = CombsArrayData.builder(); List combs = matchModels.stream() - .flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name())) + .flatMap(m -> Stream.of(m.getC1_id(), m.getC2_id(), m.getC1_guest(), m.getC2_guest())) .filter(Objects::nonNull) .distinct() - .map(combName -> { + .map(comb -> { var builder2 = CombsArrayData.CombsData.builder(); AtomicInteger w = new AtomicInteger(0); AtomicInteger l = new AtomicInteger(0); AtomicInteger pointMake = new AtomicInteger(); AtomicInteger pointTake = new AtomicInteger(); - matchModels.stream() - .filter(m -> m.isEnd() && (m.getC1Name().equals(combName) - || m.getC2Name().equals(combName))) - .forEach(matchModel -> { - int win = matchModel.win(); - if ((combName.equals(matchModel.getC1Name()) && win > 0) || - combName.equals(matchModel.getC2Name()) && win < 0) { - w.getAndIncrement(); - } else { - l.getAndIncrement(); - } - - matchModel.getScores().stream() - .filter(s -> s.getS1() > -900 && s.getS2() > -900) - .forEach(score -> { - if (combName.equals(matchModel.getC1Name())) { - pointMake.addAndGet(score.getS1()); - pointTake.addAndGet(score.getS2()); - } else { - pointMake.addAndGet(score.getS2()); - pointTake.addAndGet(score.getS1()); - } - }); - }); + makeStat(matchModels, comb, w, l, pointMake, pointTake); Categorie categorie = null; - ClubModel club = null; + String clubName = null; Optional register = registers.stream() - .filter(r -> r.getName().equals(combName)).findFirst(); + .filter(r -> Objects.equals(r.getMembre(), comb)).findFirst(); if (register.isPresent()) { - categorie = register.get().getCategorie(); - club = register.get().getClub2(); + categorie = register.get().getCategorie2(); + ClubModel club = register.get().getClub2(); + clubName = (club == null) ? BUNDLE.getString("no.licence") : club.getName(); + } else if (comb instanceof CompetitionGuestModel guestModel) { + categorie = guestModel.getCategorie(); + clubName = guestModel.getClub(); + } else if (comb instanceof MembreModel model) { + categorie = model.getCategorie(); + clubName = (model.getClub() == null) ? BUNDLE.getString( + "no.licence") : model.getClub().getName(); } builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE)); - builder2.name(combName); + builder2.name(comb.getName(membreModel, ResultPrivacy.REGISTERED_ONLY)); builder2.w(w.get()); builder2.l(l.get()); builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get()); - builder2.club((club == null) ? BUNDLE.getString("no.licence") : club.getName()); + builder2.club(clubName); builder2.pointMake(pointMake.get()); builder2.pointTake(pointTake.get()); builder2.ratioPoint( @@ -298,62 +326,62 @@ public class ResultService { }); } - public Uni> getCombList(String uuid) { - return registerRepository.list("competition.uuid = ?1", uuid) + public Uni> getCombList(String uuid, ResultPrivacy privacy) { + return registerRepository.list("competition.uuid = ?1 AND membre.resultPrivacy <= ?2", uuid, privacy) .map(models -> { HashMap map = new HashMap<>(); - models.forEach(registerEmbeddable -> { - map.put(Utils.getFullName(registerEmbeddable.getMembre()), - registerEmbeddable.getMembre().getFname() + "¤" + registerEmbeddable.getMembre() - .getLname()); - }); + models.forEach( + r -> map.put(Utils.getFullName(r.getMembre()), getCombTempId(r.getMembre().getId()))); return map; }) .chain(map -> competitionGuestRepository.list("competition.uuid = ?1", uuid) .map(models -> { models.forEach(guestModel -> map.put(Utils.getFullName(guestModel), - guestModel.getFname() + "¤" + guestModel.getLname())); + getCombTempId(guestModel.getId() * -1))); return map; }) ); } - public Uni getCombArrayPublic(String uuid, String fname, String lname) { + public Uni getCombArrayPublic(String uuid, String combTempId, ResultPrivacy privacy) { CombArrayData.CombArrayDataBuilder builder = CombArrayData.builder(); - AtomicBoolean guest = new AtomicBoolean(false); - AtomicLong id = new AtomicLong(0); + Long id = getCombTempId(combTempId); + if (id == null) { + return Uni.createFrom().failure(new DForbiddenException("Comb not found")); + } - return registerRepository.find("membre.fname = ?1 AND membre.lname = ?2 AND competition.uuid = ?3", fname, - lname, uuid).firstResult() - .chain(registerModel -> { - if (registerModel == null) { - return competitionGuestRepository.find("fname = ?1 AND lname = ?2 AND competition.uuid = ?3", - fname, lname, uuid).firstResult() - .chain(guestModel -> { - builder.name(Utils.getFullName(guestModel)); - builder.club(guestModel.getClub()); - guest.set(true); - id.set(guestModel.getId()); - builder.cat((guestModel.getCategorie() == null) ? "---" : guestModel.getCategorie() - .getName(BUNDLE)); + Uni> uni; + if (id >= 0) { + uni = registerRepository.find("membre.id = ?1 AND competition.uuid = ?2 AND membre.resultPrivacy <= ?3", id, + uuid, privacy).firstResult() + .chain(Unchecked.function(registerModel -> { + if (registerModel == null) + throw new DBadRequestException("Combattant non inscrit"); - return matchRepository.list( - "category.compet.uuid = ?1 AND (c1_guest = ?2 OR c2_guest = ?2)", uuid, - guestModel); - }); - } - builder.name(Utils.getFullName(registerModel.getMembre())); - builder.club((registerModel.getClub2() == null) ? BUNDLE.getString( - "no.licence") : registerModel.getClub2().getName()); - id.set(registerModel.getMembre().getId()); - builder.cat((registerModel.getCategorie2() == null) ? "---" : registerModel.getCategorie2() - .getName(BUNDLE)); + builder.name(Utils.getFullName(registerModel.getMembre())); + builder.club((registerModel.getClub2() == null) ? BUNDLE.getString( + "no.licence") : registerModel.getClub2().getName()); + builder.cat((registerModel.getCategorie2() == null) ? "---" : registerModel.getCategorie2() + .getName(BUNDLE)); - return matchRepository.list("category.compet.uuid = ?1 AND (c1_id = ?2 OR c2_id = ?2)", uuid, - registerModel.getMembre()); - }) - .invoke(matchModels -> { + return matchRepository.list("category.compet.uuid = ?1 AND (c1_id = ?2 OR c2_id = ?2)", uuid, + registerModel.getMembre()); + })); + } else { + uni = competitionGuestRepository.find("id = ?1 AND competition.uuid = ?2", -id, uuid).firstResult() + .chain(guestModel -> { + builder.name(Utils.getFullName(guestModel)); + builder.club(guestModel.getClub()); + builder.cat((guestModel.getCategorie() == null) ? "---" : guestModel.getCategorie() + .getName(BUNDLE)); + + return matchRepository.list("category.compet.uuid = ?1 AND (c1_guest = ?2 OR c2_guest = ?2)", + uuid, guestModel); + }); + } + + return uni.invoke(matchModels -> { List pouleModels = matchModels.stream().map(MatchModel::getCategory).distinct() .toList(); List matchs = new ArrayList<>(); @@ -375,9 +403,7 @@ public class ResultService { AtomicInteger pointMake = new AtomicInteger(); AtomicInteger pointTake = new AtomicInteger(); - if ((!guest.get() && matchModel.getC1_id() != null && matchModel.getC1_id().getId() == id.get()) - || (guest.get() && matchModel.getC1_guest() != null && matchModel.getC1_guest() - .getId() == id.get())) { + if (matchModel.isC1(id)) { builder2.adv(Utils.getFullName(matchModel.getC2_id(), matchModel.getC2_guest())); if (matchModel.isEnd()) { matchModel.getScores().stream() @@ -456,105 +482,147 @@ public class ResultService { } } - public Uni> getClubList(String uuid) { // TODO add guest club + public Uni> getClubList(String uuid) { return registerRepository.list("competition.uuid = ?1", uuid) .map(registers -> { HashMap registerMap = new HashMap<>(); registers.stream().map(RegisterModel::getClub2).distinct().filter(Objects::nonNull) .forEach(registerClub -> registerMap.put(registerClub.getName(), registerClub.getId())); return registerMap; - }); + }) + .chain(map -> competitionGuestRepository.list("competition.uuid = ?1", uuid) + .map(guests -> { + guests.stream().map(CompetitionGuestModel::getClub).distinct() + .filter(Objects::nonNull) + .forEach(guestClub -> map.putIfAbsent(guestClub, + getClubTempId(guestClub))); + return map; + }) + ); } public Uni getClubArray(String uuid, SecurityCtx securityCtx) { - return hasAccess(uuid, securityCtx).chain(cm_register -> getClubArray(uuid, cm_register.getClub2())); + return hasAccess(uuid, securityCtx).chain(cm_register -> + registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid, cm_register.getClub2()) + .chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid) + .map(matchModels -> + getClubArray2(cm_register.getClub2().getName(), + registers.stream().map(o -> (CombModel) o.getMembre()).toList(), + matchModels, registers, cm_register.getMembre())))); } public Uni getClubArrayPublic(String uuid, Long id) { - return clubRepository.findById(id).chain(clubModel -> getClubArray(uuid, clubModel)); + if (id < 0) { + String clubName = getClubTempId(id); + if (clubName == null) { + return Uni.createFrom().failure(new DForbiddenException("Club not found")); + } + + return competitionGuestRepository.list("competition.uuid = ?1 AND club = ?2", uuid, clubName) + .call(list -> { + if (list.isEmpty()) + return Uni.createFrom().failure(new DBadRequestException("Club not found")); + return Uni.createFrom().voidItem(); + }) + .chain(guests -> matchRepository.list( + "category.compet.uuid = ?1 AND (c1_guest IN ?2 OR c2_guest IN ?2)", uuid, guests) + .map(matchModels -> + getClubArray2(clubName, guests.stream().map(o -> (CombModel) o).toList(), + matchModels, new ArrayList<>(), null))); + } else { + return clubRepository.findById(id).chain(clubModel -> + registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid, clubModel) + .chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid) + .map(matchModels -> + getClubArray2(clubModel.getName(), + registers.stream().map(o -> (CombModel) o.getMembre()).toList(), + matchModels, registers, null)))); + } } - public Uni getClubArray(String uuid, ClubModel clubModel) { + private ClubArrayData getClubArray2(String name, List combs, List matchModels, + List registers, MembreModel membreModel) { ClubArrayData.ClubArrayDataBuilder builder = ClubArrayData.builder(); - builder.name(clubModel.getName()); + builder.name(name); + builder.nb_insc(combs.size()); - return registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid, clubModel) - .chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid) - .map(matchModels -> new Pair<>(registers, matchModels))) - .map(pair -> { - List registers = pair.getKey(); - List matchModels = pair.getValue(); + AtomicInteger tt_win = new AtomicInteger(0); + AtomicInteger tt_match = new AtomicInteger(0); - builder.nb_insc(registers.size()); + List combData = combs.stream().map(comb -> { + var builder2 = ClubArrayData.CombData.builder(); + AtomicInteger w = new AtomicInteger(0); + AtomicInteger l = new AtomicInteger(0); + AtomicInteger pointMake = new AtomicInteger(); + AtomicInteger pointTake = new AtomicInteger(); - AtomicInteger tt_win = new AtomicInteger(0); - AtomicInteger tt_match = new AtomicInteger(0); + makeStat(matchModels, comb, w, l, pointMake, pointTake); - List combData = registers.stream().map(register -> { - var builder2 = ClubArrayData.CombData.builder(); - AtomicInteger w = new AtomicInteger(0); - AtomicInteger l = new AtomicInteger(0); - AtomicInteger pointMake = new AtomicInteger(); - AtomicInteger pointTake = new AtomicInteger(); + Categorie categorie = null; - matchModels.stream() - .filter(m -> m.isEnd() && (register.getMembre().equals(m.getC1_id()) - || register.getMembre().equals(m.getC2_id()))) - .forEach(matchModel -> { - int win = matchModel.win(); - if ((register.getMembre().equals(matchModel.getC1_id()) && win > 0) || - register.getMembre().equals(matchModel.getC2_id()) && win < 0) { - w.getAndIncrement(); - } else { - l.getAndIncrement(); - } + Optional register = registers.stream() + .filter(r -> Objects.equals(r.getMembre(), comb)).findFirst(); + if (register.isPresent()) { + categorie = register.get().getCategorie2(); + } else if (comb instanceof CompetitionGuestModel guestModel) { + categorie = guestModel.getCategorie(); + } else if (comb instanceof MembreModel model) { + categorie = model.getCategorie(); + } - matchModel.getScores().stream() - .filter(s -> s.getS1() > -900 && s.getS2() > -900) - .forEach(score -> { - if (register.getMembre().equals(matchModel.getC1_id())) { - pointMake.addAndGet(score.getS1()); - pointTake.addAndGet(score.getS2()); - } else { - pointMake.addAndGet(score.getS2()); - pointTake.addAndGet(score.getS1()); - } - }); - }); + builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE)); + builder2.name(comb.getName(membreModel, ResultPrivacy.REGISTERED_ONLY)); + builder2.w(w.get()); + builder2.l(l.get()); + builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get()); + builder2.pointMake(pointMake.get()); + builder2.pointTake(pointTake.get()); + builder2.ratioPoint((pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get()); - Categorie categorie = register.getCategorie(); - if (categorie == null) - categorie = register.getMembre().getCategorie(); + tt_win.addAndGet(w.get()); + tt_match.addAndGet(w.get() + l.get()); - builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE)); - builder2.name(register.getName()); - builder2.w(w.get()); - builder2.l(l.get()); - builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get()); - builder2.pointMake(pointMake.get()); - builder2.pointTake(pointTake.get()); - builder2.ratioPoint( - (pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get()); + return builder2.build(); + }) + .sorted(Comparator.comparing(ClubArrayData.CombData::name)) + .toList(); - tt_win.addAndGet(w.get()); - tt_match.addAndGet(w.get() + l.get()); + builder.nb_match(tt_match.get()); + builder.match_w(tt_win.get()); + builder.ratioVictoire((float) combData.stream().filter(c -> c.l + c.w != 0) + .mapToDouble(ClubArrayData.CombData::ratioVictoire).average().orElse(0L)); + builder.pointMake(combData.stream().mapToInt(ClubArrayData.CombData::pointMake).sum()); + builder.pointTake(combData.stream().mapToInt(ClubArrayData.CombData::pointTake).sum()); + builder.ratioPoint((float) combData.stream().filter(c -> c.l + c.w != 0) + .mapToDouble(ClubArrayData.CombData::ratioPoint).average().orElse(0L)); + builder.combs(combData); - return builder2.build(); - }) - .sorted(Comparator.comparing(ClubArrayData.CombData::name)) - .toList(); + return builder.build(); + } - builder.nb_match(tt_match.get()); - builder.match_w(tt_win.get()); - builder.ratioVictoire((float) combData.stream().filter(c -> c.l + c.w != 0) - .mapToDouble(ClubArrayData.CombData::ratioVictoire).average().orElse(0L)); - builder.pointMake(combData.stream().mapToInt(ClubArrayData.CombData::pointMake).sum()); - builder.pointTake(combData.stream().mapToInt(ClubArrayData.CombData::pointTake).sum()); - builder.ratioPoint((float) combData.stream().filter(c -> c.l + c.w != 0) - .mapToDouble(ClubArrayData.CombData::ratioPoint).average().orElse(0L)); - builder.combs(combData); + private static void makeStat(List matchModels, CombModel comb, AtomicInteger w, AtomicInteger l, + AtomicInteger pointMake, AtomicInteger pointTake) { + matchModels.stream() + .filter(m -> m.isEnd() && (m.isC1(comb) || m.isC2(comb))) + .forEach(matchModel -> { + int win = matchModel.win(); + if ((matchModel.isC1(comb) && win > 0) || matchModel.isC2(comb) && win < 0) { + w.getAndIncrement(); + } else { + l.getAndIncrement(); + } - return builder.build(); + matchModel.getScores().stream() + .filter(s -> s.getS1() > -900 && s.getS2() > -900) + .forEach(score -> { + if (matchModel.isC1(comb)) { + pointMake.addAndGet(score.getS1()); + pointTake.addAndGet(score.getS2()); + } else { + pointMake.addAndGet(score.getS2()); + pointTake.addAndGet(score.getS1()); + } + }); }); } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java index aee3914..cd9a543 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java @@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.domain.service.ResultService; import fr.titionfire.ffsaf.domain.service.UpdateService; +import fr.titionfire.ffsaf.utils.ResultPrivacy; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.ws.rs.*; @@ -46,7 +47,7 @@ public class ExternalResultEndpoints { @Path("/comb/list") @Produces(MediaType.APPLICATION_JSON) public Uni> combList() { - return resultService.getCombList(id); + return resultService.getCombList(id, ResultPrivacy.PUBLIC); } @GET @@ -55,7 +56,7 @@ public class ExternalResultEndpoints { public Uni getArray(@QueryParam("comb") String comb) { if (comb.equals("0")) return Uni.createFrom().item(""); - return resultService.getCombArrayPublic(id, comb.substring(0, comb.indexOf('¤')), comb.substring(comb.indexOf('¤') + 1)); + return resultService.getCombArrayPublic(id, comb, ResultPrivacy.PUBLIC); } @GET diff --git a/src/main/java/fr/titionfire/ffsaf/rest/data/ResultCategoryData.java b/src/main/java/fr/titionfire/ffsaf/rest/data/ResultCategoryData.java index 3ff949f..1ea8279 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/data/ResultCategoryData.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/data/ResultCategoryData.java @@ -1,6 +1,8 @@ package fr.titionfire.ffsaf.rest.data; import fr.titionfire.ffsaf.data.model.MatchModel; +import fr.titionfire.ffsaf.data.model.MembreModel; +import fr.titionfire.ffsaf.utils.ResultPrivacy; import fr.titionfire.ffsaf.utils.ScoreEmbeddable; import fr.titionfire.ffsaf.utils.TreeNode; import io.quarkus.runtime.annotations.RegisterForReflection; @@ -38,15 +40,15 @@ public class ResultCategoryData { @RegisterForReflection public record PouleArrayData(String red, boolean red_w, List score, boolean blue_w, String blue, boolean end) { - public static PouleArrayData fromModel(MatchModel matchModel) { + public static PouleArrayData fromModel(MatchModel matchModel, MembreModel membreModel, ResultPrivacy privacy) { return new PouleArrayData( - matchModel.getC1Name(), + matchModel.getC1Name(membreModel, privacy), matchModel.isEnd() && matchModel.win() > 0, matchModel.isEnd() ? matchModel.getScores().stream().map(s -> new Integer[]{s.getS1(), s.getS2()}).toList() : new ArrayList<>(), matchModel.isEnd() && matchModel.win() < 0, - matchModel.getC2Name(), + matchModel.getC2Name(membreModel, privacy), matchModel.isEnd()); } } @@ -54,8 +56,8 @@ public class ResultCategoryData { @RegisterForReflection public static record TreeData(long id, String c1FullName, String c2FullName, List scores, boolean end) { - public static TreeData from(MatchModel match) { - return new TreeData(match.getId(), match.getC1Name(), match.getC2Name(), match.getScores(), match.isEnd()); + public static TreeData from(MatchModel match, MembreModel membreModel, ResultPrivacy privacy) { + return new TreeData(match.getId(), match.getC1Name(membreModel, privacy), match.getC2Name(membreModel, privacy), match.getScores(), match.isEnd()); } } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/data/SimpleMembre.java b/src/main/java/fr/titionfire/ffsaf/rest/data/SimpleMembre.java index f2cf3fe..c8c5fa3 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/data/SimpleMembre.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/data/SimpleMembre.java @@ -19,34 +19,32 @@ import java.util.Date; @AllArgsConstructor @RegisterForReflection public class SimpleMembre { - @Schema(description = "L'identifiant du membre.", example = "1") + @Schema(description = "L'identifiant du membre.", examples = "1") private long id; - @Schema(description = "L'identifiant long du membre (userID).", example = "e81d1d35-d897-421e-8086-6c5e74d13c6e") + @Schema(description = "L'identifiant long du membre (userID).", examples = "e81d1d35-d897-421e-8086-6c5e74d13c6e") private String userId; - @Schema(description = "Le nom du membre.", example = "Dupont") + @Schema(description = "Le nom du membre.", examples = "Dupont") private String lname = ""; - @Schema(description = "Le prénom du membre.", example = "Jean") + @Schema(description = "Le prénom du membre.", examples = "Jean") private String fname = ""; - @Schema(description = "La catégorie du membre.", example = "SENIOR") + @Schema(description = "La catégorie du membre.", examples = "SENIOR") private Categorie categorie; @Schema(description = "Le club du membre.") private SimpleClubModel club; - @Schema(description = "Le genre du membre.", example = "H") + @Schema(description = "Le genre du membre.", examples = "H") private Genre genre; - @Schema(description = "Le numéro de licence du membre.", example = "12345") + @Schema(description = "Le numéro de licence du membre.", examples = "12345") private Integer licence; - @Schema(description = "Le pays du membre.", example = "FR") + @Schema(description = "Le pays du membre.", examples = "FR") private String country; @Schema(description = "La date de naissance du membre.") private Date birth_date; - @Schema(description = "L'adresse e-mail du membre.", example = "jean.dupont@example.com") + @Schema(description = "L'adresse e-mail du membre.", examples = "jean.dupont@examples.com") private String email; - @Schema(description = "Le rôle du membre dans l'association.", example = "MEMBRE") + @Schema(description = "Le rôle du membre dans l'association.", examples = "MEMBRE") private RoleAsso role; - @Schema(description = "Le grade d'arbitrage du membre.", example = "N/A") + @Schema(description = "Le grade d'arbitrage du membre.", examples = "N/A") private GradeArbitrage grade_arbitrage; - @Schema(hidden = true) - private String url_photo; public static SimpleMembre fromModel(MembreModel model) { if (model == null) @@ -66,7 +64,6 @@ public class SimpleMembre { .email(model.getEmail()) .role(model.getRole()) .grade_arbitrage(model.getGrade_arbitrage()) - .url_photo(model.getUrl_photo()) .build(); } } diff --git a/src/main/java/fr/titionfire/ffsaf/utils/ResultPrivacy.java b/src/main/java/fr/titionfire/ffsaf/utils/ResultPrivacy.java new file mode 100644 index 0000000..6ae7042 --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/utils/ResultPrivacy.java @@ -0,0 +1,8 @@ +package fr.titionfire.ffsaf.utils; + +public enum ResultPrivacy { + PUBLIC, + REGISTERED_ONLY, + REGISTERED_ONLY_NO_DETAILS, + PRIVATE; +} diff --git a/src/main/webapp/src/components/Nav.jsx b/src/main/webapp/src/components/Nav.jsx index 021255f..f3693f2 100644 --- a/src/main/webapp/src/components/Nav.jsx +++ b/src/main/webapp/src/components/Nav.jsx @@ -44,9 +44,9 @@ function AffiliationMenu() { } function CompMenu() { - const {is_authenticated, userinfo} = useAuth() + const {is_authenticated} = useAuth() - if (!is_authenticated || !userinfo?.roles?.includes("federation_admin")) + if (!is_authenticated) return <> return
  • From 71a4d98434f956c02326a7b0a3be3b1962103d4d Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Fri, 2 Jan 2026 13:47:54 +0100 Subject: [PATCH 2/4] fix: club remove --- .../java/fr/titionfire/ffsaf/domain/service/ClubService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java index 16fb4b8..f790dbe 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java @@ -292,7 +292,8 @@ public class ClubService { Uni.join().all(list.stream().filter(m -> m.getUserId() != null) .map(m -> keycloakService.clearUser(m.getUserId())).toList()) .andCollectFailures()) - .chain(list -> Panache.withTransaction(() -> combRepository.persist(list))) + .chain(list -> list.isEmpty() ? Uni.createFrom().voidItem() : + Panache.withTransaction(() -> combRepository.persist(list))) .map(o -> club) ) .call(clubModel -> (clubModel.getClubId() == null) ? Uni.createFrom() From 82231744af4f6de687cd8d4fb364965bd59812c3 Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Fri, 2 Jan 2026 13:48:36 +0100 Subject: [PATCH 3/4] feat: improve result page design --- .../ffsaf/domain/service/ResultService.java | 52 ++--- .../ffsaf/rest/ExternalResultEndpoints.java | 5 +- .../ffsaf/rest/ResultEndpoints.java | 38 +++- .../webapp/src/pages/result/ResultView.jsx | 214 ++++++++++++++---- 4 files changed, 225 insertions(+), 84 deletions(-) diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java index 6b7afeb..3ed9a78 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java @@ -18,7 +18,6 @@ import org.hibernate.reactive.mutiny.Mutiny; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; @WithSession @@ -113,26 +112,17 @@ public class ResultService { }); } - public Uni> getCategory(String uuid, SecurityCtx securityCtx) { - AtomicReference membreModel = new AtomicReference<>(); - return hasAccess(uuid, securityCtx) - .invoke(m -> membreModel.set(m.getMembre())) - .chain(m -> matchRepository.list("category.compet.uuid = ?1", uuid)) - .map(matchModels -> { - HashMap> map = new HashMap<>(); - for (MatchModel matchModel : matchModels) { - if (!map.containsKey(matchModel.getCategory().getId())) - map.put(matchModel.getCategory().getId(), new ArrayList<>()); - map.get(matchModel.getCategory().getId()).add(matchModel); - } + public Uni getCategory(String uuid, long poule, SecurityCtx securityCtx) { + return hasAccess(uuid, securityCtx).chain(r -> + matchRepository.list("category.compet.uuid = ?1 AND category.id = ?2", uuid, poule) + .call(list -> Mutiny.fetch(list.get(0).getCategory().getTree())) + .map(list -> getData(list, r.getMembre()))); + } - return map.values(); - }) - .onItem() - .transformToMulti(Multi.createFrom()::iterable) - .onItem().call(list -> Mutiny.fetch(list.get(0).getCategory().getTree())) - .onItem().transform(list -> getData(list, membreModel.get())) - .collect().asList(); + public Uni getCategory(String uuid, long poule) { + return matchRepository.list("category.compet.uuid = ?1 AND category.id = ?2", uuid, poule) + .call(list -> Mutiny.fetch(list.get(0).getCategory().getTree())) + .map(list -> getData(list, null)); } private ResultCategoryData getData(List matchModels, MembreModel membreModel) { @@ -235,12 +225,6 @@ public class ResultService { } } - public Uni getCategoryPublic(String uuid, long poule) { - return matchRepository.list("category.compet.uuid = ?1 AND category.id = ?2", uuid, poule) - .call(list -> Mutiny.fetch(list.get(0).getCategory().getTree())) - .map(list -> getData(list, null)); - } - private void getTree(List treeModels, MembreModel membreModel, ResultCategoryData out) { ArrayList> trees = new ArrayList<>(); treeModels.stream().filter(t -> t.getLevel() != 0).forEach(treeModel -> { @@ -501,17 +485,11 @@ public class ResultService { ); } - public Uni getClubArray(String uuid, SecurityCtx securityCtx) { - return hasAccess(uuid, securityCtx).chain(cm_register -> - registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid, cm_register.getClub2()) - .chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid) - .map(matchModels -> - getClubArray2(cm_register.getClub2().getName(), - registers.stream().map(o -> (CombModel) o.getMembre()).toList(), - matchModels, registers, cm_register.getMembre())))); + public Uni getClubArray(String uuid, Long id, SecurityCtx securityCtx) { + return hasAccess(uuid, securityCtx).chain(cm_register -> getClubArray2(uuid, id, cm_register.getMembre())); } - public Uni getClubArrayPublic(String uuid, Long id) { + public Uni getClubArray2(String uuid, Long id, MembreModel membreModel) { if (id < 0) { String clubName = getClubTempId(id); if (clubName == null) { @@ -528,7 +506,7 @@ public class ResultService { "category.compet.uuid = ?1 AND (c1_guest IN ?2 OR c2_guest IN ?2)", uuid, guests) .map(matchModels -> getClubArray2(clubName, guests.stream().map(o -> (CombModel) o).toList(), - matchModels, new ArrayList<>(), null))); + matchModels, new ArrayList<>(), membreModel))); } else { return clubRepository.findById(id).chain(clubModel -> registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid, clubModel) @@ -536,7 +514,7 @@ public class ResultService { .map(matchModels -> getClubArray2(clubModel.getName(), registers.stream().map(o -> (CombModel) o.getMembre()).toList(), - matchModels, registers, null)))); + matchModels, registers, membreModel)))); } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java index cd9a543..2febbd1 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/ExternalResultEndpoints.java @@ -37,7 +37,7 @@ public class ExternalResultEndpoints { return Uni.createFrom().voidItem(); if (updateService.needUpdate(poule, rf)) { - return resultService.getCategoryPublic(id, poule); + return resultService.getCategory(id, poule); } else { return Uni.createFrom().voidItem(); } @@ -67,7 +67,6 @@ public class ExternalResultEndpoints { } - @GET @Path("/club/list") @Produces(MediaType.APPLICATION_JSON) @@ -81,6 +80,6 @@ public class ExternalResultEndpoints { public Uni getClubArray(@QueryParam("club") long club) { if (club == 0) return Uni.createFrom().item(""); - return resultService.getClubArrayPublic(id, club); + return resultService.getClubArray2(id, club, null); } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java index 4016887..e1449fb 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java @@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.domain.service.ResultService; import fr.titionfire.ffsaf.rest.data.ResultCategoryData; +import fr.titionfire.ffsaf.utils.ResultPrivacy; import fr.titionfire.ffsaf.utils.SecurityCtx; import io.quarkus.security.Authenticated; import io.smallrye.mutiny.Uni; @@ -10,6 +11,7 @@ import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; +import java.util.HashMap; import java.util.List; @Authenticated @@ -29,17 +31,41 @@ public class ResultEndpoints { } @GET - @Path("{uuid}") - public Uni> getCategory(@PathParam("uuid") String uuid) { - return resultService.getCategory(uuid, securityCtx); + @Path("{uuid}/category/list") + public Uni> getCategoryList(@PathParam("uuid") String uuid) { + return resultService.getCategoryList(uuid); } @GET - @Path("{uuid}/club") - public Uni getClub(@PathParam("uuid") String uuid) { - return resultService.getClubArray(uuid, securityCtx); + @Path("{uuid}/category/{id}") + public Uni getCategory(@PathParam("uuid") String uuid, @PathParam("id") long id) { + return resultService.getCategory(uuid, id, securityCtx); } + @GET + @Path("{uuid}/club/list") + public Uni> getClubList(@PathParam("uuid") String uuid) { + return resultService.getClubList(uuid); + } + + @GET + @Path("{uuid}/club/{id}") + public Uni getClub(@PathParam("uuid") String uuid, @PathParam("id") long id) { + return resultService.getClubArray(uuid, id, securityCtx); + } + + @GET + @Path("{uuid}/comb/list") + public Uni> getCombList(@PathParam("uuid") String uuid) { + return resultService.getCombList(uuid, ResultPrivacy.REGISTERED_ONLY); + } + + @GET + @Path("{uuid}/comb/{id}") + public Uni getCombList(@PathParam("uuid") String uuid, @PathParam("id") String id) { + return resultService.getCombArrayPublic(uuid, id, ResultPrivacy.REGISTERED_ONLY); + } + @GET @Path("{uuid}/comb") public Uni getComb(@PathParam("uuid") String uuid) { diff --git a/src/main/webapp/src/pages/result/ResultView.jsx b/src/main/webapp/src/pages/result/ResultView.jsx index 0dedb13..7f06393 100644 --- a/src/main/webapp/src/pages/result/ResultView.jsx +++ b/src/main/webapp/src/pages/result/ResultView.jsx @@ -3,7 +3,7 @@ import {useLoadingSwitcher} from "../../hooks/useLoading.jsx"; import {useFetch} from "../../hooks/useFetch.js"; import {AxiosError} from "../../components/AxiosError.jsx"; import {ThreeDots} from "react-loader-spinner"; -import {useEffect, useState} from "react"; +import React, {useEffect, useState} from "react"; import {DrawGraph} from "./DrawGraph.jsx"; import {TreeNode} from "../../utils/TreeUtils.js"; import {scoreToString} from "../../utils/CompetitionTools.js"; @@ -17,50 +17,45 @@ function CupImg() { export function ResultView() { const {uuid} = useParams() const navigate = useNavigate(); - const [resultShow, setResultShow] = useState(null) - - const setLoading = useLoadingSwitcher() - const {data, error} = useFetch(`/result/${uuid}`, setLoading, 1) + const [resultShow, setResultShow] = useState("cat") return <> - {data ? - : error - ? - : } + -
    +
    - {resultShow && resultShow.type !== undefined && - || resultShow && resultShow === "club" && - || resultShow && resultShow === "comb" && } + {resultShow && resultShow === "cat" && + || resultShow && resultShow === "club" && + || resultShow && resultShow === "comb" && + || resultShow && resultShow === "combs" && }
    } + // || resultShow && resultShow === "club_all" && -function MenuBar({data, resultShow, setResultShow}) { +function MenuBar({resultShow, setResultShow}) { return @@ -148,13 +143,51 @@ function BuildTree({treeData}) { return } -function PouleResult({data}) { - const [type, setType] = useState(data.type === 3 ? 1 : data.type) +function CategoryList({uuid}) { + const [catId, setCatId] = useState(null) + const setLoading = useLoadingSwitcher() + const {data, error} = useFetch(`/result/${uuid}/category/list`, setLoading, 1) useEffect(() => { - setType(data.type === 3 ? 1 : data.type) + if (data && Object.keys(data).length > 0) + setCatId(data[Object.keys(data).sort()[0]]) }, [data]); + return <> + {data ?
    +
    Catégorie
    + +
    + : error + ? + : } + {catId && } + +} + +function CategoryResult({uuid, catId}) { + const [type, setType] = useState(1) + + const setLoading = useLoadingSwitcher() + const {data, refresh, error} = useFetch(`/result/${uuid}/category/${catId}`, setLoading, 1) + + useEffect(() => { + refresh(`/result/${uuid}/category/${catId}`) + }, [catId]); + + useEffect(() => { + if (data) + setType(data.type === 3 ? 1 : data.type) + }, [data]); + + if (!data) { + return error + ? + : + } + return <> {data.type === 3 && <>
      @@ -184,9 +217,37 @@ function PouleResult({data}) { } -function ClubResult({uuid}) { +function ClubList({uuid}) { + const [clubId, setClubId] = useState(null) const setLoading = useLoadingSwitcher() - const {data, error} = useFetch(`/result/${uuid}/club`, setLoading, 1) + const {data, error} = useFetch(`/result/${uuid}/club/list`, setLoading, 1) + + useEffect(() => { + if (data && Object.keys(data).length > 0) + setClubId(data[Object.keys(data).sort()[0]]) + }, [data]); + + return <> + {data ?
      +
      Club
      + +
      + : error + ? + : } + {clubId && } + +} + +function ClubResult({uuid, clubId}) { + const setLoading = useLoadingSwitcher() + const {data, refresh, error} = useFetch(`/result/${uuid}/club/${clubId}`, setLoading, 1) + + useEffect(() => { + refresh(`/result/${uuid}/club/${clubId}`) + }, [clubId]); return <> {data ? <> @@ -242,25 +303,102 @@ function ClubResult({uuid}) { } -/*function ClubAllResult({uuid}) { - return
      +function CombList({uuid}) { + const [combId, setCombId] = useState(null) + const setLoading = useLoadingSwitcher() + const {data, error} = useFetch(`/result/${uuid}/comb/list`, setLoading, 1) -}*/ + useEffect(() => { + if (data && Object.keys(data).length > 0) + setCombId(data[Object.keys(data).sort()[0]]) + }, [data]); -function CombResult({uuid}) { + return <> + {data ?
      +
      Combattant
      + +
      + : error + ? + : } + {combId && } + +} + +function CombResult({uuid, combId}) { + const setLoading = useLoadingSwitcher() + const {data, refresh, error} = useFetch(`/result/${uuid}/comb/${combId}`, setLoading, 1) + + useEffect(() => { + refresh(`/result/${uuid}/comb/${combId}`) + }, [combId]); + + + if (!data) { + return error + ? + : + } + + return
      +

      Info :

      +
        +
      • Nom Prénom : {data.name}
      • +
      • Club : {data.club}
      • +
      • Catégorie : {data.cat}
      • +
      +

      Statistique :

      +
        +
      • Taux de victoire : {data.matchs.length === 0 ? "---" : (data.totalWin / data.matchs.length * 100).toFixed(0)}% ({data.totalWin} sur + ${data.matchs.length}) +
      • +
      • Points marqués : {data.pointMake}
      • +
      • Points reçus : {data.pointTake}
      • +
      • Ratio du score (point marqué / point reçu): {data.pointRatio.toFixed(3)}
      • +
      + +

      Liste des matchs:

      + + + + + + + + + + + + + + {data.matchs.map((match, idx) => + + + + + + )} + +
      CatégorieAdversaireScoresRatio
      {match.poule}{match.adv}{scoreToString(match.score)}{match.ratio.toFixed(3)}{match.win ? : ""}
      +
      +} + +function CombsResult({uuid}) { const setLoading = useLoadingSwitcher() const {data, error} = useFetch(`/result/${uuid}/comb`, setLoading, 1) return <> {data ? <> -

      Statistique :

      +

      Statistique :

        -
      • Nombre d'inscris : {data.nb_insc}
      • -
      • Nombre de match disputé : {data.tt_match}
      • -
      • Points marqués : {data.point}
      • +
      • Nombre d'inscris : {data.nb_insc}
      • +
      • Nombre de match disputé : {data.tt_match}
      • +
      • Points marqués : {data.point}
      -

      Liste des combattants :

      +

      Liste des combattants :

      From 075f01a205fb0274f2322e1dbe7328487fdce0de Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Fri, 2 Jan 2026 14:09:55 +0100 Subject: [PATCH 4/4] feat: add privacy setting in me page --- .../ffsaf/domain/service/MembreService.java | 19 +++++++- .../ffsaf/rest/MembreEndpoints.java | 16 +++++++ .../fr/titionfire/ffsaf/rest/data/MeData.java | 26 +++++----- .../ffsaf/rest/from/UserSettingForm.java | 15 ++++++ src/main/webapp/src/pages/MePage.jsx | 48 ++++++++++++++++++- 5 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 src/main/java/fr/titionfire/ffsaf/rest/from/UserSettingForm.java diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java index 66ffda8..fa9870b 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java @@ -15,6 +15,7 @@ import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.exception.DInternalError; import fr.titionfire.ffsaf.rest.from.FullMemberForm; +import fr.titionfire.ffsaf.rest.from.UserSettingForm; import fr.titionfire.ffsaf.utils.*; import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.PanacheQuery; @@ -467,7 +468,8 @@ public class MembreService { .call(membreModel -> licenceRepository.update("club_id = ?1 where membre = ?2 AND saison = ?3", (membreModel.getClub() == null) ? null : membreModel.getClub().getId(), membreModel, Utils.getSaison())) - .call(membreModel -> (membre.getPhoto_data() != null && membre.getPhoto_data().size() > 0) ? ls.logAUpdate("Photo", + .call(membreModel -> (membre.getPhoto_data() != null && membre.getPhoto_data() + .size() > 0) ? ls.logAUpdate("Photo", membreModel) : Uni.createFrom().nullItem()) .map(__ -> "OK"); } @@ -593,6 +595,20 @@ public class MembreService { .map(__ -> meData); } + public Uni updateSettings(String subject, UserSettingForm settingForm) { + return repository.find("userId = ?1", subject).firstResult() + .invoke(Unchecked.consumer(membreModel -> { + if (settingForm.getResultPrivacy() != null) { + ls.logChange("Confidentialité des résultats", membreModel.getResultPrivacy(), + settingForm.getResultPrivacy(), membreModel); + membreModel.setResultPrivacy(settingForm.getResultPrivacy()); + } + })) + .call(membreModel -> Panache.withTransaction(() -> repository.persist(membreModel))) + .call(membreModel -> ls.append()) + .replaceWithVoid(); + } + @Scheduled(cron = "0 0 1 1 9 ?") Uni everySeason() { return repository.list("birth_date IS NOT NULL") @@ -602,5 +618,4 @@ public class MembreService { }).toList()).andCollectFailures()) .map(__ -> null); } - } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java index c60cb9b..8cac523 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java @@ -6,6 +6,7 @@ import fr.titionfire.ffsaf.domain.service.PDFService; import fr.titionfire.ffsaf.rest.data.MeData; import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; +import fr.titionfire.ffsaf.rest.from.UserSettingForm; import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.Utils; import io.quarkus.security.Authenticated; @@ -113,6 +114,21 @@ public class MembreEndpoints { return pdfService.getLicencePdf(securityCtx.getSubject()); } + @PUT + @Path("me/setting") + @Authenticated + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.TEXT_PLAIN) + @Operation(summary = "Met à jour les paramètres du membre connecté", description = "Met à jour les paramètres du membre connecté") + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "Les paramètres ont été mis à jour"), + @APIResponse(responseCode = "403", description = "Accès refusé"), + @APIResponse(responseCode = "500", description = "Erreur interne du serveur") + }) + public Uni updateMeSettings(UserSettingForm settingForm) { + return membreService.updateSettings(securityCtx.getSubject(), settingForm); + } + @GET @Path("me/photo") @Authenticated diff --git a/src/main/java/fr/titionfire/ffsaf/rest/data/MeData.java b/src/main/java/fr/titionfire/ffsaf/rest/data/MeData.java index 3cf071f..ece32cc 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/data/MeData.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/data/MeData.java @@ -1,6 +1,7 @@ package fr.titionfire.ffsaf.rest.data; import fr.titionfire.ffsaf.data.model.MembreModel; +import fr.titionfire.ffsaf.utils.ResultPrivacy; import io.quarkus.runtime.annotations.RegisterForReflection; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,30 +16,32 @@ import java.util.List; @NoArgsConstructor @RegisterForReflection public class MeData { - @Schema(description = "L'identifiant du membre.", example = "1") + @Schema(description = "L'identifiant du membre.", examples = "1") private long id; - @Schema(description = "Le nom du membre.", example = "Dupont") + @Schema(description = "Le nom du membre.", examples = "Dupont") private String lname = ""; - @Schema(description = "Le prénom du membre.", example = "Jean") + @Schema(description = "Le prénom du membre.", examples = "Jean") private String fname = ""; - @Schema(description = "La catégorie du membre.", example = "SENIOR") + @Schema(description = "La catégorie du membre.", examples = "SENIOR") private String categorie; - @Schema(description = "Le nom du club du membre.", example = "Association sportive") + @Schema(description = "Le nom du club du membre.", examples = "Association sportive") private String club; - @Schema(description = "Le genre du membre.", example = "Homme") + @Schema(description = "Le genre du membre.", examples = "Homme") private String genre; - @Schema(description = "Le numéro de licence du membre.", example = "12345") + @Schema(description = "Le numéro de licence du membre.", examples = "12345") private int licence; - @Schema(description = "Le pays du membre.", example = "FR") + @Schema(description = "Le pays du membre.", examples = "FR") private String country; @Schema(description = "La date de naissance du membre.") private Date birth_date; - @Schema(description = "L'adresse e-mail du membre.", example = "jean.dupont@example.com") + @Schema(description = "L'adresse e-mail du membre.", examples = "jean.dupont@examples.com") private String email; - @Schema(description = "Le rôle du membre dans l'association.", example = "MEMBRE") + @Schema(description = "Le rôle du membre dans l'association.", examples = "MEMBRE") private String role; - @Schema(description = "Le grade d'arbitrage du membre.", example = "N/A") + @Schema(description = "Le grade d'arbitrage du membre.", examples = "N/A") private String grade_arbitrage; + @Schema(description = "La confidentialité des résultats", examples = "PUBLIC") + private ResultPrivacy resultPrivacy; @Schema(description = "La liste des licences du membre.") private List licences; @@ -55,5 +58,6 @@ public class MeData { this.email = membreModel.getEmail(); this.role = membreModel.getRole().str; this.grade_arbitrage = membreModel.getGrade_arbitrage().str; + this.resultPrivacy = membreModel.getResultPrivacy(); } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/from/UserSettingForm.java b/src/main/java/fr/titionfire/ffsaf/rest/from/UserSettingForm.java new file mode 100644 index 0000000..566587a --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/rest/from/UserSettingForm.java @@ -0,0 +1,15 @@ +package fr.titionfire.ffsaf.rest.from; + +import fr.titionfire.ffsaf.utils.ResultPrivacy; +import jakarta.ws.rs.FormParam; +import lombok.Getter; +import lombok.ToString; +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +@ToString +@Getter +public class UserSettingForm { + @FormParam("resultPrivacy") + @Schema(description = "La confidentialité des résultats", examples = "PUBLIC", defaultValue = "PUBLIC", required = true) + private ResultPrivacy resultPrivacy; +} diff --git a/src/main/webapp/src/pages/MePage.jsx b/src/main/webapp/src/pages/MePage.jsx index 27e74b3..aac61d3 100644 --- a/src/main/webapp/src/pages/MePage.jsx +++ b/src/main/webapp/src/pages/MePage.jsx @@ -12,6 +12,10 @@ import { faUserGroup, faVenus } from "@fortawesome/free-solid-svg-icons"; +import {CheckField} from "../components/MemberCustomFiels.jsx"; +import {toast} from "react-toastify"; +import {apiAxios} from "../utils/Tools.js"; +import {useEffect, useState} from "react"; const vite_url = import.meta.env.VITE_URL; @@ -30,6 +34,7 @@ export function MePage() {
      +
      @@ -96,8 +101,47 @@ function SelectCard() {
      ; } +function SettingsCard({data}) { + const [privacy, setPrivacy] = useState("PUBLIC"); -export function InformationForm({data}) { + useEffect(() => { + if (data?.resultPrivacy) { + setPrivacy(data.resultPrivacy); + } + }, [data]); + + const handleChange = (e) => { + const formData = new FormData(); + formData.append("resultPrivacy", e.target.value); + toast.promise(apiAxios.put(`/member/me/setting`, formData), + { + pending: 'Mise à jours des paramètres en cours...', + success: 'Paramètres mis à jours avec succès 🎉', + error: 'Échec de la mise à jours des paramètres 😕' + }) + .then(() => { + setPrivacy(String(formData.get("resultPrivacy"))); + }); + } + + return
      +
      Paramètres du compte
      +
      +
      + + +
      +
      +
      ; +} + +function InformationForm({data}) { const style = {marginRight: '0.7em'} return
      @@ -127,4 +171,4 @@ export function InformationForm({data}) {
      ; -} \ No newline at end of file +}