feat: rework CatPreset for add more detail + add preset
This commit is contained in:
parent
78d22b466d
commit
d2a7e6cbac
@ -28,24 +28,30 @@ public class CatPresetModel {
|
||||
|
||||
String name = "";
|
||||
|
||||
List<Categorie> categories;
|
||||
|
||||
long roundDuration;
|
||||
long pauseDuration;
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "category_preset_catconfig", joinColumns = @JoinColumn(name = "id_preset"))
|
||||
List<CategorieEmbeddable> categories;
|
||||
|
||||
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
|
||||
/*
|
||||
* 1 - 1 - Casque
|
||||
* 2 - 2 - Gorgerin
|
||||
* 3 - 4 - Coquille et Protection pelvienne
|
||||
* 4 - 8 - Gant main(s) armée(s)
|
||||
* 5 - 16 - Gant main bouclier
|
||||
* 6 - 32 - Plastron
|
||||
* 7 - 64 - Protection de bras armé(s)
|
||||
* 8 - 128 - Protection de bras de bouclier
|
||||
* 9 - 256 - Protection de jambes
|
||||
* 10 - 512 - Protection de genoux
|
||||
* 11 - 1024 - Protection de coudes
|
||||
* 12 - 2048 - Protection dorsale
|
||||
* 13 - 4096 - Protection de pieds
|
||||
*/
|
||||
int mandatoryProtection = 0;
|
||||
int mandatoryProtection1 = 0;
|
||||
int mandatoryProtection2 = 0;
|
||||
|
||||
@ManyToMany(mappedBy = "categoriesInscrites", fetch = FetchType.LAZY)
|
||||
private List<RegisterModel> registers = new ArrayList<>();
|
||||
@ -68,4 +74,16 @@ public class CatPresetModel {
|
||||
BUCKLER
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
|
||||
@Embeddable
|
||||
public static class CategorieEmbeddable {
|
||||
Categorie categorie;
|
||||
long roundDuration;
|
||||
long pauseDuration;
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,10 +271,9 @@ public class CompetitionService {
|
||||
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());
|
||||
presetModel.setMandatoryProtection1(preset.getMandatoryProtection1());
|
||||
presetModel.setMandatoryProtection2(preset.getMandatoryProtection2());
|
||||
}
|
||||
|
||||
// Remove deleted presets
|
||||
@ -399,7 +398,8 @@ public class CompetitionService {
|
||||
g.getCategoriesInscrites().clear();
|
||||
g.getCategoriesInscrites().addAll(cats);
|
||||
g.getCategoriesInscrites()
|
||||
.removeIf(cat -> !cat.getCategories().contains(g.getCategorie()));
|
||||
.removeIf(cat -> cat.getCategories().stream()
|
||||
.noneMatch(e -> e.getCategorie().equals(g.getCategorie())));
|
||||
}))
|
||||
.chain(model -> Panache.withTransaction(() -> competitionGuestRepository.persist(model))
|
||||
.call(r -> model.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
|
||||
@ -495,7 +495,8 @@ public class CompetitionService {
|
||||
}
|
||||
r.getCategoriesInscrites().addAll(cats);
|
||||
r.getCategoriesInscrites()
|
||||
.removeIf(cat -> !cat.getCategories().contains(r.getCategorie2()));
|
||||
.removeIf(cat -> cat.getCategories().stream()
|
||||
.noneMatch(e -> e.getCategorie().equals(r.getCategorie2())));
|
||||
})))
|
||||
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r)))
|
||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||
|
||||
@ -610,7 +610,7 @@ public class ResultService {
|
||||
} else if ((matchModel.isC1(comb) && win > 0) || matchModel.isC2(comb) && win < 0) {
|
||||
stat.w++;
|
||||
stat.win_ids.add(matchModel.getId());
|
||||
stat.score += 3;
|
||||
stat.score += 2;
|
||||
} else {
|
||||
stat.l++;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
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;
|
||||
@ -16,17 +15,15 @@ public class PresetData {
|
||||
private String name;
|
||||
private CatPresetModel.SwordType sword;
|
||||
private CatPresetModel.ShieldType shield;
|
||||
private List<Categorie> categories;
|
||||
long roundDuration;
|
||||
long pauseDuration;
|
||||
int mandatoryProtection;
|
||||
private List<CatPresetModel.CategorieEmbeddable> categories;
|
||||
private int mandatoryProtection1;
|
||||
private int mandatoryProtection2;
|
||||
|
||||
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());
|
||||
model.getCategories(), model.getMandatoryProtection1(), model.getMandatoryProtection2());
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +83,7 @@
|
||||
"ajouterUnClub": "Add a club",
|
||||
"ajouterUnMembre": "Add a member",
|
||||
"all_season": "--- all seasons ---",
|
||||
"ans": "years",
|
||||
"arme": "Weapon",
|
||||
"au": "to",
|
||||
"aucun": "None",
|
||||
@ -105,6 +106,7 @@
|
||||
"button.seDésinscrire": "Unsubscribe",
|
||||
"button.suivant": "Next",
|
||||
"button.supprimer": "Delete",
|
||||
"casque": "Helmet",
|
||||
"cat.benjamin": "Benjamin",
|
||||
"cat.cadet": "Cadet",
|
||||
"cat.catégorieInconnue": "Unknown category",
|
||||
@ -260,6 +262,7 @@
|
||||
"contactInterne": "Internal contact",
|
||||
"contact_one": "Contact",
|
||||
"contact_other": "Contacts",
|
||||
"coquilleProtectionPelvienne": "Shell / Pelvic protection",
|
||||
"date": "Date",
|
||||
"dateDeNaissance": "Date of birth",
|
||||
"days": [
|
||||
@ -299,8 +302,12 @@
|
||||
"faitPar": "Done by",
|
||||
"femme": "Female",
|
||||
"filtre": "Filter",
|
||||
"gantMainBouclier": "Shield hand glove",
|
||||
"gantMainsArmées": "Armed hand(s) glove(s)",
|
||||
"gants": "Gloves",
|
||||
"genre": "Gender",
|
||||
"gestionGroupée": "Group management",
|
||||
"gorgerin": "Gorgerin",
|
||||
"gradeDarbitrage": "Refereeing grade",
|
||||
"h": "M",
|
||||
"home": {
|
||||
@ -480,8 +487,18 @@
|
||||
"perm.créerDesCompétion": "Create competitions",
|
||||
"perm.ffsafIntra": "FFSAF intra",
|
||||
"permission": "Permission",
|
||||
"peutSinscrire": "Can register?",
|
||||
"photos": "Photos",
|
||||
"plastron": "Breastplate",
|
||||
"prenom": "First name",
|
||||
"protectionDeBras": "Arm protection",
|
||||
"protectionDeBrasArmé": "Protection of armed arm(s)",
|
||||
"protectionDeBrasDeBouclier": "Shield arm protection",
|
||||
"protectionDeCoudes": "Elbow protection",
|
||||
"protectionDeGenoux": "Knee protection",
|
||||
"protectionDeJambes": "Leg protection",
|
||||
"protectionDePieds": "Foot protection",
|
||||
"protectionDorsale": "Back protector",
|
||||
"protectionObligatoire": "Mandatory protection",
|
||||
"prénomEtNom": "First and last name",
|
||||
"rechercher": "Search",
|
||||
|
||||
@ -83,6 +83,7 @@
|
||||
"ajouterUnClub": "Ajouter un club",
|
||||
"ajouterUnMembre": "Ajouter un membre",
|
||||
"all_season": "--- tout les saisons ---",
|
||||
"ans": "ans",
|
||||
"arme": "Arme",
|
||||
"au": "au",
|
||||
"aucun": "Aucun",
|
||||
@ -105,6 +106,7 @@
|
||||
"button.seDésinscrire": "Se désinscrire",
|
||||
"button.suivant": "Suivant",
|
||||
"button.supprimer": "Supprimer",
|
||||
"casque": "Casque",
|
||||
"cat.benjamin": "Benjamin",
|
||||
"cat.cadet": "Cadet",
|
||||
"cat.catégorieInconnue": "Catégorie inconnue",
|
||||
@ -260,6 +262,7 @@
|
||||
"contactInterne": "Contact interne",
|
||||
"contact_one": "Contact",
|
||||
"contact_other": "Contacts",
|
||||
"coquilleProtectionPelvienne": "Coquille / Protection pelvienne",
|
||||
"date": "Date",
|
||||
"dateDeNaissance": "Date de naissance",
|
||||
"days": [
|
||||
@ -299,8 +302,12 @@
|
||||
"faitPar": "Fait par",
|
||||
"femme": "Femme",
|
||||
"filtre": "Filtre",
|
||||
"gantMainBouclier": "Gant main de bouclier",
|
||||
"gantMainsArmées": "Gant main(s) armée(s)",
|
||||
"gants": "Gants",
|
||||
"genre": "Genre",
|
||||
"gestionGroupée": "Gestion groupée",
|
||||
"gorgerin": "Gorgerin",
|
||||
"gradeDarbitrage": "Grade d'arbitrage",
|
||||
"h": "H",
|
||||
"home": {
|
||||
@ -480,8 +487,18 @@
|
||||
"perm.créerDesCompétion": "Créer des compétion",
|
||||
"perm.ffsafIntra": "FFSAF intra",
|
||||
"permission": "Permission",
|
||||
"peutSinscrire": "Peut s'inscrire?",
|
||||
"photos": "Photos",
|
||||
"plastron": "Plastron",
|
||||
"prenom": "Prénom",
|
||||
"protectionDeBras": "Protection de bras",
|
||||
"protectionDeBrasArmé": "Protection de bras armé(s)",
|
||||
"protectionDeBrasDeBouclier": "Protection de bras de bouclier",
|
||||
"protectionDeCoudes": "Protection de coudes",
|
||||
"protectionDeGenoux": "Protection de genoux",
|
||||
"protectionDeJambes": "Protection de jambes",
|
||||
"protectionDePieds": "Protection de pieds",
|
||||
"protectionDorsale": "Protection dorsale",
|
||||
"protectionObligatoire": "Protection obligatoire",
|
||||
"prénomEtNom": "Prénom et nom",
|
||||
"rechercher": "Rechercher",
|
||||
|
||||
115
src/main/webapp/src/assets/CategoryPreset.js
Normal file
115
src/main/webapp/src/assets/CategoryPreset.js
Normal file
@ -0,0 +1,115 @@
|
||||
const CategoryPreset = [
|
||||
{
|
||||
name: "Épée",
|
||||
sword: "ONE_HAND",
|
||||
shield: "NONE",
|
||||
categories: [
|
||||
{categorie: "MINI_POUSSIN", roundDuration: 30000, pauseDuration: 60000},
|
||||
{categorie: "POUSSIN", roundDuration: 30000, pauseDuration: 60000},
|
||||
{categorie: "BENJAMIN", roundDuration: 45000, pauseDuration: 60000},
|
||||
{categorie: "MINIME", roundDuration: 45000, pauseDuration: 60000},
|
||||
{categorie: "CADET", roundDuration: 60000, pauseDuration: 60000},
|
||||
],
|
||||
mandatoryProtection1: 45,
|
||||
mandatoryProtection2: 13
|
||||
},
|
||||
{
|
||||
name: "Épée Bouclier",
|
||||
sword: "ONE_HAND",
|
||||
shield: "STANDARD",
|
||||
categories: [
|
||||
{categorie: "SUPER_MINI", roundDuration: 30000, pauseDuration: 60000},
|
||||
{categorie: "MINI_POUSSIN", roundDuration: 30000, pauseDuration: 60000},
|
||||
{categorie: "POUSSIN", roundDuration: 45000, pauseDuration: 60000},
|
||||
{categorie: "BENJAMIN", roundDuration: 45000, pauseDuration: 60000},
|
||||
{categorie: "MINIME", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "CADET", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "JUNIOR", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR2", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN2", roundDuration: 60000, pauseDuration: 60000},
|
||||
],
|
||||
mandatoryProtection1: 45,
|
||||
mandatoryProtection2: 13
|
||||
},
|
||||
{
|
||||
name: "Épée Bocle",
|
||||
sword: "ONE_HAND",
|
||||
shield: "BUCKLER",
|
||||
categories: [
|
||||
{categorie: "POUSSIN", roundDuration: 45000, pauseDuration: 60000},
|
||||
{categorie: "BENJAMIN", roundDuration: 45000, pauseDuration: 60000},
|
||||
{categorie: "MINIME", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "CADET", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "JUNIOR", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR2", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN2", roundDuration: 60000, pauseDuration: 60000},
|
||||
],
|
||||
mandatoryProtection1: 45,
|
||||
mandatoryProtection2: 13
|
||||
},
|
||||
{
|
||||
name: "Épée Longue",
|
||||
sword: "TWO_HAND",
|
||||
shield: "NONE",
|
||||
categories: [
|
||||
{categorie: "JUNIOR", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR2", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN2", roundDuration: 60000, pauseDuration: 60000},
|
||||
],
|
||||
mandatoryProtection1: 61,
|
||||
mandatoryProtection2: 29
|
||||
},
|
||||
{
|
||||
name: "Sabre",
|
||||
sword: "SABER",
|
||||
shield: "NONE",
|
||||
categories: [
|
||||
{categorie: "MINIME", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "CADET", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "JUNIOR", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR2", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN2", roundDuration: 60000, pauseDuration: 60000},
|
||||
],
|
||||
mandatoryProtection1: 47,
|
||||
mandatoryProtection2: 47
|
||||
},
|
||||
{
|
||||
name: "Sabre Bocle",
|
||||
sword: "SABER",
|
||||
shield: "BUCKLER",
|
||||
categories: [
|
||||
{categorie: "MINIME", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "CADET", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "JUNIOR", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR2", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN1", roundDuration: 60000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN2", roundDuration: 60000, pauseDuration: 60000},
|
||||
],
|
||||
mandatoryProtection1: 47,
|
||||
mandatoryProtection2: 47
|
||||
},
|
||||
{
|
||||
name: "Profight Léger",
|
||||
sword: "ONE_HAND",
|
||||
shield: "TEARDROP",
|
||||
categories: [
|
||||
{categorie: "SENIOR1", roundDuration: 120000, pauseDuration: 60000},
|
||||
{categorie: "SENIOR2", roundDuration: 120000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN1", roundDuration: 120000, pauseDuration: 60000},
|
||||
{categorie: "VETERAN2", roundDuration: 120000, pauseDuration: 60000},
|
||||
],
|
||||
mandatoryProtection1: 3647,
|
||||
mandatoryProtection2: 3647
|
||||
},
|
||||
]
|
||||
|
||||
export default CategoryPreset;
|
||||
@ -1,98 +1,165 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
const ProtectionSelector = ({mandatoryProtection = 0, setMandatoryProtection = () => {} }) => {
|
||||
const ProtectionSelector = ({
|
||||
shield = true,
|
||||
mandatoryProtection = 0, setMandatoryProtection = () => {
|
||||
}
|
||||
}) => {
|
||||
const {t} = useTranslation();
|
||||
const toggle = (bit) => {
|
||||
bit = 1 << (bit - 1);
|
||||
setMandatoryProtection(v => (v & bit ? v & ~bit : v | bit));
|
||||
};
|
||||
|
||||
const isOn = (bit) => (mandatoryProtection & bit) !== 0;
|
||||
const props = {
|
||||
style: ({cursor: "pointer"}),
|
||||
};
|
||||
|
||||
const propsDash = {
|
||||
style: ({cursor: "pointer"}),
|
||||
opacity: "0.8",
|
||||
stroke: "#7b8285",
|
||||
strokeDasharray: "4 3",
|
||||
strokeWidth: "1"
|
||||
};
|
||||
|
||||
const isOn = (bit) => (mandatoryProtection & (1 << (bit - 1))) !== 0;
|
||||
const color = (bit) => (isOn(bit) ? "#4ade80" : "#e5e7eb");
|
||||
|
||||
/*
|
||||
1 - 1 - Casque
|
||||
2 - 2 - Gorgerin
|
||||
3 - 4 - Coquille et Protection pelvienne
|
||||
4 - 8 - Gant main(s) armée(s)
|
||||
5 - 16 - Gant main bouclier
|
||||
6 - 32 - Plastron
|
||||
7 - 64 - Protection de bras armé(s)
|
||||
8 - 128 - Protection de bras de bouclier
|
||||
9 - 256 - Protection de jambes
|
||||
10 - 512 - Protection de genoux
|
||||
11 - 1024 - Protection de coudes
|
||||
12 - 2048 - Protection dorsale
|
||||
13 - 4096 - Protection de pieds
|
||||
*/
|
||||
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"
|
||||
/>
|
||||
<svg width="200" height="300" 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)}
|
||||
/>
|
||||
{/* Casque */}
|
||||
<ellipse {...props}
|
||||
cx="80" cy="35" rx="20" ry="22"
|
||||
fill={color(1)}
|
||||
onClick={() => toggle(1)}
|
||||
><title>{t('casque')}</title></ellipse>
|
||||
|
||||
{/* Throat / Neck */}
|
||||
<ellipse
|
||||
cx="80" cy="65" rx="12" ry="8"
|
||||
fill={color(2)}
|
||||
onClick={() => toggle(2)}
|
||||
/>
|
||||
{/* Gorgerin */}
|
||||
<ellipse {...props}
|
||||
cx="80" cy="65" rx="12" ry="8"
|
||||
fill={color(2)}
|
||||
onClick={() => toggle(2)}
|
||||
><title>{t('gorgerin')}</title></ellipse>
|
||||
|
||||
{/* Torso */}
|
||||
<ellipse
|
||||
cx="80" cy="118" rx="30" ry="45"
|
||||
fill={color(4)}
|
||||
onClick={() => toggle(4)}
|
||||
/>
|
||||
{/* Plastron */}
|
||||
<ellipse {...props}
|
||||
cx="80" cy="118" rx="30" ry="45"
|
||||
fill={color(6)}
|
||||
onClick={() => toggle(6)}
|
||||
><title>{t('plastron')}</title></ellipse>
|
||||
|
||||
{/* 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)}
|
||||
/>
|
||||
{/* Protection dorsale */}
|
||||
<ellipse {...propsDash}
|
||||
cx="80" cy="118" rx="10" ry="35"
|
||||
fill={color(12)}
|
||||
onClick={() => toggle(12)}
|
||||
><title>{t('protectionDorsale')}</title></ellipse>
|
||||
|
||||
{/* 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)}
|
||||
/>
|
||||
{/* Protection de bras armé(s) */}
|
||||
<ellipse {...props}
|
||||
cx="38" cy="118" rx="12" ry="40"
|
||||
fill={color(7)}
|
||||
onClick={() => toggle(7)}
|
||||
><title>{shield ? t('protectionDeBrasArmé') : t('protectionDeBras')}</title></ellipse>
|
||||
{/* Protection de bras de bouclier */}
|
||||
<ellipse {...props}
|
||||
cx="122" cy="118" rx="12" ry="40"
|
||||
fill={color(shield ? 8 : 7)}
|
||||
onClick={() => toggle(shield ? 8 : 7)}
|
||||
><title>{shield ? t('protectionDeBrasDeBouclier') : t('protectionDeBras')}</title></ellipse>
|
||||
|
||||
{/* 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)}
|
||||
/>
|
||||
{/* Protection de coudes */}
|
||||
<ellipse {...propsDash}
|
||||
cx="38" cy="118" rx="12" ry="12"
|
||||
fill={color(11)}
|
||||
onClick={() => toggle(11)}
|
||||
><title>{t('protectionDeCoudes')}</title></ellipse>
|
||||
<ellipse {...propsDash}
|
||||
cx="122" cy="118" rx="12" ry="12"
|
||||
fill={color(11)}
|
||||
onClick={() => toggle(11)}
|
||||
><title>{t('protectionDeCoudes')}</title></ellipse>
|
||||
|
||||
{/* Groin */}
|
||||
<ellipse
|
||||
cx="80" cy="170" rx="20" ry="10"
|
||||
fill={color(32)}
|
||||
onClick={() => toggle(32)}
|
||||
/>
|
||||
{/* Gant main(s) armée(s) */}
|
||||
<ellipse {...props}
|
||||
cx="38" cy="170" rx="10" ry="12"
|
||||
fill={color(4)}
|
||||
onClick={() => toggle(4)}
|
||||
><title>{shield ? t('gantMainsArmées') : t('gants')}</title></ellipse>
|
||||
{/* Gant main bouclier */}
|
||||
<ellipse {...props}
|
||||
cx="122" cy="170" rx="10" ry="12"
|
||||
fill={color(shield ? 5 : 4)}
|
||||
onClick={() => toggle(shield ? 5 : 4)}
|
||||
><title>{shield ? t('gantMainBouclier') : t('gants')} </title></ellipse>
|
||||
|
||||
{/* 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>
|
||||
{/* Protection de jambes */}
|
||||
<ellipse {...props}
|
||||
cx="65" cy="230" rx="14" ry="55"
|
||||
fill={color(9)}
|
||||
onClick={() => toggle(9)}
|
||||
><title>{t('protectionDeJambes')}</title></ellipse>
|
||||
<ellipse {...props}
|
||||
cx="95" cy="230" rx="14" ry="55"
|
||||
fill={color(9)}
|
||||
onClick={() => toggle(9)}
|
||||
><title>{t('protectionDeJambes')}</title></ellipse>
|
||||
|
||||
{/* Protection de genoux */}
|
||||
<ellipse {...propsDash}
|
||||
cx="65" cy="230" rx="14" ry="14"
|
||||
fill={color(10)}
|
||||
onClick={() => toggle(10)}
|
||||
><title>{t('protectionDeGenoux')}</title></ellipse>
|
||||
<ellipse {...propsDash}
|
||||
cx="95" cy="230" rx="14" ry="14"
|
||||
fill={color(10)}
|
||||
onClick={() => toggle(10)}
|
||||
><title>{t('protectionDeGenoux')}</title></ellipse>
|
||||
|
||||
{/* Coquille et Protection pelvienne */}
|
||||
<ellipse {...props}
|
||||
cx="80" cy="170" rx="20" ry="10"
|
||||
fill={color(3)}
|
||||
onClick={() => toggle(3)}
|
||||
><title>{t('coquilleProtectionPelvienne')}</title></ellipse>
|
||||
|
||||
{/* Protection de pieds */}
|
||||
<ellipse {...props}
|
||||
cx="65" cy="295" rx="16" ry="8"
|
||||
fill={color(13)}
|
||||
onClick={() => toggle(13)}
|
||||
><title>{t('protectionDePieds')}</title></ellipse>
|
||||
<ellipse {...props}
|
||||
cx="95" cy="295" rx="16" ry="8"
|
||||
fill={color(13)}
|
||||
onClick={() => toggle(13)}
|
||||
><title>{t('protectionDePieds')}</title></ellipse>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {faAdd, faTrashCan} from "@fortawesome/free-solid-svg-icons";
|
||||
import {Trans, useTranslation} from "react-i18next";
|
||||
import ProtectionSelector from "../../components/ProtectionSelector.jsx";
|
||||
import CategoryPreset from "../../assets/CategoryPreset.js";
|
||||
|
||||
export function CompetitionEdit() {
|
||||
const {id} = useParams()
|
||||
@ -372,7 +373,7 @@ function Content({data}) {
|
||||
<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) =>
|
||||
{preset.categories.map(e => e.categorie).sort(sortCategories).map((cat, index) =>
|
||||
<span key={index} className="badge text-bg-secondary"
|
||||
style={{margin: "0 0.25em"}}>{getCatName(cat)}</span>)}
|
||||
</a>)}
|
||||
@ -381,11 +382,27 @@ function Content({data}) {
|
||||
<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 className="btn-group">
|
||||
<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>
|
||||
<button type="button" className="btn btn-success dropdown-toggle dropdown-toggle-split"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span className="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
{CategoryPreset.map((preset, index) =>
|
||||
<li key={index}>
|
||||
<button className="dropdown-item" type="button" data-bs-toggle="modal"
|
||||
data-bs-target="#catModal"
|
||||
onClick={() => setModaleState({id: Math.min(...presets.map(p => p.id), 0) - 1, ...preset})}>
|
||||
{preset.name}
|
||||
</button>
|
||||
</li>)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -479,10 +496,9 @@ 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 [mandatoryProtection1, setMandatoryProtection1] = useState(state.mandatoryProtection1 || 5)
|
||||
const [mandatoryProtection2, setMandatoryProtection2] = useState(state.mandatoryProtection2 || 5)
|
||||
|
||||
const {t} = useTranslation();
|
||||
|
||||
@ -490,23 +506,42 @@ function CatModalContent({setPresets, setPresetChange, state}) {
|
||||
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)
|
||||
setCats(state.categories?.map(c => ({
|
||||
categorie: c.categorie,
|
||||
roundDuration: timePrint(c.roundDuration),
|
||||
pauseDuration: timePrint(c.pauseDuration)
|
||||
})) || [])
|
||||
setMandatoryProtection1(state.mandatoryProtection1 || 5)
|
||||
setMandatoryProtection2(state.mandatoryProtection2 || 5)
|
||||
}, [state]);
|
||||
|
||||
const setCat = (e, cat) => {
|
||||
if (e.target.checked) {
|
||||
if (!cats.includes(cat)) {
|
||||
setCats([...cats, cat])
|
||||
setCats([...cats, {categorie: cat, roundDuration: "", pauseDuration: ""}])
|
||||
}
|
||||
} else {
|
||||
setCats(cats.filter(c => c !== cat))
|
||||
setCats(cats.filter(c => c.categorie !== cat))
|
||||
}
|
||||
}
|
||||
const setTime = (e, cat) => {
|
||||
const value = e.target.value;
|
||||
setCats(cats.map(c => {
|
||||
if (c.categorie === cat)
|
||||
return {...c, roundDuration: value}
|
||||
return c
|
||||
}))
|
||||
}
|
||||
const setPause = (e, cat) => {
|
||||
const value = e.target.value;
|
||||
setCats(cats.map(c => {
|
||||
if (c.categorie === cat)
|
||||
return {...c, pauseDuration: value}
|
||||
return c
|
||||
}))
|
||||
}
|
||||
|
||||
const isCatSelected = (cat) => cats.includes(cat)
|
||||
const isCatSelected = (cat) => cats.some(cat_ => cat_.categorie === cat)
|
||||
|
||||
const parseTime = (str) => {
|
||||
const parts = str.split(":").map(part => parseInt(part, 10));
|
||||
@ -525,10 +560,13 @@ function CatModalContent({setPresets, setPresetChange, state}) {
|
||||
name: name,
|
||||
sword: sword,
|
||||
shield: shield,
|
||||
roundDuration: parseTime(time),
|
||||
pauseDuration: parseTime(pause),
|
||||
categories: cats,
|
||||
mandatoryProtection: mandatoryProtection
|
||||
categories: cats.map(c => ({
|
||||
categorie: c.categorie,
|
||||
roundDuration: parseTime(c.roundDuration),
|
||||
pauseDuration: parseTime(c.pauseDuration)
|
||||
})),
|
||||
mandatoryProtection1: mandatoryProtection1,
|
||||
mandatoryProtection2: mandatoryProtection2
|
||||
}
|
||||
setPresets(presets => [...presets.filter(p => p.id !== out.id), out])
|
||||
setPresetChange(true)
|
||||
@ -553,19 +591,6 @@ function CatModalContent({setPresets, setPresetChange, state}) {
|
||||
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}
|
||||
@ -586,24 +611,46 @@ function CatModalContent({setPresets, setPresetChange, state}) {
|
||||
</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>
|
||||
<table className="table" style={{textAlign: "center"}}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{t('catégorie')}</th>
|
||||
<th scope="col">{t('peutSinscrire')}</th>
|
||||
<th scope="col">{t('duréeRound')}</th>
|
||||
<th scope="col">{t('duréePause')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{CatList.map((cat, index) => <tr key={index} style={{verticalAlign: "middle"}}>
|
||||
<th scope="row" style={{width: "7em"}}><label htmlFor={"catInput" + index}>{getCatName(cat)}</label></th>
|
||||
<td><input className="form-check-input" type="checkbox" id={"catInput" + index} checked={isCatSelected(cat)}
|
||||
aria-label={getCatName(cat)} onChange={e => setCat(e, cat)}/></td>
|
||||
<td style={{padding: "0"}}><input type="text" className="form-control form-control-sm" placeholder="mm:ss"
|
||||
value={cats.find(c => c.categorie === cat)?.roundDuration || ""}
|
||||
onChange={e => setTime(e, cat)}
|
||||
aria-label="mm:ss" hidden={!isCatSelected(cat)} style={{width: "4.5em"}}/></td>
|
||||
<td style={{padding: "0"}}><input type="text" className="form-control form-control-sm" placeholder="mm:ss"
|
||||
value={cats.find(c => c.categorie === cat)?.pauseDuration || ""}
|
||||
onChange={e => setPause(e, cat)}
|
||||
aria-label="mm:ss" hidden={!isCatSelected(cat)} style={{width: "4.5em"}}/></td>
|
||||
</tr>)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="col-12 col-md-5">
|
||||
<div style={{textAlign: "center"}}>
|
||||
<h6>{t('protectionObligatoire')} :</h6>
|
||||
<ProtectionSelector mandatoryProtection={mandatoryProtection} setMandatoryProtection={setMandatoryProtection}/>
|
||||
{cats.some(cat_ => CatList.indexOf(cat_.categorie) <= CatList.indexOf("JUNIOR")) && <>
|
||||
<div>< 18 {t('ans')}</div>
|
||||
<ProtectionSelector shield={shield !== "NONE"} mandatoryProtection={mandatoryProtection1}
|
||||
setMandatoryProtection={setMandatoryProtection1}/>
|
||||
</>}
|
||||
{cats.some(cat_ => CatList.indexOf(cat_.categorie) > CatList.indexOf("JUNIOR")) && <>
|
||||
<div>≥ 18 {t('ans')}</div>
|
||||
<ProtectionSelector shield={shield !== "NONE"} mandatoryProtection={mandatoryProtection2}
|
||||
setMandatoryProtection={setMandatoryProtection2}/>
|
||||
</>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,7 @@ import {LoadingProvider, useLoadingSwitcher} from "../../hooks/useLoading.jsx";
|
||||
import {useFetch} from "../../hooks/useFetch.js";
|
||||
import {AxiosError} from "../../components/AxiosError.jsx";
|
||||
import {ThreeDots} from "react-loader-spinner";
|
||||
import React, {useEffect, useReducer, useRef, useState} from "react";
|
||||
import React, {useEffect, useId, useReducer, useRef, useState} from "react";
|
||||
import {apiAxios, applyOverCategory, CatList, getCatName, getToastMessage} from "../../utils/Tools.js";
|
||||
import {toast} from "react-toastify";
|
||||
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
|
||||
@ -317,6 +317,8 @@ const AutoCompleteInput = ({suggestions = [], handleAdd}) => {
|
||||
|
||||
function CategoriesList({error2, availableCats, fistCatInput, categories, setCategories}) {
|
||||
const {t} = useTranslation();
|
||||
const id = useId();
|
||||
|
||||
return <>
|
||||
{error2 ? <AxiosError error={error2}/> : <>
|
||||
{availableCats && availableCats.length === 0 && <div>{t('aucuneCatégorieDisponible')}</div>}
|
||||
@ -325,9 +327,9 @@ function CategoriesList({error2, availableCats, fistCatInput, categories, setCat
|
||||
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}
|
||||
id={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>
|
||||
<label style={{marginLeft: "0.5em"}} htmlFor={id + "categoriesInput" + index}>{cat.name}</label>
|
||||
</div>
|
||||
</div>)}
|
||||
</>}
|
||||
@ -427,7 +429,7 @@ function Modal({data2, error2, sendRegister, modalState, setModalState, source})
|
||||
}
|
||||
|
||||
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)) : []
|
||||
const availableCats = data2 ? (currenCat !== "" ? data2.filter(c => c.categories.some(c2 => c2.categorie === currenCat)) : data2).sort((a, b) => a.name.localeCompare(b.name)) : []
|
||||
if (availableCats.length === 0) {
|
||||
if (fistCatInput.current) {
|
||||
fistCatInput.current = null
|
||||
@ -625,7 +627,8 @@ function MakeCentralPanel({data, data2, dispatch, id, setModalState, source}) {
|
||||
<small>
|
||||
{req.data.categoriesInscrites.map(catId => data2?.find(c => c.id === catId)).filter(o => o !== undefined)
|
||||
.sort((a, b) => a.name.localeCompare(b.name)).map(cat =>
|
||||
<span key={cat.id} className="badge text-bg-secondary" style={{margin: "0 0.125em"}}>{cat.name}</span>)}
|
||||
<span key={cat.id} className="badge text-bg-secondary"
|
||||
style={{margin: "0 0.125em"}}>{cat.name}</span>)}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -74,7 +74,7 @@ function MakeContent({data}) {
|
||||
disabled={new Date() < new Date(data.startRegister.split('+')[0]) || new Date() > new Date(data.endRegister.split('+')[0])}
|
||||
onClick={_ => navigate("/competition/" + data.id + "/club/register")}>{t('comp.inscription')}</button>
|
||||
}
|
||||
{data.registerMode === "FREE" && !isClubAdmin(userinfo) && <SelfRegister/>
|
||||
{data.registerMode === "FREE" && !isClubAdmin(userinfo) && <SelfRegister data2={data}/>
|
||||
|| <ShowRegister/>
|
||||
}
|
||||
{data.registerMode === "HELLOASSO" &&
|
||||
@ -147,7 +147,7 @@ function SelfRegister({data2}) {
|
||||
}
|
||||
|
||||
const currenCat = data?.length > 0 && data[0]?.categorie !== "" ? applyOverCategory(data[0]?.categorie, cat) : "";
|
||||
const availableCats = data3 ? (currenCat !== "" ? data3.filter(c => c.categories.includes(currenCat)) : data3).sort((a, b) => a.name.localeCompare(b.name)) : []
|
||||
const availableCats = data3 ? (currenCat !== "" ? data3.filter(c => c.categories.some(c2 => c2.categorie === currenCat)) : data3).sort((a, b) => a.name.localeCompare(b.name)) : []
|
||||
|
||||
return <>
|
||||
{data
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user