dev #105
@ -0,0 +1,71 @@
|
|||||||
|
package fr.titionfire.ffsaf.data.model;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.utils.Categorie;
|
||||||
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@RegisterForReflection
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "category_preset")
|
||||||
|
public class CatPresetModel {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "competition", referencedColumnName = "id")
|
||||||
|
CompetitionModel competition;
|
||||||
|
|
||||||
|
String name = "";
|
||||||
|
|
||||||
|
List<Categorie> categories;
|
||||||
|
|
||||||
|
long roundDuration;
|
||||||
|
long pauseDuration;
|
||||||
|
|
||||||
|
SwordType swordType = SwordType.NONE;
|
||||||
|
ShieldType shieldType = ShieldType.NONE;
|
||||||
|
|
||||||
|
/* Bitmask protections:
|
||||||
|
* 1 - 1 - Head
|
||||||
|
* 2 - 2 - Throat
|
||||||
|
* 3 - 4 - Torso
|
||||||
|
* 4 - 8 - Arms
|
||||||
|
* 5 - 16 - Hands
|
||||||
|
* 6 - 32 - Groin
|
||||||
|
* 7 - 64 - Legs
|
||||||
|
*/
|
||||||
|
int mandatoryProtection = 0;
|
||||||
|
|
||||||
|
@ManyToMany(mappedBy = "categoriesInscrites", fetch = FetchType.LAZY)
|
||||||
|
private List<RegisterModel> registers = new ArrayList<>();
|
||||||
|
|
||||||
|
@ManyToMany(mappedBy = "categoriesInscrites", fetch = FetchType.LAZY)
|
||||||
|
private List<CompetitionGuestModel> guest = new ArrayList<>();
|
||||||
|
|
||||||
|
public enum SwordType {
|
||||||
|
NONE,
|
||||||
|
ONE_HAND,
|
||||||
|
TWO_HAND,
|
||||||
|
SABER
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ShieldType {
|
||||||
|
NONE,
|
||||||
|
STANDARD,
|
||||||
|
ROUND,
|
||||||
|
TEARDROP,
|
||||||
|
BUCKLER
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -44,4 +44,8 @@ public class CategoryModel {
|
|||||||
Integer type;
|
Integer type;
|
||||||
|
|
||||||
String liceName = "1";
|
String liceName = "1";
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
|
@JoinColumn(name = "id_preset", referencedColumnName = "id")
|
||||||
|
CatPresetModel preset;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,14 @@ public class CompetitionGuestModel implements CombModel {
|
|||||||
)
|
)
|
||||||
List<CompetitionGuestModel> guest = new ArrayList<>();
|
List<CompetitionGuestModel> guest = new ArrayList<>();
|
||||||
|
|
||||||
|
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
|
||||||
|
@JoinTable(
|
||||||
|
name = "categories_insc_guest",
|
||||||
|
joinColumns = @JoinColumn(name = "guest_id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "category_id")
|
||||||
|
)
|
||||||
|
List<CatPresetModel> categoriesInscrites = new ArrayList<>();
|
||||||
|
|
||||||
public CompetitionGuestModel(String s) {
|
public CompetitionGuestModel(String s) {
|
||||||
this.fname = s.substring(0, s.indexOf(" "));
|
this.fname = s.substring(0, s.indexOf(" "));
|
||||||
this.lname = s.substring(s.indexOf(" ") + 1);
|
this.lname = s.substring(s.indexOf(" ") + 1);
|
||||||
|
|||||||
@ -58,6 +58,8 @@ public class CompetitionModel {
|
|||||||
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||||
List<CompetitionGuestModel> guests = new ArrayList<>();
|
List<CompetitionGuestModel> guests = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
|
||||||
|
List<CatPresetModel> catPreset = new ArrayList<>();
|
||||||
|
|
||||||
List<Long> banMembre = new ArrayList<>();
|
List<Long> banMembre = new ArrayList<>();
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,9 @@ import lombok.Setter;
|
|||||||
import org.hibernate.annotations.OnDelete;
|
import org.hibernate.annotations.OnDelete;
|
||||||
import org.hibernate.annotations.OnDeleteAction;
|
import org.hibernate.annotations.OnDeleteAction;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -46,6 +49,17 @@ public class RegisterModel {
|
|||||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||||
boolean lockEdit = false;
|
boolean lockEdit = false;
|
||||||
|
|
||||||
|
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
|
||||||
|
@JoinTable(
|
||||||
|
name = "categories_insc_comb",
|
||||||
|
joinColumns = {
|
||||||
|
@JoinColumn(name = "id_competition", referencedColumnName = "id_competition"),
|
||||||
|
@JoinColumn(name = "id_membre", referencedColumnName = "id_membre")
|
||||||
|
},
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "category_id")
|
||||||
|
)
|
||||||
|
List<CatPresetModel> categoriesInscrites = new ArrayList<>();
|
||||||
|
|
||||||
public RegisterModel(CompetitionModel competition, MembreModel membre, Integer weight, int overCategory,
|
public RegisterModel(CompetitionModel competition, MembreModel membre, Integer weight, int overCategory,
|
||||||
Categorie categorie, ClubModel club) {
|
Categorie categorie, ClubModel club) {
|
||||||
this.id = new RegisterId(competition.getId(), membre.getId());
|
this.id = new RegisterId(competition.getId(), membre.getId());
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
package fr.titionfire.ffsaf.data.repository;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.data.model.CatPresetModel;
|
||||||
|
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class CatPresetRepository implements PanacheRepositoryBase<CatPresetModel, Long> {
|
||||||
|
}
|
||||||
@ -98,12 +98,14 @@ public class CompetPermService {
|
|||||||
map.putIfAbsent(model.getId(), "owner");
|
map.putIfAbsent(model.getId(), "owner");
|
||||||
else if (securityCtx.roleHas("federation_admin"))
|
else if (securityCtx.roleHas("federation_admin"))
|
||||||
map.putIfAbsent(model.getId(), "admin");
|
map.putIfAbsent(model.getId(), "admin");
|
||||||
else if (securityCtx.isInClubGroup(model.getClub().getId()) && (securityCtx.roleHas(
|
else if (securityCtx.isInClubGroup(
|
||||||
"club_president")
|
model.getClub().getId()) && (securityCtx.isClubAdmin()))
|
||||||
|| securityCtx.roleHas("club_respo_intra") || securityCtx.roleHas(
|
|
||||||
"club_secretaire")
|
|
||||||
|| securityCtx.roleHas("club_tresorier")))
|
|
||||||
map.putIfAbsent(model.getId(), "admin");
|
map.putIfAbsent(model.getId(), "admin");
|
||||||
|
else if (model.getAdmin().contains(securityCtx.getSubject()))
|
||||||
|
map.putIfAbsent(model.getId(), "admin");
|
||||||
|
else if (model.getTable().contains(securityCtx.getSubject()))
|
||||||
|
map.putIfAbsent(model.getId(), "table");
|
||||||
|
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}));
|
}));
|
||||||
@ -182,12 +184,14 @@ public class CompetPermService {
|
|||||||
if (o.getSystem() == CompetitionSystem.SAFCA)
|
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||||
return hasSafcaViewPerm(securityCtx, o.getId());
|
return hasSafcaViewPerm(securityCtx, o.getId());
|
||||||
|
|
||||||
|
if (o.getAdmin().contains(securityCtx.getSubject()))
|
||||||
|
return Uni.createFrom().nullItem();
|
||||||
|
|
||||||
if (!securityCtx.isInClubGroup(o.getClub().getId())) // Only membre club pass here
|
if (!securityCtx.isInClubGroup(o.getClub().getId())) // Only membre club pass here
|
||||||
throw new DForbiddenException();
|
throw new DForbiddenException();
|
||||||
|
|
||||||
if (o.getSystem() == CompetitionSystem.INTERNAL)
|
if (o.getSystem() == CompetitionSystem.INTERNAL)
|
||||||
if (securityCtx.roleHas("club_president") || securityCtx.roleHas("club_respo_intra")
|
if (securityCtx.isClubAdmin())
|
||||||
|| securityCtx.roleHas("club_secretaire") || securityCtx.roleHas("club_tresorier"))
|
|
||||||
return Uni.createFrom().nullItem();
|
return Uni.createFrom().nullItem();
|
||||||
|
|
||||||
throw new DForbiddenException();
|
throw new DForbiddenException();
|
||||||
|
|||||||
@ -7,10 +7,7 @@ import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
|||||||
import fr.titionfire.ffsaf.net2.request.SReqCompet;
|
import fr.titionfire.ffsaf.net2.request.SReqCompet;
|
||||||
import fr.titionfire.ffsaf.net2.request.SReqRegister;
|
import fr.titionfire.ffsaf.net2.request.SReqRegister;
|
||||||
import fr.titionfire.ffsaf.rest.client.dto.NotificationData;
|
import fr.titionfire.ffsaf.rest.client.dto.NotificationData;
|
||||||
import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
import fr.titionfire.ffsaf.rest.data.*;
|
||||||
import fr.titionfire.ffsaf.rest.data.RegisterRequestData;
|
|
||||||
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
|
||||||
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
|
||||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||||
@ -63,6 +60,9 @@ public class CompetitionService {
|
|||||||
@Inject
|
@Inject
|
||||||
CompetitionGuestRepository competitionGuestRepository;
|
CompetitionGuestRepository competitionGuestRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CatPresetRepository catPresetRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ServerCustom serverCustom;
|
ServerCustom serverCustom;
|
||||||
|
|
||||||
@ -112,16 +112,14 @@ public class CompetitionService {
|
|||||||
|
|
||||||
public Uni<CompetitionData> getByIdAdmin(SecurityCtx securityCtx, Long id) {
|
public Uni<CompetitionData> getByIdAdmin(SecurityCtx securityCtx, Long id) {
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
return Uni.createFrom()
|
return Uni.createFrom().item(new CompetitionData());
|
||||||
.item(new CompetitionData(null, "", "", "", "", new Date(), new Date(),
|
|
||||||
CompetitionSystem.INTERNAL, RegisterMode.FREE, new Date(), new Date(), true,
|
|
||||||
null, "", "", null, true, true,
|
|
||||||
"", "", "", "", "{}"));
|
|
||||||
}
|
}
|
||||||
return permService.hasAdminViewPerm(securityCtx, id)
|
return permService.hasAdminViewPerm(securityCtx, id)
|
||||||
|
.call(competitionModel -> Mutiny.fetch(competitionModel.getCatPreset()))
|
||||||
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
||||||
.chain(insc -> Mutiny.fetch(competitionModel.getGuests())
|
.chain(insc -> Mutiny.fetch(competitionModel.getGuests())
|
||||||
.map(guest -> CompetitionData.fromModel(competitionModel).addInsc(insc, guest))))
|
.map(guest -> CompetitionData.fromModel(competitionModel).addInsc(insc, guest)
|
||||||
|
.addPresets(competitionModel.getCatPreset()))))
|
||||||
.chain(data ->
|
.chain(data ->
|
||||||
vertx.getOrCreateContext().executeBlocking(() -> {
|
vertx.getOrCreateContext().executeBlocking(() -> {
|
||||||
keycloakService.getUser(UUID.fromString(data.getOwner()))
|
keycloakService.getUser(UUID.fromString(data.getOwner()))
|
||||||
@ -208,17 +206,21 @@ public class CompetitionService {
|
|||||||
model.setGuests(new ArrayList<>());
|
model.setGuests(new ArrayList<>());
|
||||||
model.setUuid(UUID.randomUUID().toString());
|
model.setUuid(UUID.randomUUID().toString());
|
||||||
model.setOwner(securityCtx.getSubject());
|
model.setOwner(securityCtx.getSubject());
|
||||||
|
model.setCatPreset(new ArrayList<>());
|
||||||
|
|
||||||
copyData(data, model);
|
copyData(data, model);
|
||||||
|
|
||||||
return Panache.withTransaction(() -> repository.persist(model));
|
return Panache.withTransaction(() -> repository.persist(model));
|
||||||
}).map(CompetitionData::fromModel)
|
})
|
||||||
|
.call(model -> syncPreset(data, model))
|
||||||
|
.map(CompetitionData::fromModel)
|
||||||
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||||
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||||
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
||||||
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
||||||
} else {
|
} else {
|
||||||
return permService.hasEditPerm(securityCtx, data.getId())
|
return permService.hasEditPerm(securityCtx, data.getId())
|
||||||
|
.call(model -> Mutiny.fetch(model.getCatPreset()))
|
||||||
.chain(model -> {
|
.chain(model -> {
|
||||||
copyData(data, model);
|
copyData(data, model);
|
||||||
|
|
||||||
@ -237,7 +239,9 @@ public class CompetitionService {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(__ -> Panache.withTransaction(() -> repository.persist(model)));
|
.chain(__ -> Panache.withTransaction(() -> repository.persist(model)));
|
||||||
}).map(CompetitionData::fromModel)
|
})
|
||||||
|
.call(model -> syncPreset(data, model))
|
||||||
|
.map(model -> CompetitionData.fromModel(model).addPresets(model.getCatPreset()))
|
||||||
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||||
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||||
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
||||||
@ -245,6 +249,46 @@ public class CompetitionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Uni<?> syncPreset(CompetitionData data, CompetitionModel model) {
|
||||||
|
List<Long> toRemoveId = model.getCatPreset().stream()
|
||||||
|
.map(CatPresetModel::getId)
|
||||||
|
.filter(id -> data.getPresets().stream().noneMatch(preset -> Objects.equals(preset.getId(), id)))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (PresetData preset : data.getPresets()) {
|
||||||
|
CatPresetModel presetModel;
|
||||||
|
if (preset.getId() != null && preset.getId() > 0) {
|
||||||
|
presetModel = model.getCatPreset().stream()
|
||||||
|
.filter(p -> p.getId().equals(preset.getId()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(new CatPresetModel());
|
||||||
|
} else {
|
||||||
|
presetModel = new CatPresetModel();
|
||||||
|
model.getCatPreset().add(presetModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
presetModel.setCompetition(model);
|
||||||
|
presetModel.setName(preset.getName());
|
||||||
|
presetModel.setSwordType(preset.getSword());
|
||||||
|
presetModel.setShieldType(preset.getShield());
|
||||||
|
presetModel.setRoundDuration(preset.getRoundDuration());
|
||||||
|
presetModel.setPauseDuration(preset.getPauseDuration());
|
||||||
|
presetModel.setCategories(preset.getCategories());
|
||||||
|
presetModel.setMandatoryProtection(preset.getMandatoryProtection());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove deleted presets
|
||||||
|
model.getCatPreset().removeIf(presetModel -> toRemoveId.contains(presetModel.getId()));
|
||||||
|
|
||||||
|
return Panache.withTransaction(() -> repository.persist(model)
|
||||||
|
.call(__ -> {
|
||||||
|
if (!toRemoveId.isEmpty()) {
|
||||||
|
return catPresetRepository.delete("id IN ?1", toRemoveId);
|
||||||
|
}
|
||||||
|
return Uni.createFrom().nullItem();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
private void copyData(CompetitionData data, CompetitionModel model) {
|
private void copyData(CompetitionData data, CompetitionModel model) {
|
||||||
if (model.getBanMembre() == null)
|
if (model.getBanMembre() == null)
|
||||||
model.setBanMembre(new ArrayList<>());
|
model.setBanMembre(new ArrayList<>());
|
||||||
@ -271,11 +315,17 @@ public class CompetitionService {
|
|||||||
Uni<List<SimpleRegisterComb>> uni = Mutiny.fetch(c.getInsc())
|
Uni<List<SimpleRegisterComb>> uni = Mutiny.fetch(c.getInsc())
|
||||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||||
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
||||||
.map(cm -> SimpleRegisterComb.fromModel(cm, cm.getMembre().getLicences()))
|
.onItem().call(combModel -> Mutiny.fetch(combModel.getCategoriesInscrites()))
|
||||||
|
.map(cm -> SimpleRegisterComb.fromModel(cm, cm.getMembre().getLicences())
|
||||||
|
.setCategorieInscrite(cm.getCategoriesInscrites()))
|
||||||
.collect().asList();
|
.collect().asList();
|
||||||
return uni
|
return uni
|
||||||
.call(l -> Mutiny.fetch(c.getGuests())
|
.call(l -> Mutiny.fetch(c.getGuests())
|
||||||
.map(guest -> guest.stream().map(SimpleRegisterComb::fromModel).toList())
|
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||||
|
.onItem().call(guest -> Mutiny.fetch(guest.getCategoriesInscrites()))
|
||||||
|
.map(guest -> SimpleRegisterComb.fromModel(guest)
|
||||||
|
.setCategorieInscrite(guest.getCategoriesInscrites()))
|
||||||
|
.collect().asList()
|
||||||
.invoke(l::addAll));
|
.invoke(l::addAll));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -290,11 +340,15 @@ public class CompetitionService {
|
|||||||
model.getClub()))
|
model.getClub()))
|
||||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||||
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
||||||
.map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences()))
|
.onItem().call(combModel -> Mutiny.fetch(combModel.getCategoriesInscrites()))
|
||||||
|
.map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences())
|
||||||
|
.setCategorieInscrite(combModel.getCategoriesInscrites()))
|
||||||
.collect().asList();
|
.collect().asList();
|
||||||
|
|
||||||
return membreService.getByAccountId(securityCtx.getSubject())
|
return membreService.getByAccountId(securityCtx.getSubject())
|
||||||
.chain(model -> registerRepository.find("competition.id = ?1 AND membre = ?2", id, model).firstResult()
|
.chain(model -> registerRepository.find("competition.id = ?1 AND membre = ?2", id, model).firstResult()
|
||||||
|
.call(rm -> rm == null ? Uni.createFrom().voidItem() :
|
||||||
|
Mutiny.fetch(rm.getCategoriesInscrites()))
|
||||||
.map(rm -> rm == null ? List.of() : List.of(SimpleRegisterComb.fromModel(rm, List.of()))));
|
.map(rm -> rm == null ? List.of() : List.of(SimpleRegisterComb.fromModel(rm, List.of()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +366,8 @@ public class CompetitionService {
|
|||||||
return Panache.withTransaction(() -> repository.persist(c));
|
return Panache.withTransaction(() -> repository.persist(c));
|
||||||
})
|
})
|
||||||
.chain(combModel -> updateRegister(data, c, combModel, true)))
|
.chain(combModel -> updateRegister(data, c, combModel, true)))
|
||||||
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()));
|
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences())
|
||||||
|
.setCategorieInscrite(r.getCategoriesInscrites()));
|
||||||
} else {
|
} else {
|
||||||
return permService.hasEditPerm(securityCtx, id)
|
return permService.hasEditPerm(securityCtx, id)
|
||||||
.chain(c -> competitionGuestRepository.findById(data.getId() * -1)
|
.chain(c -> competitionGuestRepository.findById(data.getId() * -1)
|
||||||
@ -323,7 +378,7 @@ public class CompetitionService {
|
|||||||
model.setCompetition(c);
|
model.setCompetition(c);
|
||||||
return model;
|
return model;
|
||||||
}))
|
}))
|
||||||
.chain(model -> {
|
.invoke(model -> {
|
||||||
model.setFname(data.getFname());
|
model.setFname(data.getFname());
|
||||||
if (data.getLname().equals("__team"))
|
if (data.getLname().equals("__team"))
|
||||||
model.setLname("_team");
|
model.setLname("_team");
|
||||||
@ -334,13 +389,21 @@ public class CompetitionService {
|
|||||||
model.setCountry(data.getCountry());
|
model.setCountry(data.getCountry());
|
||||||
model.setWeight(data.getWeight());
|
model.setWeight(data.getWeight());
|
||||||
model.setCategorie(data.getCategorie());
|
model.setCategorie(data.getCategorie());
|
||||||
|
|
||||||
return Panache.withTransaction(() -> competitionGuestRepository.persist(model))
|
|
||||||
.call(r -> model.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
|
|
||||||
sRegister.sendRegister(model.getCompetition().getUuid(),
|
|
||||||
r) : Uni.createFrom().voidItem());
|
|
||||||
})
|
})
|
||||||
.map(SimpleRegisterComb::fromModel);
|
.call(g -> Mutiny.fetch(g.getCategoriesInscrites()))
|
||||||
|
.call(g -> catPresetRepository.list("competition = ?1 AND id IN ?2", g.getCompetition(),
|
||||||
|
data.getCategoriesInscrites())
|
||||||
|
.invoke(cats -> {
|
||||||
|
g.getCategoriesInscrites().clear();
|
||||||
|
g.getCategoriesInscrites().addAll(cats);
|
||||||
|
g.getCategoriesInscrites()
|
||||||
|
.removeIf(cat -> !cat.getCategories().contains(g.getCategorie()));
|
||||||
|
}))
|
||||||
|
.chain(model -> Panache.withTransaction(() -> competitionGuestRepository.persist(model))
|
||||||
|
.call(r -> model.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
|
||||||
|
sRegister.sendRegister(model.getCompetition().getUuid(),
|
||||||
|
r) : Uni.createFrom().voidItem()))
|
||||||
|
.map(g -> SimpleRegisterComb.fromModel(g).setCategorieInscrite(g.getCategoriesInscrites()));
|
||||||
}
|
}
|
||||||
if ("club".equals(source))
|
if ("club".equals(source))
|
||||||
return repository.findById(id)
|
return repository.findById(id)
|
||||||
@ -418,6 +481,19 @@ public class CompetitionService {
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}))
|
}))
|
||||||
|
.call(r -> Mutiny.fetch(r.getCategoriesInscrites()).chain(__ ->
|
||||||
|
catPresetRepository.list("competition = ?1 AND id IN ?2", c, data.getCategoriesInscrites())
|
||||||
|
.invoke(cats -> {
|
||||||
|
if (data.isQuick()) {
|
||||||
|
cats.removeIf(cat -> r.getCategoriesInscrites().stream()
|
||||||
|
.anyMatch(cp -> cp.equals(cat)));
|
||||||
|
} else {
|
||||||
|
r.getCategoriesInscrites().clear();
|
||||||
|
}
|
||||||
|
r.getCategoriesInscrites().addAll(cats);
|
||||||
|
r.getCategoriesInscrites()
|
||||||
|
.removeIf(cat -> !cat.getCategories().contains(r.getCategorie2()));
|
||||||
|
})))
|
||||||
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r)))
|
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r)))
|
||||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||||
sRegister.sendRegister(c.getUuid(), r) : Uni.createFrom().voidItem());
|
sRegister.sendRegister(c.getUuid(), r) : Uni.createFrom().voidItem());
|
||||||
@ -660,6 +736,12 @@ public class CompetitionService {
|
|||||||
.call(__ -> cache.invalidate(data.getId()));
|
.call(__ -> cache.invalidate(data.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Uni<List<PresetData>> getPresetsForCompetition(SecurityCtx securityCtx, Long id) {
|
||||||
|
return permService.hasViewPerm(securityCtx, id)
|
||||||
|
.chain(cm -> Mutiny.fetch(cm.getCatPreset()))
|
||||||
|
.map(p -> p.stream().map(PresetData::fromModel).toList());
|
||||||
|
}
|
||||||
|
|
||||||
public Uni<Response> unregisterHelloAsso(NotificationData data) {
|
public Uni<Response> unregisterHelloAsso(NotificationData data) {
|
||||||
if (!data.getState().equals("Refunded"))
|
if (!data.getState().equals("Refunded"))
|
||||||
return Uni.createFrom().item(Response.ok().build());
|
return Uni.createFrom().item(Response.ok().build());
|
||||||
@ -693,8 +775,8 @@ public class CompetitionService {
|
|||||||
public Uni<Response> registerHelloAsso(NotificationData data) {
|
public Uni<Response> registerHelloAsso(NotificationData data) {
|
||||||
String organizationSlug = data.getOrganizationSlug();
|
String organizationSlug = data.getOrganizationSlug();
|
||||||
String formSlug = data.getFormSlug();
|
String formSlug = data.getFormSlug();
|
||||||
RegisterRequestData req = new RegisterRequestData(null, "", "", null, 0, false, null, Categorie.CADET, Genre.NA,
|
RegisterRequestData req = new RegisterRequestData(null, "", "", null, 0, false, new ArrayList<>(), null,
|
||||||
null, "fr");
|
Categorie.CADET, Genre.NA, null, "fr", false);
|
||||||
|
|
||||||
return repository.find("data1 = ?1 AND data2 = ?2", organizationSlug, formSlug).firstResult()
|
return repository.find("data1 = ?1 AND data2 = ?2", organizationSlug, formSlug).firstResult()
|
||||||
.onFailure().recoverWithNull()
|
.onFailure().recoverWithNull()
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
package fr.titionfire.ffsaf.rest;
|
package fr.titionfire.ffsaf.rest;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.domain.service.CompetitionService;
|
import fr.titionfire.ffsaf.domain.service.CompetitionService;
|
||||||
import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
import fr.titionfire.ffsaf.rest.data.*;
|
||||||
import fr.titionfire.ffsaf.rest.data.RegisterRequestData;
|
|
||||||
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
|
||||||
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
|
||||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
import io.quarkus.security.Authenticated;
|
import io.quarkus.security.Authenticated;
|
||||||
import io.smallrye.mutiny.Uni;
|
import io.smallrye.mutiny.Uni;
|
||||||
@ -79,6 +76,13 @@ public class CompetitionEndpoints {
|
|||||||
return service.getInternalData(securityCtx, id);
|
return service.getInternalData(securityCtx, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{id}/categories")
|
||||||
|
@Authenticated
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Uni<List<PresetData>> getPresetsForCompetition(@PathParam("id") Long id) {
|
||||||
|
return service.getPresetsForCompetition(securityCtx, id);
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("all")
|
@Path("all")
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package fr.titionfire.ffsaf.rest.data;
|
package fr.titionfire.ffsaf.rest.data;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.data.model.CatPresetModel;
|
||||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||||
@ -10,6 +11,7 @@ import io.quarkus.runtime.annotations.RegisterForReflection;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@ -41,6 +43,14 @@ public class CompetitionData {
|
|||||||
private String data3;
|
private String data3;
|
||||||
private String data4;
|
private String data4;
|
||||||
private String config;
|
private String config;
|
||||||
|
private List<PresetData> presets;
|
||||||
|
|
||||||
|
public CompetitionData () {
|
||||||
|
this(null, "", "", "", "", new Date(), new Date(),
|
||||||
|
CompetitionSystem.INTERNAL, RegisterMode.FREE, new Date(), new Date(), true,
|
||||||
|
null, "", "", null, true, true,
|
||||||
|
"", "", "", "", "{}", new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
public static CompetitionData fromModel(CompetitionModel model) {
|
public static CompetitionData fromModel(CompetitionModel model) {
|
||||||
if (model == null)
|
if (model == null)
|
||||||
@ -50,7 +60,7 @@ public class CompetitionData {
|
|||||||
model.getUuid(), model.getDate(), model.getTodate(), model.getSystem(),
|
model.getUuid(), model.getDate(), model.getTodate(), model.getSystem(),
|
||||||
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||||
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null, false, false,
|
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null, false, false,
|
||||||
model.getData1(), model.getData2(), model.getData3(), model.getData4(), model.getConfig());
|
model.getData1(), model.getData2(), model.getData3(), model.getData4(), model.getConfig(), new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompetitionData fromModelLight(CompetitionModel model) {
|
public static CompetitionData fromModelLight(CompetitionModel model) {
|
||||||
@ -61,7 +71,7 @@ public class CompetitionData {
|
|||||||
model.getAdresse(), "", model.getDate(), model.getTodate(), null,
|
model.getAdresse(), "", model.getDate(), model.getTodate(), null,
|
||||||
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||||
null, model.getClub().getName(), "", null, false, false,
|
null, model.getClub().getName(), "", null, false, false,
|
||||||
"", "", "", "", "{}");
|
"", "", "", "", "{}", new ArrayList<>());
|
||||||
|
|
||||||
if (model.getRegisterMode() == RegisterMode.HELLOASSO) {
|
if (model.getRegisterMode() == RegisterMode.HELLOASSO) {
|
||||||
out.setData1(model.getData1());
|
out.setData1(model.getData1());
|
||||||
@ -84,6 +94,11 @@ public class CompetitionData {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompetitionData addPresets(List<CatPresetModel> presets) {
|
||||||
|
this.presets = presets.stream().map(PresetData::fromModel).toList();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
|
|||||||
32
src/main/java/fr/titionfire/ffsaf/rest/data/PresetData.java
Normal file
32
src/main/java/fr/titionfire/ffsaf/rest/data/PresetData.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package fr.titionfire.ffsaf.rest.data;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.data.model.CatPresetModel;
|
||||||
|
import fr.titionfire.ffsaf.utils.Categorie;
|
||||||
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@RegisterForReflection
|
||||||
|
public class PresetData {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private CatPresetModel.SwordType sword;
|
||||||
|
private CatPresetModel.ShieldType shield;
|
||||||
|
private List<Categorie> categories;
|
||||||
|
long roundDuration;
|
||||||
|
long pauseDuration;
|
||||||
|
int mandatoryProtection;
|
||||||
|
|
||||||
|
public static PresetData fromModel(CatPresetModel model) {
|
||||||
|
if (model == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new PresetData(model.getId(), model.getName(), model.getSwordType(), model.getShieldType(),
|
||||||
|
model.getCategories(), model.getRoundDuration(), model.getPauseDuration(),
|
||||||
|
model.getMandatoryProtection());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,8 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ -19,6 +21,7 @@ public class RegisterRequestData {
|
|||||||
private Integer weight;
|
private Integer weight;
|
||||||
private int overCategory;
|
private int overCategory;
|
||||||
private boolean lockEdit = false;
|
private boolean lockEdit = false;
|
||||||
|
private List<Long> categoriesInscrites;
|
||||||
|
|
||||||
// for guest registration only
|
// for guest registration only
|
||||||
private Long id = null;
|
private Long id = null;
|
||||||
@ -26,4 +29,6 @@ public class RegisterRequestData {
|
|||||||
private Genre genre = Genre.NA;
|
private Genre genre = Genre.NA;
|
||||||
private String club = null;
|
private String club = null;
|
||||||
private String country = null;
|
private String country = null;
|
||||||
|
|
||||||
|
private boolean quick = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
package fr.titionfire.ffsaf.rest.data;
|
package fr.titionfire.ffsaf.rest.data;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
import fr.titionfire.ffsaf.data.model.*;
|
||||||
import fr.titionfire.ffsaf.data.model.LicenceModel;
|
|
||||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
|
||||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
|
||||||
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
||||||
import fr.titionfire.ffsaf.utils.Categorie;
|
import fr.titionfire.ffsaf.utils.Categorie;
|
||||||
import fr.titionfire.ffsaf.utils.Genre;
|
import fr.titionfire.ffsaf.utils.Genre;
|
||||||
@ -12,6 +9,7 @@ import io.quarkus.runtime.annotations.RegisterForReflection;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -30,6 +28,7 @@ public class SimpleRegisterComb {
|
|||||||
private int overCategory;
|
private int overCategory;
|
||||||
private boolean hasLicenceActive;
|
private boolean hasLicenceActive;
|
||||||
private boolean lockEdit;
|
private boolean lockEdit;
|
||||||
|
private List<Long> categoriesInscrites;
|
||||||
|
|
||||||
public static SimpleRegisterComb fromModel(RegisterModel register, List<LicenceModel> licences) {
|
public static SimpleRegisterComb fromModel(RegisterModel register, List<LicenceModel> licences) {
|
||||||
MembreModel membreModel = register.getMembre();
|
MembreModel membreModel = register.getMembre();
|
||||||
@ -39,13 +38,19 @@ public class SimpleRegisterComb {
|
|||||||
SimpleClubModel.fromModel(register.getClub()), membreModel.getLicence(), register.getWeight(),
|
SimpleClubModel.fromModel(register.getClub()), membreModel.getLicence(), register.getWeight(),
|
||||||
register.getOverCategory(),
|
register.getOverCategory(),
|
||||||
licences.stream().anyMatch(l -> l.isValidate() && l.getSaison() == Utils.getSaison()),
|
licences.stream().anyMatch(l -> l.isValidate() && l.getSaison() == Utils.getSaison()),
|
||||||
register.isLockEdit());
|
register.isLockEdit(), new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SimpleRegisterComb fromModel(CompetitionGuestModel guest) {
|
public static SimpleRegisterComb fromModel(CompetitionGuestModel guest) {
|
||||||
return new SimpleRegisterComb(guest.getId() * -1, guest.getFname(), guest.getLname(),
|
return new SimpleRegisterComb(guest.getId() * -1, guest.getFname(), guest.getLname(),
|
||||||
guest.getGenre(), guest.getCountry(), guest.getCategorie(),
|
guest.getGenre(), guest.getCountry(), guest.getCategorie(),
|
||||||
new SimpleClubModel(null, guest.getClub(), "fr", null),
|
new SimpleClubModel(null, guest.getClub(), "fr", null),
|
||||||
null, guest.getWeight(), 0, false, false);
|
null, guest.getWeight(), 0, false, false,
|
||||||
|
new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleRegisterComb setCategorieInscrite(List<CatPresetModel> presets) {
|
||||||
|
this.categoriesInscrites = presets.stream().map(CatPresetModel::getId).toList();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,6 +102,7 @@
|
|||||||
"supprimer": "Delete",
|
"supprimer": "Delete",
|
||||||
"sélectionneLesModesDaffichage": "Select display modes",
|
"sélectionneLesModesDaffichage": "Select display modes",
|
||||||
"sélectionner": "Select",
|
"sélectionner": "Select",
|
||||||
|
"team": "Team",
|
||||||
"terminé": "Finished",
|
"terminé": "Finished",
|
||||||
"texteCopiéDansLePresse": "Text copied to clipboard! Paste it into an HTML tag on your WordPress.",
|
"texteCopiéDansLePresse": "Text copied to clipboard! Paste it into an HTML tag on your WordPress.",
|
||||||
"toast.createCategory.error": "Error while creating the category",
|
"toast.createCategory.error": "Error while creating the category",
|
||||||
@ -113,6 +114,9 @@
|
|||||||
"toast.matchs.create.error": "Error while creating matches.",
|
"toast.matchs.create.error": "Error while creating matches.",
|
||||||
"toast.matchs.create.pending": "Creating matches in progress...",
|
"toast.matchs.create.pending": "Creating matches in progress...",
|
||||||
"toast.matchs.create.success": "Matches created successfully.",
|
"toast.matchs.create.success": "Matches created successfully.",
|
||||||
|
"toast.team.update.error": "Error while updating team",
|
||||||
|
"toast.team.update.pending": "Updating team...",
|
||||||
|
"toast.team.update.success": "Team updated!",
|
||||||
"toast.updateCategory.error": "Error while updating the category",
|
"toast.updateCategory.error": "Error while updating the category",
|
||||||
"toast.updateCategory.pending": "Updating category...",
|
"toast.updateCategory.pending": "Updating category...",
|
||||||
"toast.updateCategory.success": "Category updated!",
|
"toast.updateCategory.success": "Category updated!",
|
||||||
@ -125,12 +129,8 @@
|
|||||||
"toast.updateTrees.init.success": "Trees created!",
|
"toast.updateTrees.init.success": "Trees created!",
|
||||||
"toast.updateTrees.pending": "Updating tournament trees...",
|
"toast.updateTrees.pending": "Updating tournament trees...",
|
||||||
"toast.updateTrees.success": "Trees updated!",
|
"toast.updateTrees.success": "Trees updated!",
|
||||||
"toast.team.update.error": "Error while updating team",
|
|
||||||
"toast.team.update.pending": "Updating team...",
|
|
||||||
"toast.team.update.success": "Team updated!",
|
|
||||||
"tournoi": "Tournament",
|
"tournoi": "Tournament",
|
||||||
"tournois": "Tournaments",
|
"tournois": "Tournaments",
|
||||||
"team": "Team",
|
|
||||||
"tousLesMatchs": "All matches",
|
"tousLesMatchs": "All matches",
|
||||||
"toutConserver": "Keep all",
|
"toutConserver": "Keep all",
|
||||||
"ttm.admin.obs": "Short click: Download resources. Long click: Create OBS configuration",
|
"ttm.admin.obs": "Short click: Download resources. Long click: Create OBS configuration",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"(optionnelle)": "(optional)",
|
"(optionnelle)": "(optional)",
|
||||||
"---SansClub---": "--- no club ---",
|
"---SansClub---": "--- no club ---",
|
||||||
|
"---TousLesAges---": "--- all ages ---",
|
||||||
"---ToutLesClubs---": "--- all clubs ---",
|
"---ToutLesClubs---": "--- all clubs ---",
|
||||||
"---ToutLesPays---": "--- all countries ---",
|
"---ToutLesPays---": "--- all countries ---",
|
||||||
"---TouteLesCatégories---": "--- all categories ---",
|
"---TouteLesCatégories---": "--- all categories ---",
|
||||||
@ -8,6 +9,7 @@
|
|||||||
"--SélectionnerCatégorie--": "-- Select category --",
|
"--SélectionnerCatégorie--": "-- Select category --",
|
||||||
"1Catégorie": "+1 category",
|
"1Catégorie": "+1 category",
|
||||||
"2Catégorie": "+2 categories",
|
"2Catégorie": "+2 categories",
|
||||||
|
"LesModificationsNontEnregistrer": "/!\\ The changes have not yet been saved, click save /!\\",
|
||||||
"activer": "Activate",
|
"activer": "Activate",
|
||||||
"admin": "Administration",
|
"admin": "Administration",
|
||||||
"administrateur": "Administrator",
|
"administrateur": "Administrator",
|
||||||
@ -81,11 +83,14 @@
|
|||||||
"ajouterUnClub": "Add a club",
|
"ajouterUnClub": "Add a club",
|
||||||
"ajouterUnMembre": "Add a member",
|
"ajouterUnMembre": "Add a member",
|
||||||
"all_season": "--- all seasons ---",
|
"all_season": "--- all seasons ---",
|
||||||
|
"arme": "Weapon",
|
||||||
"au": "to",
|
"au": "to",
|
||||||
"aucun": "None",
|
"aucun": "None",
|
||||||
"aucunMembreSélectionné": "No member selected",
|
"aucunMembreSélectionné": "No member selected",
|
||||||
|
"aucuneCatégorieDisponible": "No categories available at this time.",
|
||||||
"back": "« back",
|
"back": "« back",
|
||||||
"blason": "Coat of arms",
|
"blason": "Coat of arms",
|
||||||
|
"bouclier": "Shield",
|
||||||
"bureau": "Board",
|
"bureau": "Board",
|
||||||
"button.accepter": "Accept",
|
"button.accepter": "Accept",
|
||||||
"button.ajouter": "Add",
|
"button.ajouter": "Add",
|
||||||
@ -93,7 +98,6 @@
|
|||||||
"button.appliquer": "Apply",
|
"button.appliquer": "Apply",
|
||||||
"button.confirmer": "Confirm",
|
"button.confirmer": "Confirm",
|
||||||
"button.créer": "Create",
|
"button.créer": "Create",
|
||||||
"button.enregister": "Save",
|
|
||||||
"button.enregistrer": "Save",
|
"button.enregistrer": "Save",
|
||||||
"button.fermer": "Close",
|
"button.fermer": "Close",
|
||||||
"button.modifier": "Edit",
|
"button.modifier": "Edit",
|
||||||
@ -115,6 +119,7 @@
|
|||||||
"cat.vétéran2": "Veteran 2",
|
"cat.vétéran2": "Veteran 2",
|
||||||
"categorie": "category",
|
"categorie": "category",
|
||||||
"catégorie": "Category",
|
"catégorie": "Category",
|
||||||
|
"catégorieàAjouter": "Category to add",
|
||||||
"certificatMédical": "Medical certificate",
|
"certificatMédical": "Medical certificate",
|
||||||
"chargement...": "Loading...",
|
"chargement...": "Loading...",
|
||||||
"chargerLexcel": "Load Excel",
|
"chargerLexcel": "Load Excel",
|
||||||
@ -249,6 +254,7 @@
|
|||||||
"compte": "Account",
|
"compte": "Account",
|
||||||
"compétition": "Competition",
|
"compétition": "Competition",
|
||||||
"configuration": "Configuration",
|
"configuration": "Configuration",
|
||||||
|
"configurationDeLaCatégorie": "Category configuration",
|
||||||
"conserverLancienEmail": "Keep the old email",
|
"conserverLancienEmail": "Keep the old email",
|
||||||
"contactAdministratif": "Administrative contact",
|
"contactAdministratif": "Administrative contact",
|
||||||
"contactInterne": "Internal contact",
|
"contactInterne": "Internal contact",
|
||||||
@ -274,6 +280,8 @@
|
|||||||
"donnéesAdministratives": "Administrative data",
|
"donnéesAdministratives": "Administrative data",
|
||||||
"du": "From",
|
"du": "From",
|
||||||
"dun": "of a",
|
"dun": "of a",
|
||||||
|
"duréePause": "Pause duration",
|
||||||
|
"duréeRound": "Round duration",
|
||||||
"définirLidDuCompte": "Define account ID",
|
"définirLidDuCompte": "Define account ID",
|
||||||
"editionDeL'affiliation": "Editing affiliation",
|
"editionDeL'affiliation": "Editing affiliation",
|
||||||
"editionDeLaDemande": "Editing request",
|
"editionDeLaDemande": "Editing request",
|
||||||
@ -474,6 +482,7 @@
|
|||||||
"permission": "Permission",
|
"permission": "Permission",
|
||||||
"photos": "Photos",
|
"photos": "Photos",
|
||||||
"prenom": "First name",
|
"prenom": "First name",
|
||||||
|
"protectionObligatoire": "Mandatory protection",
|
||||||
"prénomEtNom": "First and last name",
|
"prénomEtNom": "First and last name",
|
||||||
"rechercher": "Search",
|
"rechercher": "Search",
|
||||||
"rechercher...": "Search...",
|
"rechercher...": "Search...",
|
||||||
@ -494,8 +503,15 @@
|
|||||||
"role.vise-secrétaire": "Vice-Secretary",
|
"role.vise-secrétaire": "Vice-Secretary",
|
||||||
"role.vise-trésorier": "Vice-Treasurer",
|
"role.vise-trésorier": "Vice-Treasurer",
|
||||||
"saison": "Season",
|
"saison": "Season",
|
||||||
|
"sans": "Without",
|
||||||
"secrétariatsDeLice": "Ring secretariats",
|
"secrétariatsDeLice": "Ring secretariats",
|
||||||
"selectionner...": "Select...",
|
"selectionner...": "Select...",
|
||||||
|
"shield.buckler": "Buckler",
|
||||||
|
"shield.none": "$t(sans) / $t(nonDéfinie)",
|
||||||
|
"shield.round": "Round",
|
||||||
|
"shield.standard": "Standard",
|
||||||
|
"shield.teardrop": "Teardrop",
|
||||||
|
"siDisponiblePourLaCatégorieDages": "If available for the age category",
|
||||||
"siretOuRna": "SIRET or RNA",
|
"siretOuRna": "SIRET or RNA",
|
||||||
"stats": "Statistics",
|
"stats": "Statistics",
|
||||||
"statue": "Statue",
|
"statue": "Statue",
|
||||||
@ -505,6 +521,10 @@
|
|||||||
"supprimerLeClub.msg": "Are you sure you want to delete this club?",
|
"supprimerLeClub.msg": "Are you sure you want to delete this club?",
|
||||||
"supprimerLeCompte": "Delete account",
|
"supprimerLeCompte": "Delete account",
|
||||||
"supprimerLeCompte.msg": "Are you sure you want to delete this account?",
|
"supprimerLeCompte.msg": "Are you sure you want to delete this account?",
|
||||||
|
"sword.none": "$t(sans) / $t(nonDéfinie)",
|
||||||
|
"sword.oneHand": "One hand",
|
||||||
|
"sword.saber": "Saber",
|
||||||
|
"sword.twoHand": "Two hands",
|
||||||
"sélectionEnéquipeDeFrance": "Selection in the French team",
|
"sélectionEnéquipeDeFrance": "Selection in the French team",
|
||||||
"sélectionner...": "Select...",
|
"sélectionner...": "Select...",
|
||||||
"toast.edit.error": "Failed to save changes",
|
"toast.edit.error": "Failed to save changes",
|
||||||
|
|||||||
@ -102,6 +102,7 @@
|
|||||||
"supprimer": "Supprimer",
|
"supprimer": "Supprimer",
|
||||||
"sélectionneLesModesDaffichage": "Sélectionne les modes d'affichage",
|
"sélectionneLesModesDaffichage": "Sélectionne les modes d'affichage",
|
||||||
"sélectionner": "Sélectionner",
|
"sélectionner": "Sélectionner",
|
||||||
|
"team": "Équipe",
|
||||||
"terminé": "Terminé",
|
"terminé": "Terminé",
|
||||||
"texteCopiéDansLePresse": "Texte copié dans le presse-papier ! Collez-le dans une balise HTML sur votre WordPress.",
|
"texteCopiéDansLePresse": "Texte copié dans le presse-papier ! Collez-le dans une balise HTML sur votre WordPress.",
|
||||||
"toast.createCategory.error": "Erreur lors de la création de la catégorie",
|
"toast.createCategory.error": "Erreur lors de la création de la catégorie",
|
||||||
@ -113,6 +114,9 @@
|
|||||||
"toast.matchs.create.error": "Erreur lors de la création des matchs.",
|
"toast.matchs.create.error": "Erreur lors de la création des matchs.",
|
||||||
"toast.matchs.create.pending": "Création des matchs en cours...",
|
"toast.matchs.create.pending": "Création des matchs en cours...",
|
||||||
"toast.matchs.create.success": "Matchs créés avec succès.",
|
"toast.matchs.create.success": "Matchs créés avec succès.",
|
||||||
|
"toast.team.update.error": "Erreur lors de la mise à jour de l'équipe",
|
||||||
|
"toast.team.update.pending": "Mise à jour de l'équipe...",
|
||||||
|
"toast.team.update.success": "Équipe mise à jour !",
|
||||||
"toast.updateCategory.error": "Erreur lors de la mise à jour de la catégorie",
|
"toast.updateCategory.error": "Erreur lors de la mise à jour de la catégorie",
|
||||||
"toast.updateCategory.pending": "Mise à jour de la catégorie...",
|
"toast.updateCategory.pending": "Mise à jour de la catégorie...",
|
||||||
"toast.updateCategory.success": "Catégorie mise à jour !",
|
"toast.updateCategory.success": "Catégorie mise à jour !",
|
||||||
@ -125,12 +129,8 @@
|
|||||||
"toast.updateTrees.init.success": "Arbres créés !",
|
"toast.updateTrees.init.success": "Arbres créés !",
|
||||||
"toast.updateTrees.pending": "Mise à jour des arbres du tournoi...",
|
"toast.updateTrees.pending": "Mise à jour des arbres du tournoi...",
|
||||||
"toast.updateTrees.success": "Arbres mis à jour !",
|
"toast.updateTrees.success": "Arbres mis à jour !",
|
||||||
"toast.team.update.error": "Erreur lors de la mise à jour de l'équipe",
|
|
||||||
"toast.team.update.pending": "Mise à jour de l'équipe...",
|
|
||||||
"toast.team.update.success": "Équipe mise à jour !",
|
|
||||||
"tournoi": "Tournoi",
|
"tournoi": "Tournoi",
|
||||||
"tournois": "Tournois",
|
"tournois": "Tournois",
|
||||||
"team": "Équipe",
|
|
||||||
"tousLesMatchs": "Tous les matchs",
|
"tousLesMatchs": "Tous les matchs",
|
||||||
"toutConserver": "Tout conserver",
|
"toutConserver": "Tout conserver",
|
||||||
"ttm.admin.obs": "Clique court : Télécharger les ressources. Clique long : Créer la configuration obs",
|
"ttm.admin.obs": "Clique court : Télécharger les ressources. Clique long : Créer la configuration obs",
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
{
|
{
|
||||||
"(optionnelle)": "(optionnelle)",
|
"(optionnelle)": "(optionnelle)",
|
||||||
"---SansClub---": "--- sans club ---",
|
"---SansClub---": "--- sans club ---",
|
||||||
"---ToutLesClubs---": "--- tout les clubs ---",
|
"---TousLesAges---": "--- tous les ages ---",
|
||||||
|
"---ToutLesClubs---": "--- tous les clubs ---",
|
||||||
"---ToutLesPays---": "--- tout les pays ---",
|
"---ToutLesPays---": "--- tout les pays ---",
|
||||||
"---TouteLesCatégories---": "--- toute les catégories ---",
|
"---TouteLesCatégories---": "--- toute les catégories ---",
|
||||||
"--NonLicencier--": "-- Non licencier --",
|
"--NonLicencier--": "-- Non licencier --",
|
||||||
"--SélectionnerCatégorie--": "-- Sélectionner catégorie --",
|
"--SélectionnerCatégorie--": "-- Sélectionner catégorie --",
|
||||||
"1Catégorie": "+1 catégorie",
|
"1Catégorie": "+1 catégorie",
|
||||||
"2Catégorie": "+2 catégorie",
|
"2Catégorie": "+2 catégorie",
|
||||||
|
"LesModificationsNontEnregistrer": "/!\\ Les modifications n'ont pas encore été enregistré, cliqué sur enregistrer /!\\",
|
||||||
"activer": "Activer",
|
"activer": "Activer",
|
||||||
"admin": "Administration",
|
"admin": "Administration",
|
||||||
"administrateur": "Administrateur",
|
"administrateur": "Administrateur",
|
||||||
@ -81,11 +83,14 @@
|
|||||||
"ajouterUnClub": "Ajouter un club",
|
"ajouterUnClub": "Ajouter un club",
|
||||||
"ajouterUnMembre": "Ajouter un membre",
|
"ajouterUnMembre": "Ajouter un membre",
|
||||||
"all_season": "--- tout les saisons ---",
|
"all_season": "--- tout les saisons ---",
|
||||||
|
"arme": "Arme",
|
||||||
"au": "au",
|
"au": "au",
|
||||||
"aucun": "Aucun",
|
"aucun": "Aucun",
|
||||||
"aucunMembreSélectionné": "Aucun membre sélectionné",
|
"aucunMembreSélectionné": "Aucun membre sélectionné",
|
||||||
|
"aucuneCatégorieDisponible": "Aucune catégorie disponible pour le moment.",
|
||||||
"back": "« retour",
|
"back": "« retour",
|
||||||
"blason": "Blason",
|
"blason": "Blason",
|
||||||
|
"bouclier": "Bouclier",
|
||||||
"bureau": "Bureau",
|
"bureau": "Bureau",
|
||||||
"button.accepter": "Accepter",
|
"button.accepter": "Accepter",
|
||||||
"button.ajouter": "Ajouter",
|
"button.ajouter": "Ajouter",
|
||||||
@ -93,7 +98,6 @@
|
|||||||
"button.appliquer": "Appliquer",
|
"button.appliquer": "Appliquer",
|
||||||
"button.confirmer": "Confirmer",
|
"button.confirmer": "Confirmer",
|
||||||
"button.créer": "Créer",
|
"button.créer": "Créer",
|
||||||
"button.enregister": "Enregister",
|
|
||||||
"button.enregistrer": "Enregistrer",
|
"button.enregistrer": "Enregistrer",
|
||||||
"button.fermer": "Fermer",
|
"button.fermer": "Fermer",
|
||||||
"button.modifier": "Modifier",
|
"button.modifier": "Modifier",
|
||||||
@ -115,6 +119,7 @@
|
|||||||
"cat.vétéran2": "Vétéran 2",
|
"cat.vétéran2": "Vétéran 2",
|
||||||
"categorie": "categorie",
|
"categorie": "categorie",
|
||||||
"catégorie": "Catégorie",
|
"catégorie": "Catégorie",
|
||||||
|
"catégorieàAjouter": "Catégorie à ajouter",
|
||||||
"certificatMédical": "Certificat médical",
|
"certificatMédical": "Certificat médical",
|
||||||
"chargement...": "Chargement...",
|
"chargement...": "Chargement...",
|
||||||
"chargerLexcel": "Charger l'Excel",
|
"chargerLexcel": "Charger l'Excel",
|
||||||
@ -249,6 +254,7 @@
|
|||||||
"compte": "Compte",
|
"compte": "Compte",
|
||||||
"compétition": "Compétition",
|
"compétition": "Compétition",
|
||||||
"configuration": "Configuration",
|
"configuration": "Configuration",
|
||||||
|
"configurationDeLaCatégorie": "Configuration de la catégorie",
|
||||||
"conserverLancienEmail": "Conserver l'ancien email",
|
"conserverLancienEmail": "Conserver l'ancien email",
|
||||||
"contactAdministratif": "Contact administratif",
|
"contactAdministratif": "Contact administratif",
|
||||||
"contactInterne": "Contact interne",
|
"contactInterne": "Contact interne",
|
||||||
@ -274,6 +280,8 @@
|
|||||||
"donnéesAdministratives": "Données administratives",
|
"donnéesAdministratives": "Données administratives",
|
||||||
"du": "Du",
|
"du": "Du",
|
||||||
"dun": "d'un",
|
"dun": "d'un",
|
||||||
|
"duréePause": "Durée pause",
|
||||||
|
"duréeRound": "Durée round",
|
||||||
"définirLidDuCompte": "Définir l'id du compte",
|
"définirLidDuCompte": "Définir l'id du compte",
|
||||||
"editionDeL'affiliation": "Edition de l'affiliation",
|
"editionDeL'affiliation": "Edition de l'affiliation",
|
||||||
"editionDeLaDemande": "Edition de la demande ",
|
"editionDeLaDemande": "Edition de la demande ",
|
||||||
@ -474,6 +482,7 @@
|
|||||||
"permission": "Permission",
|
"permission": "Permission",
|
||||||
"photos": "Photos",
|
"photos": "Photos",
|
||||||
"prenom": "Prénom",
|
"prenom": "Prénom",
|
||||||
|
"protectionObligatoire": "Protection obligatoire",
|
||||||
"prénomEtNom": "Prénom et nom",
|
"prénomEtNom": "Prénom et nom",
|
||||||
"rechercher": "Rechercher",
|
"rechercher": "Rechercher",
|
||||||
"rechercher...": "Rechercher...",
|
"rechercher...": "Rechercher...",
|
||||||
@ -494,8 +503,15 @@
|
|||||||
"role.vise-secrétaire": "Vise-Secrétaire",
|
"role.vise-secrétaire": "Vise-Secrétaire",
|
||||||
"role.vise-trésorier": "Vise-Trésorier",
|
"role.vise-trésorier": "Vise-Trésorier",
|
||||||
"saison": "Saison",
|
"saison": "Saison",
|
||||||
|
"sans": "Sans",
|
||||||
"secrétariatsDeLice": "Secrétariats de lice",
|
"secrétariatsDeLice": "Secrétariats de lice",
|
||||||
"selectionner...": "Sélectionner...",
|
"selectionner...": "Sélectionner...",
|
||||||
|
"shield.buckler": "Bocle",
|
||||||
|
"shield.none": "$t(sans) / $t(nonDéfinie)",
|
||||||
|
"shield.round": "Rond",
|
||||||
|
"shield.standard": "Standard",
|
||||||
|
"shield.teardrop": "Larme",
|
||||||
|
"siDisponiblePourLaCatégorieDages": "Si disponible pour la catégorie d'ages",
|
||||||
"siretOuRna": "SIRET ou RNA",
|
"siretOuRna": "SIRET ou RNA",
|
||||||
"stats": "Statistiques",
|
"stats": "Statistiques",
|
||||||
"statue": "Statue",
|
"statue": "Statue",
|
||||||
@ -505,6 +521,10 @@
|
|||||||
"supprimerLeClub.msg": "Êtes-vous sûr de vouloir supprimer ce club ?",
|
"supprimerLeClub.msg": "Êtes-vous sûr de vouloir supprimer ce club ?",
|
||||||
"supprimerLeCompte": "Supprimer le compte",
|
"supprimerLeCompte": "Supprimer le compte",
|
||||||
"supprimerLeCompte.msg": "Êtes-vous sûr de vouloir supprimer ce compte ?",
|
"supprimerLeCompte.msg": "Êtes-vous sûr de vouloir supprimer ce compte ?",
|
||||||
|
"sword.none": "$t(sans) / $t(nonDéfinie)",
|
||||||
|
"sword.oneHand": "Une main",
|
||||||
|
"sword.saber": "Sabre",
|
||||||
|
"sword.twoHand": "Deux mains",
|
||||||
"sélectionEnéquipeDeFrance": "Sélection en équipe de France",
|
"sélectionEnéquipeDeFrance": "Sélection en équipe de France",
|
||||||
"sélectionner...": "Sélectionner...",
|
"sélectionner...": "Sélectionner...",
|
||||||
"toast.edit.error": "Échec de l'enregistrement des modifications",
|
"toast.edit.error": "Échec de l'enregistrement des modifications",
|
||||||
|
|||||||
99
src/main/webapp/src/components/ProtectionSelector.jsx
Normal file
99
src/main/webapp/src/components/ProtectionSelector.jsx
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
|
||||||
|
const ProtectionSelector = ({mandatoryProtection = 0, setMandatoryProtection = () => {} }) => {
|
||||||
|
const toggle = (bit) => {
|
||||||
|
setMandatoryProtection(v => (v & bit ? v & ~bit : v | bit));
|
||||||
|
};
|
||||||
|
|
||||||
|
const isOn = (bit) => (mandatoryProtection & bit) !== 0;
|
||||||
|
const color = (bit) => (isOn(bit) ? "#4ade80" : "#e5e7eb");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<svg width="200" height="420" viewBox="0 0 160 320">
|
||||||
|
<rect
|
||||||
|
width="160" height="320"
|
||||||
|
fill="#f9fafb00"
|
||||||
|
stroke="#d1d5db"
|
||||||
|
strokeWidth="2"
|
||||||
|
rx="10"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Head */}
|
||||||
|
<ellipse
|
||||||
|
cx="80" cy="35" rx="20" ry="22"
|
||||||
|
fill={color(1)}
|
||||||
|
onClick={() => toggle(1)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Throat / Neck */}
|
||||||
|
<ellipse
|
||||||
|
cx="80" cy="65" rx="12" ry="8"
|
||||||
|
fill={color(2)}
|
||||||
|
onClick={() => toggle(2)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Torso */}
|
||||||
|
<ellipse
|
||||||
|
cx="80" cy="118" rx="30" ry="45"
|
||||||
|
fill={color(4)}
|
||||||
|
onClick={() => toggle(4)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Arms */}
|
||||||
|
<ellipse
|
||||||
|
cx="38" cy="118" rx="12" ry="40"
|
||||||
|
fill={color(8)}
|
||||||
|
onClick={() => toggle(8)}
|
||||||
|
/>
|
||||||
|
<ellipse
|
||||||
|
cx="122" cy="118" rx="12" ry="40"
|
||||||
|
fill={color(8)}
|
||||||
|
onClick={() => toggle(8)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hands */}
|
||||||
|
<ellipse
|
||||||
|
cx="38" cy="170" rx="10" ry="12"
|
||||||
|
fill={color(16)}
|
||||||
|
onClick={() => toggle(16)}
|
||||||
|
/>
|
||||||
|
<ellipse
|
||||||
|
cx="122" cy="170" rx="10" ry="12"
|
||||||
|
fill={color(16)}
|
||||||
|
onClick={() => toggle(16)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Legs */}
|
||||||
|
<ellipse
|
||||||
|
cx="65" cy="230" rx="14" ry="55"
|
||||||
|
fill={color(64)}
|
||||||
|
onClick={() => toggle(64)}
|
||||||
|
/>
|
||||||
|
<ellipse
|
||||||
|
cx="95" cy="230" rx="14" ry="55"
|
||||||
|
fill={color(64)}
|
||||||
|
onClick={() => toggle(64)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Groin */}
|
||||||
|
<ellipse
|
||||||
|
cx="80" cy="170" rx="20" ry="10"
|
||||||
|
fill={color(32)}
|
||||||
|
onClick={() => toggle(32)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Feet */}
|
||||||
|
<ellipse
|
||||||
|
cx="65" cy="295" rx="16" ry="8"
|
||||||
|
fill="#f0f0f0"
|
||||||
|
/>
|
||||||
|
<ellipse
|
||||||
|
cx="95" cy="295" rx="16" ry="8"
|
||||||
|
fill="#f0f0f0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProtectionSelector;
|
||||||
@ -6,12 +6,23 @@ import {CheckField, OptionField, TextField} from "../../components/MemberCustomF
|
|||||||
import {ClubSelect} from "../../components/ClubSelect.jsx";
|
import {ClubSelect} from "../../components/ClubSelect.jsx";
|
||||||
import {ConfirmDialog} from "../../components/ConfirmDialog.jsx";
|
import {ConfirmDialog} from "../../components/ConfirmDialog.jsx";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
import {apiAxios, getToastMessage} from "../../utils/Tools.js";
|
import {
|
||||||
import {useEffect, useReducer, useState} from "react";
|
apiAxios,
|
||||||
|
CatList,
|
||||||
|
getCatName, getShieldTypeName,
|
||||||
|
getSwordTypeName,
|
||||||
|
getToastMessage,
|
||||||
|
ShieldList,
|
||||||
|
sortCategories,
|
||||||
|
SwordList,
|
||||||
|
timePrint
|
||||||
|
} from "../../utils/Tools.js";
|
||||||
|
import React, {useEffect, useReducer, useState} from "react";
|
||||||
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
|
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {faAdd, faTrashCan} from "@fortawesome/free-solid-svg-icons";
|
import {faAdd, faTrashCan} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {Trans, useTranslation} from "react-i18next";
|
import {Trans, useTranslation} from "react-i18next";
|
||||||
|
import ProtectionSelector from "../../components/ProtectionSelector.jsx";
|
||||||
|
|
||||||
export function CompetitionEdit() {
|
export function CompetitionEdit() {
|
||||||
const {id} = useParams()
|
const {id} = useParams()
|
||||||
@ -190,10 +201,10 @@ function ContentSAFCAAndInternal({data2, type = "SAFCA"}) {
|
|||||||
}}><FontAwesomeIcon icon={faAdd}/></button>
|
}}><FontAwesomeIcon icon={faAdd}/></button>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
<div className="row" style={{marginTop: "1em"}}>
|
||||||
<div className="row mb-3">
|
<div className="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||||
<div className="d-grid gap-2 d-md-flex justify-content-md-end">
|
<button type="submit" className="btn btn-primary">{t('button.enregistrer')}</button>
|
||||||
<button type="submit" className="btn btn-primary">{t('button.enregistrer')}</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -205,6 +216,9 @@ function ContentSAFCAAndInternal({data2, type = "SAFCA"}) {
|
|||||||
function Content({data}) {
|
function Content({data}) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [registerMode, setRegisterMode] = useState(data.registerMode || "FREE");
|
const [registerMode, setRegisterMode] = useState(data.registerMode || "FREE");
|
||||||
|
const [modaleState, setModaleState] = useState({})
|
||||||
|
const [presets, setPresets] = useState(data.presets || []);
|
||||||
|
const [presetChange, setPresetChange] = useState(false)
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
@ -227,6 +241,7 @@ function Content({data}) {
|
|||||||
out['startRegister'] = event.target.startRegister?.value
|
out['startRegister'] = event.target.startRegister?.value
|
||||||
out['endRegister'] = event.target.endRegister?.value
|
out['endRegister'] = event.target.endRegister?.value
|
||||||
out['registerMode'] = registerMode
|
out['registerMode'] = registerMode
|
||||||
|
out['presets'] = presets
|
||||||
|
|
||||||
if (out['registerMode'] === "HELLOASSO") {
|
if (out['registerMode'] === "HELLOASSO") {
|
||||||
out['data3'] = event.target.data3?.value
|
out['data3'] = event.target.data3?.value
|
||||||
@ -277,14 +292,17 @@ function Content({data}) {
|
|||||||
toast.promise(
|
toast.promise(
|
||||||
apiAxios.post(`/competition`, out), getToastMessage("comp.toast.save")
|
apiAxios.post(`/competition`, out), getToastMessage("comp.toast.save")
|
||||||
).then(data => {
|
).then(data => {
|
||||||
|
setPresetChange(false)
|
||||||
console.log(data.data)
|
console.log(data.data)
|
||||||
if (data.data.id !== undefined)
|
if (data.data.id !== undefined)
|
||||||
navigate("/competition/" + data.data.id)
|
navigate("/competition/" + data.data.id)
|
||||||
|
if (data.data.presets !== undefined)
|
||||||
|
setPresets(data.data.presets)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return <form onSubmit={handleSubmit}>
|
return <>
|
||||||
<div className="card mb-4">
|
<form onSubmit={handleSubmit} className="card mb-4">
|
||||||
<input name="id" value={data.id || ""} readOnly hidden/>
|
<input name="id" value={data.id || ""} readOnly hidden/>
|
||||||
<div className="card-header">{data.id ? t('comp.editionCompétition') : t('comp.créationCompétition')}</div>
|
<div className="card-header">{data.id ? t('comp.editionCompétition') : t('comp.créationCompétition')}</div>
|
||||||
<div className="card-body text-center">
|
<div className="card-body text-center">
|
||||||
@ -340,6 +358,40 @@ function Content({data}) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="accordion-item">
|
||||||
|
<h2 className="accordion-header">
|
||||||
|
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFour"
|
||||||
|
aria-expanded="false" aria-controls="collapseFour">
|
||||||
|
Catégories proposées
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapseFour" className="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||||
|
<div className="accordion-body" style={{textAlign: "left"}}>
|
||||||
|
<div className="list-group">
|
||||||
|
{presets.sort((a, b) => a.name.localeCompare(b.name)).map((preset) =>
|
||||||
|
<a key={preset.id} className="list-group-item list-group-item-action" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#catModal" onClick={() => setModaleState(preset)}>
|
||||||
|
<span style={{margin: "0 0.25em 0 0"}}>{preset.name}</span>
|
||||||
|
{preset.categories.sort(sortCategories).map((cat, index) =>
|
||||||
|
<span key={index} className="badge text-bg-secondary"
|
||||||
|
style={{margin: "0 0.25em"}}>{getCatName(cat)}</span>)}
|
||||||
|
</a>)}
|
||||||
|
</div>
|
||||||
|
<div className="row" style={{marginTop: "1em"}}>
|
||||||
|
<div className="col-auto"
|
||||||
|
style={{color: "red"}}>{presetChange && t('LesModificationsNontEnregistrer')}</div>
|
||||||
|
<div className="col" style={{textAlign: "right"}}>
|
||||||
|
<button type="button" className="btn btn-success" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#catModal"
|
||||||
|
onClick={() => setModaleState({id: Math.min(...presets.map(p => p.id), 0) - 1})}>
|
||||||
|
<FontAwesomeIcon icon={faAdd}/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="accordion-item">
|
<div className="accordion-item">
|
||||||
<h2 className="accordion-header">
|
<h2 className="accordion-header">
|
||||||
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree"
|
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree"
|
||||||
@ -404,14 +456,162 @@ function Content({data}) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="row" style={{marginTop: "1em"}}>
|
||||||
|
<div className="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||||
|
<button type="submit" className="btn btn-primary">{t('button.enregistrer')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
<div className="row mb-3">
|
<div className="modal fade" id="catModal" tabIndex="-1" aria-labelledby="catModalLabel" aria-hidden="true">
|
||||||
<div className="d-grid gap-2 d-md-flex justify-content-md-end">
|
<div className="modal-dialog modal-dialog-scrollable modal-lg modal-fullscreen-lg-down">
|
||||||
<button type="submit" className="btn btn-primary">{t('button.enregistrer')}</button>
|
<div className="modal-content">
|
||||||
|
<CatModalContent setPresets={setPresets} setPresetChange={setPresetChange} state={modaleState}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
function CatModalContent({setPresets, setPresetChange, state}) {
|
||||||
|
const [name, setName] = useState(state.name || "")
|
||||||
|
const [sword, setSword] = useState(state.sword || "NONE")
|
||||||
|
const [shield, setShield] = useState(state.shield || "NONE")
|
||||||
|
const [time, setTime] = useState(timePrint(state.roundDuration || 90000))
|
||||||
|
const [pause, setPause] = useState(timePrint(state.pauseDuration || 60000))
|
||||||
|
const [cats, setCats] = useState(state.categories || [])
|
||||||
|
const [mandatoryProtection, setMandatoryProtection] = useState(state.mandatoryProtection || 33)
|
||||||
|
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setName(state.name || "")
|
||||||
|
setSword(state.sword || "NONE")
|
||||||
|
setShield(state.shield || "NONE")
|
||||||
|
setTime(timePrint(state.roundDuration || 90000))
|
||||||
|
setPause(timePrint(state.pauseDuration || 60000))
|
||||||
|
setCats(state.categories || [])
|
||||||
|
setMandatoryProtection(state.mandatoryProtection || 33)
|
||||||
|
}, [state]);
|
||||||
|
|
||||||
|
const setCat = (e, cat) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
if (!cats.includes(cat)) {
|
||||||
|
setCats([...cats, cat])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setCats(cats.filter(c => c !== cat))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isCatSelected = (cat) => cats.includes(cat)
|
||||||
|
|
||||||
|
const parseTime = (str) => {
|
||||||
|
const parts = str.split(":").map(part => parseInt(part, 10));
|
||||||
|
if (parts.length === 1) {
|
||||||
|
return parts[0] * 1000;
|
||||||
|
} else if (parts.length === 2) {
|
||||||
|
return (parts[0] * 60 + parts[1]) * 1000;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
const out = {
|
||||||
|
id: state.id,
|
||||||
|
name: name,
|
||||||
|
sword: sword,
|
||||||
|
shield: shield,
|
||||||
|
roundDuration: parseTime(time),
|
||||||
|
pauseDuration: parseTime(pause),
|
||||||
|
categories: cats,
|
||||||
|
mandatoryProtection: mandatoryProtection
|
||||||
|
}
|
||||||
|
setPresets(presets => [...presets.filter(p => p.id !== out.id), out])
|
||||||
|
setPresetChange(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRm = () => {
|
||||||
|
setPresets(presets => presets.filter(p => p.id !== state.id))
|
||||||
|
setPresetChange(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<div className="modal-header">
|
||||||
|
<h1 className="modal-title fs-5" id="CategorieModalLabel">{t('configurationDeLaCatégorie')}</h1>
|
||||||
|
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12 col-md-7 mb-3">
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<span className="input-group-text" id="categorie">{t("nom")}</span>
|
||||||
|
<input type="text" className="form-control" placeholder={t("nom")} name="name"
|
||||||
|
value={name} onChange={e => setName(e.target.value)}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<span className="input-group-text">{t('duréeRound')}</span>
|
||||||
|
<input type="text" className="form-control" placeholder="0" aria-label="Min" value={time}
|
||||||
|
onChange={e => setTime(e.target.value)}/>
|
||||||
|
<span className="input-group-text">(mm:ss)</span>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<span className="input-group-text">{t('duréePause')}</span>
|
||||||
|
<input type="text" className="form-control" placeholder="0" aria-label="Min" value={pause}
|
||||||
|
onChange={e => setPause(e.target.value)}/>
|
||||||
|
<span className="input-group-text">(mm:ss)</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<span className="input-group-text" id="sword">{t('arme')}</span>
|
||||||
|
<select className="form-select" aria-label={t('arme')} name="sword" value={sword}
|
||||||
|
onChange={e => setSword(e.target.value)}>
|
||||||
|
{SwordList.map(sword =>
|
||||||
|
<option key={sword} value={sword}>{getSwordTypeName(sword)}</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<span className="input-group-text" id="shield">{t('bouclier')}</span>
|
||||||
|
<select className="form-select" aria-label={t('bouclier')} name="shield" value={shield}
|
||||||
|
onChange={e => setShield(e.target.value)}>
|
||||||
|
{ShieldList.map(shield =>
|
||||||
|
<option key={shield} value={shield}>{getShieldTypeName(shield)}</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label htmlFor="inputState2" className="form-label">
|
||||||
|
{t('catégorie')} :
|
||||||
|
</label>
|
||||||
|
<div className="d-flex flex-wrap">
|
||||||
|
{CatList.map((cat, index) => <div key={index} className="input-group" style={{display: "contents"}}>
|
||||||
|
<div className="input-group-text">
|
||||||
|
<input className="form-check-input mt-0" type="checkbox" id={"catInput" + index} checked={isCatSelected(cat)}
|
||||||
|
aria-label={getCatName(cat)} onChange={e => setCat(e, cat)}/>
|
||||||
|
<label style={{marginLeft: "0.5em"}} htmlFor={"catInput" + index}>{getCatName(cat)}</label>
|
||||||
|
</div>
|
||||||
|
</div>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-md-5">
|
||||||
|
<div style={{textAlign: "center"}}>
|
||||||
|
<h6>{t('protectionObligatoire')} :</h6>
|
||||||
|
<ProtectionSelector mandatoryProtection={mandatoryProtection} setMandatoryProtection={setMandatoryProtection}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="button" className="btn btn-danger" data-bs-dismiss="modal" onClick={handleRm}>{t('button.supprimer')}</button>
|
||||||
|
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">{t('button.fermer')}</button>
|
||||||
|
<button type="button" className="btn btn-primary" data-bs-dismiss="modal" onClick={handleSave}>{t('button.appliquer')}</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@ import {LoadingProvider, useLoadingSwitcher} from "../../hooks/useLoading.jsx";
|
|||||||
import {useFetch} from "../../hooks/useFetch.js";
|
import {useFetch} from "../../hooks/useFetch.js";
|
||||||
import {AxiosError} from "../../components/AxiosError.jsx";
|
import {AxiosError} from "../../components/AxiosError.jsx";
|
||||||
import {ThreeDots} from "react-loader-spinner";
|
import {ThreeDots} from "react-loader-spinner";
|
||||||
import {useEffect, useReducer, useRef, useState} from "react";
|
import React, {useEffect, useReducer, useRef, useState} from "react";
|
||||||
import {apiAxios, CatList, getCatName, getToastMessage} from "../../utils/Tools.js";
|
import {apiAxios, applyOverCategory, CatList, getCatName, getToastMessage} from "../../utils/Tools.js";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
|
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
@ -19,12 +19,14 @@ export function CompetitionRegisterAdmin({source}) {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [state, dispatch] = useReducer(SimpleReducer, [])
|
const [state, dispatch] = useReducer(SimpleReducer, [])
|
||||||
const [clubFilter, setClubFilter] = useState("")
|
const [clubFilter, setClubFilter] = useState("")
|
||||||
const [catFilter, setCatFilter] = useState("")
|
const [catAgeFilter, setCatAgeFilter] = useState("")
|
||||||
|
const [catFilter, setCatFilter] = useState(-1)
|
||||||
const [modalState, setModalState] = useState({})
|
const [modalState, setModalState] = useState({})
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data, error} = useFetch(`/competition/${id}/register/${source}`, setLoading, 1)
|
const {data, error} = useFetch(`/competition/${id}/register/${source}`, setLoading, 1)
|
||||||
|
const {data: data2, error: error2} = useFetch(`/competition/${id}/categories`, setLoading, 1)
|
||||||
|
|
||||||
const sortName = (a, b) => {
|
const sortName = (a, b) => {
|
||||||
if (a.data.fname === b.data.fname) return a.data.lname.localeCompare(b.data.lname);
|
if (a.data.fname === b.data.fname) return a.data.lname.localeCompare(b.data.lname);
|
||||||
@ -43,11 +45,11 @@ export function CompetitionRegisterAdmin({source}) {
|
|||||||
return toast.promise(apiAxios.post(`/competition/${id}/register/${source}`, new_state), getToastMessage("comp.toast.register.add")
|
return toast.promise(apiAxios.post(`/competition/${id}/register/${source}`, new_state), getToastMessage("comp.toast.register.add")
|
||||||
).then((response) => {
|
).then((response) => {
|
||||||
if (response.data.error) {
|
if (response.data.error) {
|
||||||
return
|
return null;
|
||||||
}
|
}
|
||||||
dispatch({type: 'UPDATE_OR_ADD', payload: {id: response.data.id, data: response.data}})
|
dispatch({type: 'UPDATE_OR_ADD', payload: {id: response.data.id, data: response.data}})
|
||||||
dispatch({type: 'SORT', payload: sortName})
|
dispatch({type: 'SORT', payload: sortName})
|
||||||
document.getElementById("closeModal").click();
|
return response.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +64,9 @@ export function CompetitionRegisterAdmin({source}) {
|
|||||||
<div className="col-lg-9">
|
<div className="col-lg-9">
|
||||||
{data ? <div className="">
|
{data ? <div className="">
|
||||||
<MakeCentralPanel
|
<MakeCentralPanel
|
||||||
data={state.filter(s => (clubFilter.length === 0 || s.data.club.name === clubFilter) && (catFilter.length === 0 || s.data.categorie === catFilter))}
|
data={state.filter(s => (clubFilter.length === 0 || s.data.club.name === clubFilter)
|
||||||
|
&& (catAgeFilter.length === 0 || s.data.categorie === catAgeFilter)
|
||||||
|
&& (catFilter === -1 || s.data.categoriesInscrites.includes(catFilter)))}
|
||||||
dispatch={dispatch} id={id} setModalState={setModalState} source={source}/>
|
dispatch={dispatch} id={id} setModalState={setModalState} source={source}/>
|
||||||
</div> : error ? <AxiosError error={error}/> : <Def/>}
|
</div> : error ? <AxiosError error={error}/> : <Def/>}
|
||||||
</div>
|
</div>
|
||||||
@ -77,36 +81,60 @@ export function CompetitionRegisterAdmin({source}) {
|
|||||||
onClick={() => setModalState({id: -793548328091516928})}>{t('comp.ajouterUnInvité')}
|
onClick={() => setModalState({id: -793548328091516928})}>{t('comp.ajouterUnInvité')}
|
||||||
</button>
|
</button>
|
||||||
</div>}
|
</div>}
|
||||||
<QuickAdd sendRegister={sendRegister} source={source}/>
|
<QuickAdd sendRegister={sendRegister} source={source} data2={data2} error2={error2}/>
|
||||||
<div className="card mb-4">
|
<div className="card mb-4">
|
||||||
<div className="card-header">{t('filtre')}</div>
|
<div className="card-header">{t('filtre')}</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<FiltreBar data={data} clubFilter={clubFilter} setClubFilter={setClubFilter} catFilter={catFilter}
|
<FiltreBar data={data} data2={data2} clubFilter={clubFilter} setClubFilter={setClubFilter} catFilter={catFilter}
|
||||||
setCatFilter={setCatFilter} source={source}/>
|
setCatFilter={setCatFilter} catAgeFilter={catAgeFilter} setCatAgeFilter={setCatAgeFilter} source={source}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{source === "admin" && <FileOutput data={data}/>}
|
{source === "admin" && <FileOutput data={data}/>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Modal sendRegister={sendRegister} modalState={modalState} setModalState={setModalState} source={source}/>
|
<Modal data2={data2} error2={error2} sendRegister={sendRegister} modalState={modalState} setModalState={setModalState} source={source}/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function QuickAdd({sendRegister, source}) {
|
function QuickAdd({sendRegister, source, data2, error2}) {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
const [categories, setCategories] = useState([])
|
||||||
|
|
||||||
const handleAdd = (licence) => {
|
const handleAdd = (licence) => {
|
||||||
console.log("Quick add licence: " + licence)
|
|
||||||
|
|
||||||
sendRegister({
|
sendRegister({
|
||||||
licence: licence, fname: "", lname: "", weight: "", overCategory: 0, lockEdit: false, id: null
|
licence: licence,
|
||||||
|
fname: "",
|
||||||
|
lname: "",
|
||||||
|
weight: "",
|
||||||
|
overCategory: 0,
|
||||||
|
lockEdit: false,
|
||||||
|
id: null,
|
||||||
|
quick: true,
|
||||||
|
categoriesInscrites: categories
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setCategories_ = (e, catId) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
if (!categories.includes(catId)) {
|
||||||
|
setCategories([...categories, catId])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setCategories(categories.filter(c => c !== catId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return <div className="card mb-4">
|
return <div className="card mb-4">
|
||||||
<div className="card-header">{t('comp.ajoutRapide')}</div>
|
<div className="card-header">{t('comp.ajoutRapide')}</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
|
<div className="d-flex flex-wrap">
|
||||||
|
<label htmlFor="inputState2" className="form-label align-self-center" style={{margin: "0 0.5em 0 0"}}>
|
||||||
|
{t('catégorieàAjouter')}<br/> <small>({t('siDisponiblePourLaCatégorieDages')})</small>
|
||||||
|
</label>
|
||||||
|
<CategoriesList error2={error2} availableCats={data2} categories={categories} setCategories={setCategories_}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<span>{t('comp.noDeLicence')}</span>
|
<span>{t('comp.noDeLicence')}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -131,14 +159,14 @@ function QuickAdd({sendRegister, source}) {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{source === "club" && <LoadingProvider>
|
{source === "club" && <LoadingProvider>
|
||||||
<SearchMember sendRegister={sendRegister}/>
|
<SearchMember sendRegister={sendRegister} categories={categories}/>
|
||||||
</LoadingProvider>}
|
</LoadingProvider>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function SearchMember({sendRegister}) {
|
function SearchMember({sendRegister, categories}) {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data, error} = useFetch(`/club/members`, setLoading, 1)
|
const {data, error} = useFetch(`/club/members`, setLoading, 1)
|
||||||
const [suggestions, setSuggestions] = useState([])
|
const [suggestions, setSuggestions] = useState([])
|
||||||
@ -158,7 +186,9 @@ function SearchMember({sendRegister}) {
|
|||||||
weight: "",
|
weight: "",
|
||||||
overCategory: 0,
|
overCategory: 0,
|
||||||
lockEdit: false,
|
lockEdit: false,
|
||||||
id: null
|
id: null,
|
||||||
|
quick: true,
|
||||||
|
categoriesInscrites: categories
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,9 +314,33 @@ const AutoCompleteInput = ({suggestions = [], handleAdd}) => {
|
|||||||
</div>);
|
</div>);
|
||||||
};
|
};
|
||||||
|
|
||||||
function Modal({sendRegister, modalState, setModalState, source}) {
|
function CategoriesList({error2, availableCats, fistCatInput, categories, setCategories}) {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
return <>
|
||||||
|
{error2 ? <AxiosError error={error2}/> : <>
|
||||||
|
{availableCats && availableCats.length === 0 && <div>{t('aucuneCatégorieDisponible')}</div>}
|
||||||
|
{availableCats && availableCats.map((cat, index) =>
|
||||||
|
<div key={cat.id} className="input-group"
|
||||||
|
style={{display: "contents"}}>
|
||||||
|
<div className="input-group-text">
|
||||||
|
<input ref={index === 0 ? fistCatInput : undefined} className="form-check-input mt-0" type="checkbox"
|
||||||
|
id={"categoriesInput" + index} checked={categories.includes(cat.id)} aria-label={cat.name}
|
||||||
|
onChange={e => setCategories(e, cat.id)}/>
|
||||||
|
<label style={{marginLeft: "0.5em"}} htmlFor={"categoriesInput" + index}>{cat.name}</label>
|
||||||
|
</div>
|
||||||
|
</div>)}
|
||||||
|
</>}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
function Modal({data2, error2, sendRegister, modalState, setModalState, source}) {
|
||||||
const country = useCountries('fr')
|
const country = useCountries('fr')
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
const closeBtn = useRef(null);
|
||||||
|
const licenceInput = useRef(null);
|
||||||
|
const nameInput = useRef(null);
|
||||||
|
const fistCatInput = useRef(null);
|
||||||
|
const submitBtn = useRef(null);
|
||||||
|
|
||||||
const [licence, setLicence] = useState("")
|
const [licence, setLicence] = useState("")
|
||||||
const [fname, setFname] = useState("")
|
const [fname, setFname] = useState("")
|
||||||
@ -299,97 +353,125 @@ function Modal({sendRegister, modalState, setModalState, source}) {
|
|||||||
const [genre, setGenre] = useState("NA")
|
const [genre, setGenre] = useState("NA")
|
||||||
const [editMode, setEditMode] = useState(false)
|
const [editMode, setEditMode] = useState(false)
|
||||||
const [lockEdit, setLockEdit] = useState(false)
|
const [lockEdit, setLockEdit] = useState(false)
|
||||||
|
const [categories, setCategories] = useState([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(modalState)
|
setLicence(modalState?.licence ? modalState.licence : "")
|
||||||
if (!modalState) {
|
setFname(modalState?.fname ? modalState.fname : "")
|
||||||
setLicence("")
|
setLname(modalState?.lname ? modalState.lname : "")
|
||||||
setFname("")
|
setWeight(modalState?.weight ? modalState.weight : "")
|
||||||
setLname("")
|
setCat(modalState?.overCategory ? modalState.overCategory : 0)
|
||||||
setWeight("")
|
setEditMode(modalState?.licence || (modalState.fname && modalState.lname))
|
||||||
setCat(0)
|
setLockEdit(modalState?.lockEdit === undefined ? false : modalState.lockEdit)
|
||||||
setEditMode(false)
|
setClub(modalState?.club ? modalState.club.name : "")
|
||||||
setLockEdit(false)
|
setGCat(modalState?.categorie ? modalState.categorie : "")
|
||||||
setClub("")
|
setCountry_(modalState?.country ? modalState.country : "FR")
|
||||||
setGCat("")
|
setGenre(modalState?.genre ? modalState.genre : "NA")
|
||||||
setCountry_("FR")
|
setCategories(modalState?.categoriesInscrites ? modalState.categoriesInscrites : [])
|
||||||
setGenre("NA")
|
|
||||||
} else {
|
setTimeout(() => {
|
||||||
setLicence(modalState.licence ? modalState.licence : "")
|
if (modalState?.id === 0) {
|
||||||
setFname(modalState.fname ? modalState.fname : "")
|
licenceInput.current?.focus()
|
||||||
setLname(modalState.lname ? modalState.lname : "")
|
} else if (modalState?.id < 0) {
|
||||||
setWeight(modalState.weight ? modalState.weight : "")
|
nameInput.current?.focus()
|
||||||
setCat(modalState.overCategory ? modalState.overCategory : 0)
|
}
|
||||||
setEditMode(modalState.licence || (modalState.fname && modalState.lname))
|
}, 450)
|
||||||
setLockEdit(modalState.lockEdit)
|
|
||||||
setClub(modalState.club ? modalState.club.name : "")
|
|
||||||
setGCat(modalState.categorie ? modalState.categorie : "")
|
|
||||||
setCountry_(modalState.country ? modalState.country : "FR")
|
|
||||||
setGenre(modalState.genre ? modalState.genre : "NA")
|
|
||||||
}
|
|
||||||
}, [modalState]);
|
}, [modalState]);
|
||||||
|
|
||||||
return <div className="modal fade" id="registerModal" tabIndex="-1" aria-labelledby="registerLabel"
|
const setCategories_ = (e, catId) => {
|
||||||
aria-hidden="true">
|
if (e.target.checked) {
|
||||||
|
if (!categories.includes(catId)) {
|
||||||
|
setCategories([...categories, catId])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setCategories(categories.filter(c => c !== catId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
const new_state = {
|
||||||
|
licence: Number.isInteger(licence) ? licence : licence.trim(),
|
||||||
|
fname: fname.trim(),
|
||||||
|
lname: lname.trim(),
|
||||||
|
weight: weight,
|
||||||
|
overCategory: cat,
|
||||||
|
lockEdit: lockEdit,
|
||||||
|
categoriesInscrites: categories,
|
||||||
|
id: modalState.id !== 0 ? modalState.id : null
|
||||||
|
}
|
||||||
|
if (modalState.id < 0) {
|
||||||
|
new_state.licence = -1
|
||||||
|
new_state.categorie = gcat
|
||||||
|
new_state.club = club
|
||||||
|
new_state.country = country_
|
||||||
|
new_state.genre = genre
|
||||||
|
}
|
||||||
|
sendRegister(new_state)
|
||||||
|
.then(data => {
|
||||||
|
if (!data) return;
|
||||||
|
setModalState(data)
|
||||||
|
if (editMode || data.id < 0) {
|
||||||
|
closeBtn.current.click()
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (fistCatInput.current) {
|
||||||
|
fistCatInput.current.focus()
|
||||||
|
} else {
|
||||||
|
submitBtn.current.focus()
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const currenCat = gcat !== "" ? applyOverCategory(gcat, cat) : "";
|
||||||
|
const availableCats = data2 ? (currenCat !== "" ? data2.filter(c => c.categories.includes(currenCat)) : data2).sort((a, b) => a.name.localeCompare(b.name)) : []
|
||||||
|
if (availableCats.length === 0) {
|
||||||
|
if (fistCatInput.current) {
|
||||||
|
fistCatInput.current = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="modal fade" id="registerModal" tabIndex="-1" aria-labelledby="registerLabel" aria-hidden="true">
|
||||||
<div className="modal-dialog">
|
<div className="modal-dialog">
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
<form onSubmit={e => {
|
<div className="modal-header">
|
||||||
e.preventDefault()
|
<h1 className="modal-title fs-5"
|
||||||
const new_state = {
|
id="registerLabel">{editMode ? t('modification') : t('ajout')} {t('dun')} {modalState.id >= 0 ? t('combattant') : t('invité')}</h1>
|
||||||
licence: Number.isInteger(licence) ? licence : licence.trim(),
|
<button ref={closeBtn} type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
fname: fname.trim(),
|
</div>
|
||||||
lname: lname.trim(),
|
<div className="modal-body">
|
||||||
weight: weight,
|
{modalState.id < 0 &&
|
||||||
overCategory: cat,
|
<div className="mb-2">{t('comp.modal.text1')}</div>}
|
||||||
lockEdit: lockEdit,
|
<div className="card" style={{marginBottom: "1em"}}>
|
||||||
id: modalState.id !== 0 ? modalState.id : null
|
<div className="card-header">{modalState.id >= 0 ? t('comp.modal.recherche') : t('comp.modal.information')}</div>
|
||||||
}
|
<div className="card-body">
|
||||||
if (modalState.id < 0) {
|
<div className="row" hidden={modalState.id < 0}>
|
||||||
new_state.licence = -1
|
<div className="col">
|
||||||
new_state.categorie = gcat
|
<input ref={licenceInput} type="number" min={0} step={1} className="form-control"
|
||||||
new_state.club = club
|
placeholder={t("comp.noDeLicence")} name="licence" value={licence}
|
||||||
new_state.country = country_
|
onChange={e => setLicence(e.target.value)} disabled={editMode}
|
||||||
new_state.genre = genre
|
onKeyUp={e => e.key === "Enter" ? handleSubmit(e) : undefined}/>
|
||||||
}
|
|
||||||
sendRegister(new_state)
|
|
||||||
.then(() => {
|
|
||||||
setModalState(new_state)
|
|
||||||
})
|
|
||||||
}}>
|
|
||||||
<div className="modal-header">
|
|
||||||
<h1 className="modal-title fs-5"
|
|
||||||
id="registerLabel">{editMode ? t('modification') : t('ajout')} {t('dun')} {modalState.id >= 0 ? t('combattant') : t('invité')}</h1>
|
|
||||||
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div className="modal-body">
|
|
||||||
{modalState.id < 0 &&
|
|
||||||
<div className="mb-2">{t('comp.modal.text1')}</div>}
|
|
||||||
<div className="card" style={{marginBottom: "1em"}}>
|
|
||||||
<div className="card-header">{modalState.id >= 0 ? t('comp.modal.recherche') : t('comp.modal.information')}</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<div className="row" hidden={modalState.id < 0}>
|
|
||||||
<div className="col">
|
|
||||||
<input type="number" min={0} step={1} className="form-control" placeholder={t("comp.noDeLicence")}
|
|
||||||
name="licence"
|
|
||||||
value={licence} onChange={e => setLicence(e.target.value)} disabled={editMode}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<h5 style={{textAlign: "center", marginTop: "0.25em"}} hidden={modalState.id < 0}>{t('ou')}</h5>
|
</div>
|
||||||
<div className="row">
|
<h5 style={{textAlign: "center", marginTop: "0.25em"}} hidden={modalState.id < 0}>{t('ou')}</h5>
|
||||||
<div className="col">
|
<div className="row">
|
||||||
<input type="text" className="form-control" placeholder={t('prenom')} name="fname"
|
<div className="col">
|
||||||
disabled={editMode && modalState.id >= 0}
|
<input ref={nameInput} type="text" className="form-control" placeholder={t('prenom')} name="fname"
|
||||||
value={fname} onChange={e => setFname(e.target.value)}/>
|
disabled={editMode && modalState.id >= 0}
|
||||||
</div>
|
value={fname} onChange={e => setFname(e.target.value)}/>
|
||||||
<div className="col">
|
</div>
|
||||||
<input type="text" className="form-control" placeholder={t('nom')} name="lname"
|
<div className="col">
|
||||||
disabled={editMode && modalState.id >= 0}
|
<input type="text" className="form-control" placeholder={t('nom')} name="lname"
|
||||||
value={lname} onChange={e => setLname(e.target.value)}/>
|
disabled={editMode && modalState.id >= 0} value={lname} onChange={e => setLname(e.target.value)}
|
||||||
</div>
|
onKeyUp={e => e.key === "Enter" && modalState.id >= 0 ? handleSubmit(e) : undefined}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{(editMode || modalState.id < 0) && <>
|
||||||
<div className="input-group mb-3" hidden={modalState.id >= 0}>
|
<div className="input-group mb-3" hidden={modalState.id >= 0}>
|
||||||
<span className="input-group-text" id="categorie">{t("club", {count: 1})}</span>
|
<span className="input-group-text" id="categorie">{t("club", {count: 1})}</span>
|
||||||
<input type="text" className="form-control" placeholder={t("club", {count: 1})} name="club"
|
<input type="text" className="form-control" placeholder={t("club", {count: 1})} name="club"
|
||||||
@ -451,28 +533,34 @@ function Modal({sendRegister, modalState, setModalState, source}) {
|
|||||||
onChange={e => setLockEdit(e.target.checked)}/>
|
onChange={e => setLockEdit(e.target.checked)}/>
|
||||||
<label className="form-check-label" htmlFor="switchCheckReverse">{t('comp.modal.text2')}</label>
|
<label className="form-check-label" htmlFor="switchCheckReverse">{t('comp.modal.text2')}</label>
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
|
||||||
<div className="modal-footer">
|
<div className="d-flex flex-wrap">
|
||||||
<button type="submit" className="btn btn-primary">{editMode ? t('button.modifier') : t('button.ajouter')}</button>
|
<label htmlFor="inputState2" className="form-label align-self-center" style={{margin: "0 0.5em 0 0"}}>
|
||||||
<button type="reset" className="btn btn-secondary" data-bs-dismiss="modal" id="closeModal">{t('button.annuler')}</button>
|
{t('catégorie')} :
|
||||||
</div>
|
</label>
|
||||||
</form>
|
<CategoriesList error2={error2} availableCats={availableCats} fistCatInput={fistCatInput} categories={categories}
|
||||||
|
setCategories={setCategories_}/>
|
||||||
|
</div>
|
||||||
|
</>}
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal" id="closeModal">{t('button.annuler')}</button>
|
||||||
|
<button ref={submitBtn} type="button" className="btn btn-primary"
|
||||||
|
onClick={handleSubmit}>{editMode ? t('button.modifier') : t('button.ajouter')}</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
let allClub = []
|
let allClub = []
|
||||||
let allCat = []
|
|
||||||
|
|
||||||
function FiltreBar({data, clubFilter, setClubFilter, catFilter, setCatFilter, source}) {
|
function FiltreBar({data, data2, clubFilter, setClubFilter, catFilter, setCatFilter, catAgeFilter, setCatAgeFilter, source}) {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
allClub.push(...data.map((e) => e.club?.name))
|
allClub.push(...data.map((e) => e.club?.name))
|
||||||
allClub = allClub.filter((value, index, self) => self.indexOf(value) === index).filter(value => value != null).sort()
|
allClub = allClub.filter((value, index, self) => self.indexOf(value) === index).filter(value => value != null).sort()
|
||||||
allCat.push(...data.map((e) => e.categorie))
|
|
||||||
allCat = allCat.filter((value, index, self) => self.indexOf(value) === index).filter(value => value != null).sort()
|
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
@ -485,13 +573,19 @@ function FiltreBar({data, clubFilter, setClubFilter, catFilter, setCatFilter, so
|
|||||||
</select>
|
</select>
|
||||||
</div>}
|
</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={catAgeFilter} onChange={event => setCatAgeFilter(event.target.value)}>
|
||||||
<option value="">{t('---TouteLesCatégories---')}</option>
|
<option value="">{t('---TousLesAges---')}</option>
|
||||||
{allCat && allCat.map((value, index) => {
|
{CatList && CatList.map((value, index) => {
|
||||||
return <option key={index} value={value}>{value}</option>
|
return <option key={index} value={value}>{getCatName(value)}</option>
|
||||||
})}
|
})}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<select className="form-select" value={catFilter} onChange={event => setCatFilter(Number(event.target.value))}>
|
||||||
|
<option value={-1}>{t('---TouteLesCatégories---')}</option>
|
||||||
|
{data2 && data2.map((cat) => {
|
||||||
|
return <option key={cat.id} value={cat.id}>{cat.name}</option>
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -160,7 +160,7 @@ function SelfRegister({data2}) {
|
|||||||
onClick={handleUnregister}>{t('button.seDésinscrire')}
|
onClick={handleUnregister}>{t('button.seDésinscrire')}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className="btn btn-primary" disabled={disabled}
|
<button type="button" className="btn btn-primary" disabled={disabled}
|
||||||
onClick={handleSubmit}>{t('button.enregister')}
|
onClick={handleSubmit}>{t('button.enregistrer')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -42,6 +42,32 @@ export const CatList = [
|
|||||||
"VETERAN2"
|
"VETERAN2"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export function sortCategories(catA, catB) {
|
||||||
|
const indexA = CatList.indexOf(catA);
|
||||||
|
const indexB = CatList.indexOf(catB);
|
||||||
|
|
||||||
|
if (indexA === -1 && indexB === -1) {
|
||||||
|
return 0; // Both categories are unknown, maintain their order
|
||||||
|
} else if (indexA === -1) {
|
||||||
|
return 1; // catA is unknown, place it after catB
|
||||||
|
} else if (indexB === -1) {
|
||||||
|
return -1; // catB is unknown, place it after catA
|
||||||
|
} else {
|
||||||
|
return indexA - indexB; // Both categories are known, sort by their indices
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyOverCategory(cat, overCat) {
|
||||||
|
const catIndex = CatList.indexOf(cat) + overCat;
|
||||||
|
if (catIndex < 0) {
|
||||||
|
return CatList[0];
|
||||||
|
} else if (catIndex >= CatList.length) {
|
||||||
|
return CatList[CatList.length - 1];
|
||||||
|
} else {
|
||||||
|
return CatList[catIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getCategoryFormBirthDate(birth_date, currentDate = new Date()) {
|
export function getCategoryFormBirthDate(birth_date, currentDate = new Date()) {
|
||||||
const currentSaison = getSaison(currentDate)
|
const currentSaison = getSaison(currentDate)
|
||||||
const birthYear = birth_date.getFullYear()
|
const birthYear = birth_date.getFullYear()
|
||||||
@ -111,6 +137,53 @@ export function getCatName(cat) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const SwordList = [
|
||||||
|
"NONE",
|
||||||
|
"ONE_HAND",
|
||||||
|
"TWO_HAND",
|
||||||
|
"SABER"
|
||||||
|
]
|
||||||
|
|
||||||
|
export function getSwordTypeName(type) {
|
||||||
|
switch (type) {
|
||||||
|
case "NONE":
|
||||||
|
return i18n.t('sword.none');
|
||||||
|
case "ONE_HAND":
|
||||||
|
return i18n.t('sword.oneHand');
|
||||||
|
case "TWO_HAND":
|
||||||
|
return i18n.t('sword.twoHand');
|
||||||
|
case "SABER":
|
||||||
|
return i18n.t('sword.saber');
|
||||||
|
default:
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ShieldList = [
|
||||||
|
"NONE",
|
||||||
|
"STANDARD",
|
||||||
|
"ROUND",
|
||||||
|
"TEARDROP",
|
||||||
|
"BUCKLER"
|
||||||
|
]
|
||||||
|
|
||||||
|
export function getShieldTypeName(type) {
|
||||||
|
switch (type) {
|
||||||
|
case "NONE":
|
||||||
|
return i18n.t('shield.none');
|
||||||
|
case "STANDARD":
|
||||||
|
return i18n.t('shield.standard');
|
||||||
|
case "ROUND":
|
||||||
|
return i18n.t('shield.round');
|
||||||
|
case "TEARDROP":
|
||||||
|
return i18n.t('shield.teardrop');
|
||||||
|
case "BUCKLER":
|
||||||
|
return i18n.t('shield.buckler');
|
||||||
|
default:
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getToastMessage(msgKey, ns = 'common') {
|
export function getToastMessage(msgKey, ns = 'common') {
|
||||||
return {
|
return {
|
||||||
pending: i18n.t(msgKey + '.pending', {ns}),
|
pending: i18n.t(msgKey + '.pending', {ns}),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user