Compare commits
41 Commits
dev-comp
...
dc5ab9c3c4
| Author | SHA1 | Date | |
|---|---|---|---|
| dc5ab9c3c4 | |||
| 7e1356b621 | |||
| b689521e56 | |||
| 095a5fcede | |||
| 254fd7d73f | |||
| 12a75d003c | |||
| 7f957b98f2 | |||
| 50b49c40e3 | |||
| 47d3921e05 | |||
| 7c4addd525 | |||
| fefc5d651b | |||
| 53509820c6 | |||
| f46e268d39 | |||
| 6e7eec0587 | |||
| 8c83668364 | |||
| 771c06ccd8 | |||
| b479b992cf | |||
| be2f01c070 | |||
| 9ab50238b9 | |||
| cf5d93630f | |||
| 7410569ced | |||
| 8e2d68ebd5 | |||
| d02fd63834 | |||
| b143cc759f | |||
| cc5534ef00 | |||
| 26f56006f6 | |||
| ed1f30f2b6 | |||
| 6cec8ff31d | |||
| d95c173fa8 | |||
| 8a0e4423f2 | |||
| b956236934 | |||
| 7767c98304 | |||
| 7e380ccb69 | |||
| 94d1148eb1 | |||
| 79dbbdaaec | |||
| dec98f9508 | |||
| b89ed62795 | |||
| 5e48bc4623 | |||
| c6659f8d85 | |||
| e86fe42b3d | |||
| ef528aa524 |
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||||||
import fr.titionfire.ffsaf.data.model.AffiliationModel;
|
import fr.titionfire.ffsaf.data.model.AffiliationModel;
|
||||||
import fr.titionfire.ffsaf.data.model.ClubModel;
|
import fr.titionfire.ffsaf.data.model.ClubModel;
|
||||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||||
|
import fr.titionfire.ffsaf.data.repository.AffiliationRepository;
|
||||||
import fr.titionfire.ffsaf.data.repository.ClubRepository;
|
import fr.titionfire.ffsaf.data.repository.ClubRepository;
|
||||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||||
import fr.titionfire.ffsaf.net2.ServerCustom;
|
import fr.titionfire.ffsaf.net2.ServerCustom;
|
||||||
@@ -44,6 +45,9 @@ public class ClubService {
|
|||||||
@Inject
|
@Inject
|
||||||
ClubRepository repository;
|
ClubRepository repository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AffiliationRepository affiliationRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ServerCustom serverCustom;
|
ServerCustom serverCustom;
|
||||||
|
|
||||||
@@ -234,7 +238,8 @@ public class ClubService {
|
|||||||
}
|
}
|
||||||
return Panache.withTransaction(() -> repository.persist(m)).call(() -> ls.append());
|
return Panache.withTransaction(() -> repository.persist(m)).call(() -> ls.append());
|
||||||
}))
|
}))
|
||||||
.call(clubModel -> nameChange.get() ? keycloakService.updateGroupFromClub(clubModel) // update group in keycloak
|
.call(clubModel -> nameChange.get() ? keycloakService.updateGroupFromClub(
|
||||||
|
clubModel) // update group in keycloak
|
||||||
: Uni.createFrom().nullItem())
|
: Uni.createFrom().nullItem())
|
||||||
.invoke(membreModel -> SReqClub.sendIfNeed(serverCustom.clients,
|
.invoke(membreModel -> SReqClub.sendIfNeed(serverCustom.clients,
|
||||||
SimpleClubModel.fromModel(membreModel)))
|
SimpleClubModel.fromModel(membreModel)))
|
||||||
@@ -323,9 +328,11 @@ public class ClubService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uni<List<ClubMapData>> getMapData() {
|
public Uni<List<ClubMapData>> getMapData() {
|
||||||
return repository.list("international", false).toMulti().flatMap(list -> Multi.createFrom().iterable(list))
|
return affiliationRepository.list("saison >= ?1 AND club.international = ?2", Utils.getSaison() - 1, false)
|
||||||
.call(clubModel -> Mutiny.fetch(clubModel.getContact()))
|
.toMulti().flatMap(list -> Multi.createFrom().iterable(list))
|
||||||
.map(clubModel -> {
|
.call(affiliationModel -> Mutiny.fetch(affiliationModel.getClub().getContact()))
|
||||||
|
.map(affiliationModel -> {
|
||||||
|
ClubModel clubModel = affiliationModel.getClub();
|
||||||
ClubMapData data = new ClubMapData();
|
ClubMapData data = new ClubMapData();
|
||||||
|
|
||||||
data.setName(clubModel.getName());
|
data.setName(clubModel.getName());
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ public class CompetitionService {
|
|||||||
public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data,
|
public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data,
|
||||||
String source) {
|
String source) {
|
||||||
if ("admin".equals(source))
|
if ("admin".equals(source))
|
||||||
if (data.getLicence() != -1) { // not a guest
|
if (data.getLicence() == null || data.getLicence() != -1) { // not a guest
|
||||||
return permService.hasEditPerm(securityCtx, id)
|
return permService.hasEditPerm(securityCtx, id)
|
||||||
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
||||||
.call(combModel -> Mutiny.fetch(combModel.getLicences()))
|
.call(combModel -> Mutiny.fetch(combModel.getLicences()))
|
||||||
|
|||||||
@@ -270,13 +270,99 @@ public class KeycloakService {
|
|||||||
.invoke(user -> membreModel.setUserId(user.getId()))
|
.invoke(user -> membreModel.setUserId(user.getId()))
|
||||||
.call(user -> updateRole(user.getId(), List.of("safca_user"), List.of()))
|
.call(user -> updateRole(user.getId(), List.of("safca_user"), List.of()))
|
||||||
.call(user -> enabled_email ? reactiveMailer.send(
|
.call(user -> enabled_email ? reactiveMailer.send(
|
||||||
Mail.withText(user.getEmail(),
|
Mail.withHtml(user.getEmail(), "FFSAF - Creation de votre compte sur l'intranet", String.format(
|
||||||
"FFSAF - Creation de votre compte sur l'intranet",
|
"""
|
||||||
String.format(
|
<!DOCTYPE html>
|
||||||
|
<html data-lt-installed="true">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Création de votre compte intranet FFSAF</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background-color: #003366;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #003366;
|
||||||
|
color: white !important;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #003366;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body data-gramm="false" data-lt-tmp-id="lt-957854">
|
||||||
|
<div class="header">
|
||||||
|
<div><img src="https://intra.ffsaf.fr/Logo-FFSAF-2023.png" alt="ffsaf" height="128">
|
||||||
|
<h1>Fédération France Soft Armored Fighting</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>Bonjour,</p>
|
||||||
|
<p>Suite à votre première inscription <span class="highlight">%s</span> à la <strong>Fédération France Soft Armored Fighting (FFSAF)</strong>, votre compte intranet a été créé.</p>
|
||||||
|
<p>Ce compte vous permettra de :</p>
|
||||||
|
<ul>
|
||||||
|
<li>Consulter vos informations personnelles,</li>
|
||||||
|
<li>Vous inscrire aux compétitions (bientôt disponible),</li>
|
||||||
|
<li>Consulter les résultats des compétitions.</li>
|
||||||
|
</ul>
|
||||||
|
<p>L’intranet est accessible à l’adresse suivante :</p>
|
||||||
|
<p style="text-align: center;"><a href="https://intra.ffsaf.fr" class="button">Accéder à l'intranet</a></p>
|
||||||
|
<p>Votre nom d’utilisateur est : <span class="highlight">%s</span></p>
|
||||||
|
<p>Pour définir votre mot de passe, rendez-vous sur l’intranet : <strong>Connexion > Mot de passe oublié ?</strong></p>
|
||||||
|
<p>Si vous n’avez pas demandé cette inscription, veuillez contacter le support à l’adresse : <a href="mailto:support@ffsaf.fr">support@ffsaf.fr</a>.</p>
|
||||||
|
<p class="footer">(Pas de panique, nous ne vous enverrons pas de message autre que ceux concernant votre compte.)</p>
|
||||||
|
<p>Cordialement,<br>L’équipe de la FFSAF</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
""",
|
||||||
|
membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub()
|
||||||
|
.getName() + ") " : "", user.getUsername())
|
||||||
|
)
|
||||||
|
.setText(String.format(
|
||||||
"""
|
"""
|
||||||
Bonjour,
|
Bonjour,
|
||||||
|
|
||||||
Suite à votre première inscription %sà la Fédération Française de Soft Armored Fighting (FFSAF), votre compte intranet a été créé.
|
Suite à votre première inscription %sà la Fédération France Soft Armored Fighting (FFSAF), votre compte intranet a été créé.
|
||||||
Ce compte vous permettra de consulter vos informations et, dans un futur proche, de vous inscrire aux compétitions ainsi que d'en consulter les résultats.
|
Ce compte vous permettra de consulter vos informations et, dans un futur proche, de vous inscrire aux compétitions ainsi que d'en consulter les résultats.
|
||||||
|
|
||||||
L'intranet est accessible à l'adresse suivante : https://intra.ffsaf.fr
|
L'intranet est accessible à l'adresse suivante : https://intra.ffsaf.fr
|
||||||
@@ -291,8 +377,8 @@ public class KeycloakService {
|
|||||||
L'équipe de la FFSAF
|
L'équipe de la FFSAF
|
||||||
""",
|
""",
|
||||||
membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub()
|
membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub()
|
||||||
.getName() + ") " : "", user.getUsername())
|
.getName() + ") " : "", user.getUsername()))
|
||||||
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
|
.setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
|
||||||
) : Uni.createFrom().nullItem())
|
) : Uni.createFrom().nullItem())
|
||||||
.call(user -> membreService.setUserId(membreModel.getId(), user.getId()))
|
.call(user -> membreService.setUserId(membreModel.getId(), user.getId()))
|
||||||
.call(user -> setClubGroupMembre(membreModel, membreModel.getClub()));
|
.call(user -> setClubGroupMembre(membreModel, membreModel.getClub()));
|
||||||
|
|||||||
@@ -84,6 +84,26 @@ public class LicenceService {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Uni<?> validePaymentLicences(List<Long> ids) {
|
||||||
|
Uni<String> uni = Uni.createFrom().nullItem();
|
||||||
|
|
||||||
|
for (Long id : ids) {
|
||||||
|
uni = uni.chain(__ -> repository.find("membre.id = ?1 AND saison = ?2", id, Utils.getSaison()).firstResult()
|
||||||
|
.chain(model -> {
|
||||||
|
if (!model.isPay())
|
||||||
|
ls.logUpdate("payment (admin) de la licence", model);
|
||||||
|
return validatePayLicences(model);
|
||||||
|
}))
|
||||||
|
.map(__ -> "OK");
|
||||||
|
}
|
||||||
|
return uni.call(__ -> ls.append());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Uni<LicenceModel> validatePayLicences(LicenceModel model) {
|
||||||
|
model.setPay(true);
|
||||||
|
return Panache.withTransaction(() -> repository.persist(model));
|
||||||
|
}
|
||||||
|
|
||||||
public Uni<LicenceModel> setLicence(long id, LicenceForm form) {
|
public Uni<LicenceModel> setLicence(long id, LicenceForm form) {
|
||||||
if (form.getId() == -1) {
|
if (form.getId() == -1) {
|
||||||
return combRepository.findById(id).chain(membreModel -> {
|
return combRepository.findById(id).chain(membreModel -> {
|
||||||
@@ -121,7 +141,7 @@ public class LicenceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Function<MembreModel, Uni<?>> genLicenceNumberAndAccountIfNeed() {
|
private Function<MembreModel, Uni<?>> genLicenceNumberAndAccountIfNeed() {
|
||||||
return membreModel -> ((membreModel.getLicence() <= 0) ?
|
return membreModel -> ((membreModel.getLicence() == null || membreModel.getLicence() <= 0) ?
|
||||||
sequenceRepository.getNextValueInTransaction(SequenceType.Licence)
|
sequenceRepository.getNextValueInTransaction(SequenceType.Licence)
|
||||||
.invoke(i -> membreModel.setLicence(Math.toIntExact(i)))
|
.invoke(i -> membreModel.setLicence(Math.toIntExact(i)))
|
||||||
.chain(() -> combRepository.persist(membreModel))
|
.chain(() -> combRepository.persist(membreModel))
|
||||||
@@ -157,7 +177,7 @@ public class LicenceService {
|
|||||||
"Impossible de supprimer une licence pour laquelle un paiement est en cours");
|
"Impossible de supprimer une licence pour laquelle un paiement est en cours");
|
||||||
})))
|
})))
|
||||||
.call(model -> ls.logADelete(model))
|
.call(model -> ls.logADelete(model))
|
||||||
.chain(model -> repository.delete(model));
|
.chain(model -> Panache.withTransaction(() -> repository.delete(model)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<LicenceModel> askLicence(long id, LicenceForm form, Consumer<MembreModel> checkPerm) {
|
public Uni<LicenceModel> askLicence(long id, LicenceForm form, Consumer<MembreModel> checkPerm) {
|
||||||
|
|||||||
@@ -125,8 +125,21 @@ public class MembreService {
|
|||||||
return sort;
|
return sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<PageResult<SimpleMembre>> searchAdmin(int limit, int page, String search, String club,
|
public Uni<PageResult<SimpleMembre>> search(int limit, int page, String search, int licenceRequest, int payState,
|
||||||
int licenceRequest, int payState, String order, String categorie) {
|
String order, String categorie, Boolean archive, String subject) {
|
||||||
|
return repository.find("userId = ?1", subject).firstResult()
|
||||||
|
.invoke(Unchecked.consumer(membreModel -> {
|
||||||
|
if (membreModel == null || membreModel.getClub() == null)
|
||||||
|
throw new DForbiddenException();
|
||||||
|
}))
|
||||||
|
.chain(membreModel ->
|
||||||
|
searchAdmin(limit, page, search, membreModel.getClub(), licenceRequest, payState, order,
|
||||||
|
categorie, archive));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uni<PageResult<SimpleMembre>> searchAdmin(int limit, int page, String search, Object club,
|
||||||
|
int licenceRequest, int payState, String order, String categorie,
|
||||||
|
Boolean archive) {
|
||||||
if (search == null)
|
if (search == null)
|
||||||
search = "";
|
search = "";
|
||||||
search = "%" + search.replaceAll(" ", "% %") + "%";
|
search = "%" + search.replaceAll(" ", "% %") + "%";
|
||||||
@@ -137,77 +150,47 @@ public class MembreService {
|
|||||||
else
|
else
|
||||||
categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal();
|
categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal();
|
||||||
|
|
||||||
String finalSearch = search;
|
String archiveFilter;
|
||||||
Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState);
|
if (archive == null || archive)
|
||||||
|
archiveFilter = "True";
|
||||||
|
else
|
||||||
|
archiveFilter = String.format(
|
||||||
|
"EXISTS (SELECT 1 FROM LicenceModel l WHERE l.membre.id = m.id AND l.saison >= %s)",
|
||||||
|
Utils.getSaison() - 1);
|
||||||
|
|
||||||
|
String clubFilter = "?3 = ?3";
|
||||||
|
if (club != null) {
|
||||||
|
if (club instanceof String club_) {
|
||||||
|
if (!club_.isBlank()) {
|
||||||
|
if (club_.equals("null"))
|
||||||
|
clubFilter = "club IS NULL AND ?3 = ?3";
|
||||||
|
else
|
||||||
|
clubFilter = "LOWER(club.name) LIKE LOWER(?3)";
|
||||||
|
}
|
||||||
|
} else if (club instanceof ClubModel)
|
||||||
|
clubFilter = "club = ?3";
|
||||||
|
}
|
||||||
|
|
||||||
|
String queryStr = String.format(
|
||||||
|
"SELECT m FROM MembreModel m WHERE id %s ?2 AND %s AND (%s) AND %s AND %s",
|
||||||
|
(licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN", clubFilter, FIND_NAME_REQUEST,
|
||||||
|
categorieFilter,
|
||||||
|
archiveFilter);
|
||||||
|
|
||||||
Sort sort = getSort(order);
|
Sort sort = getSort(order);
|
||||||
if (sort == null)
|
if (sort == null)
|
||||||
return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie"));
|
return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie"));
|
||||||
|
|
||||||
return baseUni
|
String finalSearch = search;
|
||||||
|
return getLicenceListe(licenceRequest, payState)
|
||||||
.map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList())
|
.map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList())
|
||||||
.chain(ids -> {
|
.chain(ids -> {
|
||||||
PanacheQuery<MembreModel> query;
|
PanacheQuery<MembreModel> query;
|
||||||
|
query = repository.find(queryStr, sort, finalSearch, ids, club).page(Page.ofSize(limit));
|
||||||
String idf = ((licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN");
|
|
||||||
|
|
||||||
if (club == null || club.isBlank()) {
|
|
||||||
query = repository.find(
|
|
||||||
"id " + idf + " ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
|
||||||
sort, finalSearch, ids)
|
|
||||||
.page(Page.ofSize(limit));
|
|
||||||
} else {
|
|
||||||
if (club.equals("null")) {
|
|
||||||
query = repository.find(
|
|
||||||
"id " + idf + " ?2 AND club IS NULL AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
|
||||||
sort, finalSearch, ids).page(Page.ofSize(limit));
|
|
||||||
} else {
|
|
||||||
query = repository.find(
|
|
||||||
"id " + idf + " ?3 AND LOWER(club.name) LIKE LOWER(?2) AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
|
||||||
sort, finalSearch, club, ids)
|
|
||||||
.page(Page.ofSize(limit));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getPageResult(query, limit, page);
|
return getPageResult(query, limit, page);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<PageResult<SimpleMembre>> search(int limit, int page, String search, int licenceRequest, int payState,
|
|
||||||
String order, String categorie, String subject) {
|
|
||||||
if (search == null)
|
|
||||||
search = "";
|
|
||||||
search = "%" + search.replaceAll(" ", "% %") + "%";
|
|
||||||
|
|
||||||
String finalSearch = search;
|
|
||||||
|
|
||||||
Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState);
|
|
||||||
|
|
||||||
String categorieFilter;
|
|
||||||
if (categorie == null || categorie.isBlank())
|
|
||||||
categorieFilter = " True";
|
|
||||||
else
|
|
||||||
categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal();
|
|
||||||
|
|
||||||
Sort sort = getSort(order);
|
|
||||||
if (sort == null)
|
|
||||||
return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie"));
|
|
||||||
|
|
||||||
return baseUni
|
|
||||||
.map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList())
|
|
||||||
.chain(ids -> {
|
|
||||||
String idf = ((licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN");
|
|
||||||
|
|
||||||
return repository.find("userId = ?1", subject).firstResult()
|
|
||||||
.chain(membreModel -> {
|
|
||||||
PanacheQuery<MembreModel> query = repository.find(
|
|
||||||
"id " + idf + " ?3 AND club = ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
|
||||||
sort, finalSearch, membreModel.getClub(), ids)
|
|
||||||
.page(Page.ofSize(limit));
|
|
||||||
return getPageResult(query, limit, page);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Uni<PageResult<SimpleMembre>> getPageResult(PanacheQuery<MembreModel> query, int limit, int page) {
|
private Uni<PageResult<SimpleMembre>> getPageResult(PanacheQuery<MembreModel> query, int limit, int page) {
|
||||||
return Uni.createFrom().item(new PageResult<SimpleMembre>())
|
return Uni.createFrom().item(new PageResult<SimpleMembre>())
|
||||||
.invoke(result -> result.setPage(page))
|
.invoke(result -> result.setPage(page))
|
||||||
@@ -287,14 +270,14 @@ public class MembreService {
|
|||||||
if (model.getEmail() != null && !model.getEmail().isBlank()) {
|
if (model.getEmail() != null && !model.getEmail().isBlank()) {
|
||||||
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
|
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
|
||||||
LOGGER.info("Similar membres found: " + model);
|
LOGGER.info("Similar membres found: " + model);
|
||||||
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
|
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utilisé");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringSimilarity.similarity(model.getLname().toUpperCase(),
|
if (StringSimilarity.similarity(model.getLname().toUpperCase(),
|
||||||
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
|
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
|
||||||
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
|
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
|
||||||
LOGGER.info("Similar membres found: " + model);
|
LOGGER.info("Similar membres found: " + model);
|
||||||
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
|
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utilisé");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +363,7 @@ public class MembreService {
|
|||||||
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0 && !membre.getEmail().isBlank())
|
if (c > 0 && !membre.getEmail().isBlank())
|
||||||
throw new DBadRequestException("Email déjà utiliser");
|
throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.chain(membreModel -> clubRepository.findById(membre.getClub())
|
.chain(membreModel -> clubRepository.findById(membre.getClub())
|
||||||
.map(club -> new Pair<>(membreModel, club)))
|
.map(club -> new Pair<>(membreModel, club)))
|
||||||
@@ -402,7 +385,7 @@ public class MembreService {
|
|||||||
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0 && !membre.getEmail().isBlank())
|
if (c > 0 && !membre.getEmail().isBlank())
|
||||||
throw new DBadRequestException("Email déjà utiliser");
|
throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.invoke(Unchecked.consumer(membreModel -> {
|
.invoke(Unchecked.consumer(membreModel -> {
|
||||||
if (!securityCtx.isInClubGroup(membreModel.getClub().getId()))
|
if (!securityCtx.isInClubGroup(membreModel.getClub().getId()))
|
||||||
@@ -492,7 +475,7 @@ public class MembreService {
|
|||||||
return clubRepository.findById(input.getClub())
|
return clubRepository.findById(input.getClub())
|
||||||
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0) throw new DBadRequestException("Email déjà utiliser");
|
if (c > 0) throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.chain(clubModel -> {
|
.chain(clubModel -> {
|
||||||
MembreModel model = getMembreModel(input, clubModel);
|
MembreModel model = getMembreModel(input, clubModel);
|
||||||
@@ -508,7 +491,7 @@ public class MembreService {
|
|||||||
return repository.find("userId = ?1", subject).firstResult()
|
return repository.find("userId = ?1", subject).firstResult()
|
||||||
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0) throw new DBadRequestException("Email déjà utiliser");
|
if (c > 0) throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.call(membreModel ->
|
.call(membreModel ->
|
||||||
repository.count(
|
repository.count(
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ public class LicenceEndpoints {
|
|||||||
@RolesAllowed("federation_admin")
|
@RolesAllowed("federation_admin")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Operation(summary = "Validation licence", description = "Valide en masse les licence de l'année en cours (pour les administrateurs)")
|
@Operation(summary = "Validation licence", description = "Valide en masse les licences de l'année en cours (pour les administrateurs)")
|
||||||
@APIResponses(value = {
|
@APIResponses(value = {
|
||||||
@APIResponse(responseCode = "200", description = "Les licences ont été mise à jour avec succès"),
|
@APIResponse(responseCode = "200", description = "Les licences ont été mise à jour avec succès"),
|
||||||
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
||||||
@@ -128,6 +128,21 @@ public class LicenceEndpoints {
|
|||||||
return licenceService.valideLicences(ids);
|
return licenceService.valideLicences(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("validate-pay")
|
||||||
|
@RolesAllowed("federation_admin")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Operation(summary = "Validation du payment des licences", description = "Valide en masse le payment des licences de l'année en cours (pour les administrateurs)")
|
||||||
|
@APIResponses(value = {
|
||||||
|
@APIResponse(responseCode = "200", description = "Les licences ont été mise à jour avec succès"),
|
||||||
|
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
||||||
|
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||||
|
})
|
||||||
|
public Uni<?> validePaymentLicences(@Parameter(description = "Id des membres a valider") List<Long> ids) {
|
||||||
|
return licenceService.validePaymentLicences(ids);
|
||||||
|
}
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@RolesAllowed("federation_admin")
|
@RolesAllowed("federation_admin")
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public class MembreAdminEndpoints {
|
|||||||
@Parameter(description = "Text à rechercher") @QueryParam("search") String search,
|
@Parameter(description = "Text à rechercher") @QueryParam("search") String search,
|
||||||
@Parameter(description = "Club à filter") @QueryParam("club") String club,
|
@Parameter(description = "Club à filter") @QueryParam("club") String club,
|
||||||
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie,
|
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie,
|
||||||
|
@Parameter(description = "Inclure les archive") @QueryParam("archive") Boolean archive,
|
||||||
@Parameter(description = "État de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
|
@Parameter(description = "État de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
|
||||||
@Parameter(description = "État du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment,
|
@Parameter(description = "État du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment,
|
||||||
@Parameter(description = "Ordre") @QueryParam("order") String order) {
|
@Parameter(description = "Ordre") @QueryParam("order") String order) {
|
||||||
@@ -66,7 +67,8 @@ public class MembreAdminEndpoints {
|
|||||||
limit = 50;
|
limit = 50;
|
||||||
if (page == null || page < 1)
|
if (page == null || page < 1)
|
||||||
page = 1;
|
page = 1;
|
||||||
return membreService.searchAdmin(limit, page - 1, search, club, licenceRequest, payment, order, categorie);
|
return membreService.searchAdmin(limit, page - 1, search, club, licenceRequest, payment, order,
|
||||||
|
categorie, archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public class MembreClubEndpoints {
|
|||||||
@Parameter(description = "Page à consulter") @QueryParam("page") Integer page,
|
@Parameter(description = "Page à consulter") @QueryParam("page") Integer page,
|
||||||
@Parameter(description = "Text à rechercher") @QueryParam("search") String search,
|
@Parameter(description = "Text à rechercher") @QueryParam("search") String search,
|
||||||
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie,
|
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie,
|
||||||
|
@Parameter(description = "Inclure les archive") @QueryParam("archive") Boolean archive,
|
||||||
@Parameter(description = "Etat de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
|
@Parameter(description = "Etat de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
|
||||||
@Parameter(description = "Etat du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment,
|
@Parameter(description = "Etat du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment,
|
||||||
@Parameter(description = "Ordre") @QueryParam("order") String order) {
|
@Parameter(description = "Ordre") @QueryParam("order") String order) {
|
||||||
@@ -58,7 +59,7 @@ public class MembreClubEndpoints {
|
|||||||
limit = 50;
|
limit = 50;
|
||||||
if (page == null || page < 1)
|
if (page == null || page < 1)
|
||||||
page = 1;
|
page = 1;
|
||||||
return membreService.search(limit, page - 1, search, licenceRequest, payment, order, categorie, securityCtx.getSubject());
|
return membreService.search(limit, page - 1, search, licenceRequest, payment, order, categorie, archive, securityCtx.getSubject());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
|||||||
BIN
src/main/webapp/public/Logo-FFSAF-2023.png
Normal file
BIN
src/main/webapp/public/Logo-FFSAF-2023.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 155 KiB |
@@ -14,6 +14,7 @@ import {ClubRoot, getClubChildren} from "./pages/club/ClubRoot.jsx";
|
|||||||
import {DemandeAff, DemandeAffOk} from "./pages/DemandeAff.jsx";
|
import {DemandeAff, DemandeAffOk} from "./pages/DemandeAff.jsx";
|
||||||
import {MePage} from "./pages/MePage.jsx";
|
import {MePage} from "./pages/MePage.jsx";
|
||||||
import {CompetitionRoot, getCompetitionChildren} from "./pages/competition/CompetitionRoot.jsx";
|
import {CompetitionRoot, getCompetitionChildren} from "./pages/competition/CompetitionRoot.jsx";
|
||||||
|
import {FallingLines} from "react-loader-spinner";
|
||||||
import {getResultChildren, ResultRoot} from "./pages/result/ResultRoot.jsx";
|
import {getResultChildren, ResultRoot} from "./pages/result/ResultRoot.jsx";
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
|
|||||||
@@ -119,13 +119,13 @@ export function CheckField({name, text, value, row = false}) {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Checkbox = ({label, value, onChange}) => {
|
export const Checkbox = ({label, value, onChange, name = "checkbox1"}) => {
|
||||||
const handleChange = () => {
|
const handleChange = () => {
|
||||||
onChange(!value);
|
onChange(!value);
|
||||||
};
|
};
|
||||||
|
|
||||||
return <div className="form-check">
|
return <div className="form-check">
|
||||||
<input className="form-check-input" type="checkbox" id="checkbox1" checked={value} onChange={handleChange}/>
|
<input className="form-check-input" type="checkbox" id={name} checked={value} onChange={handleChange}/>
|
||||||
<label className="form-check-label" htmlFor="checkbox1">{label}</label>
|
<label className="form-check-label" htmlFor={name}>{label}</label>
|
||||||
</div>
|
</div>
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export function MemberList({source}) {
|
|||||||
payment: 2,
|
payment: 2,
|
||||||
order: "",
|
order: "",
|
||||||
categorie: "",
|
categorie: "",
|
||||||
|
archived: false,
|
||||||
...JSON.parse(decodeURI(hash.substring(1)) || "{}"),
|
...JSON.parse(decodeURI(hash.substring(1)) || "{}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,10 +44,10 @@ export function MemberList({source}) {
|
|||||||
data,
|
data,
|
||||||
error,
|
error,
|
||||||
refresh
|
refresh
|
||||||
} = useFetch(`/member/find/${source}?page=${filter.page}&search=${filter.search}&club=${filter.club}&licenceRequest=${filter.licenceRequest}&payment=${filter.payment}&order=${filter.order}&categorie=${filter.categorie}`, setLoading, 1)
|
} = useFetch(`/member/find/${source}?page=${filter.page}&search=${filter.search}&club=${filter.club}&licenceRequest=${filter.licenceRequest}&payment=${filter.payment}&order=${filter.order}&categorie=${filter.categorie}&archive=${filter.archived}`, setLoading, 1)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tmp = `/member/find/${source}?page=${filter.page}&search=${filter.search}&club=${filter.club}&licenceRequest=${filter.licenceRequest}&payment=${filter.payment}&order=${filter.order}&categorie=${filter.categorie}`;
|
const tmp = `/member/find/${source}?page=${filter.page}&search=${filter.search}&club=${filter.club}&licenceRequest=${filter.licenceRequest}&payment=${filter.payment}&order=${filter.order}&categorie=${filter.categorie}&archive=${filter.archived}`;
|
||||||
if (tmp === lastRefresh)
|
if (tmp === lastRefresh)
|
||||||
return;
|
return;
|
||||||
lastRefresh = tmp
|
lastRefresh = tmp
|
||||||
@@ -137,6 +138,8 @@ export function MemberList({source}) {
|
|||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<FiltreBar showLicenceState={showLicenceState}
|
<FiltreBar showLicenceState={showLicenceState}
|
||||||
setShowLicenceState={setShowLicenceState}
|
setShowLicenceState={setShowLicenceState}
|
||||||
|
showArchived={filter.archived}
|
||||||
|
setShowArchived={e => setFilter({...filter, archived: e})}
|
||||||
clubFilter={filter.club}
|
clubFilter={filter.club}
|
||||||
setClubFilter={e => setFilter({...filter, club: e})}
|
setClubFilter={e => setFilter({...filter, club: e})}
|
||||||
source={source}
|
source={source}
|
||||||
@@ -523,6 +526,8 @@ function OrderBar({onOrderChange, defaultValues = "", source}) {
|
|||||||
function FiltreBar({
|
function FiltreBar({
|
||||||
showLicenceState,
|
showLicenceState,
|
||||||
setShowLicenceState,
|
setShowLicenceState,
|
||||||
|
showArchived,
|
||||||
|
setShowArchived,
|
||||||
clubFilter,
|
clubFilter,
|
||||||
setClubFilter,
|
setClubFilter,
|
||||||
source,
|
source,
|
||||||
@@ -538,6 +543,9 @@ function FiltreBar({
|
|||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<Checkbox value={showLicenceState} onChange={setShowLicenceState} label="Afficher l'état des licences"/>
|
<Checkbox value={showLicenceState} onChange={setShowLicenceState} label="Afficher l'état des licences"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<Checkbox value={showArchived} onChange={setShowArchived} name="checkbox2" label="Afficher les combattants inactifs"/>
|
||||||
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<select className="form-select" value={catFilter} onChange={event => setCatFilter(event.target.value)}>
|
<select className="form-select" value={catFilter} onChange={event => setCatFilter(event.target.value)}>
|
||||||
<option value="">--- toute les catégories ---</option>
|
<option value="">--- toute les catégories ---</option>
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import {AxiosError} from "../components/AxiosError.jsx";
|
|||||||
import {ThreeDots} from "react-loader-spinner";
|
import {ThreeDots} from "react-loader-spinner";
|
||||||
import {useEffect, useRef, useState} from "react";
|
import {useEffect, useRef, useState} from "react";
|
||||||
import {useLocation, useNavigate} from "react-router-dom";
|
import {useLocation, useNavigate} from "react-router-dom";
|
||||||
import {apiAxios, errFormater} from "../utils/Tools.js";
|
import {apiAxios, errFormater, getCatName} from "../utils/Tools.js";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
import {SearchBar} from "../components/SearchBar.jsx";
|
import {SearchBar} from "../components/SearchBar.jsx";
|
||||||
import {ConfirmDialog} from "../components/ConfirmDialog.jsx";
|
import {ConfirmDialog} from "../components/ConfirmDialog.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {faCircleInfo, faEuroSign} from "@fortawesome/free-solid-svg-icons";
|
import {faCircleInfo, faEuroSign} from "@fortawesome/free-solid-svg-icons";
|
||||||
import "./PayAndValidateList.css";
|
import "./PayAndValidateList.css";
|
||||||
|
import * as Tools from "../utils/Tools.js";
|
||||||
|
|
||||||
export function PayAndValidateList({source}) {
|
export function PayAndValidateList({source}) {
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ export function PayAndValidateList({source}) {
|
|||||||
const [memberData, setMemberData] = useState([]);
|
const [memberData, setMemberData] = useState([]);
|
||||||
const [licenceData, setLicenceData] = useState([]);
|
const [licenceData, setLicenceData] = useState([]);
|
||||||
const [clubFilter, setClubFilter] = useState("");
|
const [clubFilter, setClubFilter] = useState("");
|
||||||
|
const [catFilter, setCatFilter] = useState("");
|
||||||
const [stateFilter, setStateFilter] = useState((source === "club") ? 1 : 2)
|
const [stateFilter, setStateFilter] = useState((source === "club") ? 1 : 2)
|
||||||
const [lastSearch, setLastSearch] = useState("");
|
const [lastSearch, setLastSearch] = useState("");
|
||||||
const [paymentFilter, setPaymentFilter] = useState((source === "club") ? 0 : 2);
|
const [paymentFilter, setPaymentFilter] = useState((source === "club") ? 0 : 2);
|
||||||
@@ -34,15 +36,15 @@ export function PayAndValidateList({source}) {
|
|||||||
data,
|
data,
|
||||||
error,
|
error,
|
||||||
refresh
|
refresh
|
||||||
} = useFetch(`/member/find/${source}?page=${page}&licenceRequest=${stateFilter}&payment=${paymentFilter}`, setLoading, 1)
|
} = useFetch(`/member/find/${source}?page=${page}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`, setLoading, 1)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
sessionStorage.setItem("selectedMembers", JSON.stringify(selectedMembers));
|
sessionStorage.setItem("selectedMembers", JSON.stringify(selectedMembers));
|
||||||
}, [selectedMembers]);
|
}, [selectedMembers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}`);
|
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`);
|
||||||
}, [hash, clubFilter, stateFilter, lastSearch, paymentFilter]);
|
}, [hash, clubFilter, stateFilter, lastSearch, paymentFilter, catFilter]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data)
|
if (!data)
|
||||||
@@ -62,7 +64,7 @@ export function PayAndValidateList({source}) {
|
|||||||
setMemberData(data2);
|
setMemberData(data2);
|
||||||
}, [data, licenceData]);
|
}, [data, licenceData]);
|
||||||
|
|
||||||
useEffect(() => {
|
const fetchLicenceData = () => {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
apiAxios.get(`/licence/current/${source}`),
|
apiAxios.get(`/licence/current/${source}`),
|
||||||
{
|
{
|
||||||
@@ -77,6 +79,10 @@ export function PayAndValidateList({source}) {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
setLicenceData(data.data);
|
setLicenceData(data.data);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchLicenceData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const search = (search) => {
|
const search = (search) => {
|
||||||
@@ -104,7 +110,31 @@ export function PayAndValidateList({source}) {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
setSelectedMembers([]);
|
setSelectedMembers([]);
|
||||||
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}`);
|
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePayment = () => {
|
||||||
|
if (selectedMembers.length === 0) {
|
||||||
|
toast.error("Aucun membre sélectionné");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.promise(
|
||||||
|
apiAxios.post(`/licence/validate-pay`, selectedMembers),
|
||||||
|
{
|
||||||
|
pending: "Validation des licences en cours...",
|
||||||
|
success: "Licences validées avec succès 🎉",
|
||||||
|
error: {
|
||||||
|
render({data}) {
|
||||||
|
return errFormater(data, "Échec de la validation des licences")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
setSelectedMembers([]);
|
||||||
|
fetchLicenceData();
|
||||||
|
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,13 +183,20 @@ export function PayAndValidateList({source}) {
|
|||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<FiltreBar data={data} clubFilter={clubFilter} setClubFilter={setClubFilter} source={source}
|
<FiltreBar data={data} clubFilter={clubFilter} setClubFilter={setClubFilter} source={source}
|
||||||
stateFilter={stateFilter} setStateFilter={setStateFilter} paymentFilter={paymentFilter}
|
stateFilter={stateFilter} setStateFilter={setStateFilter} paymentFilter={paymentFilter}
|
||||||
setPaymentFilter={setPaymentFilter}/>
|
setPaymentFilter={setPaymentFilter} setCatFilter={setCatFilter} catFilter={catFilter}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
{source === "admin" && <>
|
{source === "admin" && <>
|
||||||
<button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#confirm-validation">Valider
|
<button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#confirm-pay">Valider le payement
|
||||||
|
des {selectedMembers.length} licences sélectionnée
|
||||||
|
</button>
|
||||||
|
<ConfirmDialog title="Payment des licences"
|
||||||
|
message={"Êtes-vous sûr de vouloir marquer comme payées les " + selectedMembers.length + " licences ?"}
|
||||||
|
onConfirm={handlePayment} id="confirm-pay"/>
|
||||||
|
|
||||||
|
<button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#confirm-validation" style={{marginTop: "0.5em"}}>Valider
|
||||||
les {selectedMembers.length} licences sélectionnée
|
les {selectedMembers.length} licences sélectionnée
|
||||||
</button>
|
</button>
|
||||||
<ConfirmDialog title="Validation des licences"
|
<ConfirmDialog title="Validation des licences"
|
||||||
@@ -385,7 +422,7 @@ function MakeRow({member, source, isChecked, onCheckboxClick, onRowClick}) {
|
|||||||
|
|
||||||
let allClub = []
|
let allClub = []
|
||||||
|
|
||||||
function FiltreBar({data, clubFilter, setClubFilter, source, stateFilter, setStateFilter, paymentFilter, setPaymentFilter}) {
|
function FiltreBar({data, clubFilter, setClubFilter, source, stateFilter, setStateFilter, paymentFilter, setPaymentFilter, setCatFilter, catFilter}) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
@@ -395,6 +432,14 @@ function FiltreBar({data, clubFilter, setClubFilter, source, stateFilter, setSta
|
|||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
{source !== "club" && <ClubSelectFilter clubFilter={clubFilter} setClubFilter={setClubFilter}/>}
|
{source !== "club" && <ClubSelectFilter clubFilter={clubFilter} setClubFilter={setClubFilter}/>}
|
||||||
|
<div className="mb-3">
|
||||||
|
<select className="form-select" value={catFilter} onChange={event => setCatFilter(event.target.value)}>
|
||||||
|
<option value="">--- toute les catégories ---</option>
|
||||||
|
{Tools.CatList.map(cat => (
|
||||||
|
<option key={cat} value={cat}>{getCatName(cat)}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<select className="form-select" value={stateFilter} onChange={event => setStateFilter(Number(event.target.value))}>
|
<select className="form-select" value={stateFilter} onChange={event => setStateFilter(Number(event.target.value))}>
|
||||||
<option value={1}>Avec demande ou licence validée</option>
|
<option value={1}>Avec demande ou licence validée</option>
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ export function InformationForm({data}) {
|
|||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
}
|
}
|
||||||
}).then(_ => {
|
}).then(_ => {
|
||||||
toast.success('Profile mis à jours avec succès 🎉');
|
toast.success('Profil mis à jours avec succès 🎉');
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.log(e.response)
|
console.log(e.response)
|
||||||
toast.error(errFormater(e,'Échec de la mise à jours du profile 😕'));
|
toast.error(errFormater(e,'Échec de la mise à jours du profil 😕'));
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
if (setLoading)
|
if (setLoading)
|
||||||
setLoading(0)
|
setLoading(0)
|
||||||
@@ -114,4 +114,4 @@ export function InformationForm({data}) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>;
|
</form>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,15 +147,13 @@ function SearchMember({sendRegister}) {
|
|||||||
|
|
||||||
const handleAdd = (name) => {
|
const handleAdd = (name) => {
|
||||||
const member = data.find(m => `${m.fname} ${m.lname}`.trim() === name);
|
const member = data.find(m => `${m.fname} ${m.lname}`.trim() === name);
|
||||||
console.log("Quick add licence:", member)
|
|
||||||
|
|
||||||
if (!member) {
|
if (!member) {
|
||||||
toast.error("Combattant non trouvé");
|
toast.error("Combattant non trouvé");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRegister({
|
sendRegister({
|
||||||
licence: member.licence, fname: member.fname, lname: member.lname, weight: "", overCategory: 0, lockEdit: false, id: null
|
licence: member.licence.trim(), fname: member.fname.trim(), lname: member.lname.trim(), weight: "", overCategory: 0, lockEdit: false, id: null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cats && cats.length > 0 && !cat) {
|
if (cats && cats.length > 0 && !cat) {
|
||||||
setCatId(cats.sort((a, b) => a.name.localeCompare(b.name))[0].id);
|
setCatId(cats.sort((a, b) => a.name.localeCompare(b.name))[0].id);
|
||||||
|
} else if (cats && cats.length === 0) {
|
||||||
|
setModal({});
|
||||||
|
bthRef.current.click();
|
||||||
}
|
}
|
||||||
}, [cats]);
|
}, [cats]);
|
||||||
|
|
||||||
@@ -77,7 +80,6 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
} else { // New category
|
} else { // New category
|
||||||
setModal({});
|
setModal({});
|
||||||
bthRef.current.click();
|
bthRef.current.click();
|
||||||
console.log(cat);
|
|
||||||
e.target.value = cat?.id;
|
e.target.value = cat?.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user