Compare commits
3 Commits
dc5ab9c3c4
...
4856326b29
| Author | SHA1 | Date | |
|---|---|---|---|
| 4856326b29 | |||
| b94f4b43ce | |||
| 795d044c0b |
@ -355,10 +355,16 @@ public class AffiliationService {
|
|||||||
.map(c -> club));
|
.map(c -> club));
|
||||||
})
|
})
|
||||||
.call(club -> reactiveMailer.send(
|
.call(club -> reactiveMailer.send(
|
||||||
Mail.withText(form.getM1_email(),
|
Mail.withHtml(form.getM1_email(), "FFSAF - Creation de votre compte sur l'intranet",
|
||||||
"FFSAF - Acceptation de votre demande d'affiliation",
|
String.format(Utils.HTML_HEADER, "FFSAF - Creation de votre compte sur l'intranet") +
|
||||||
String.format(
|
String.format("""
|
||||||
"""
|
<p>Votre demande d'affiliation pour le club <span class="highlight">%s</span> a été acceptée.</p>
|
||||||
|
<p>LLe numéro d'affiliation de votre club est le <span class="highlight">%d</span>.</p>
|
||||||
|
""",
|
||||||
|
club.getName(), club.getNo_affiliation()) +
|
||||||
|
Utils.HTML_FOOTER
|
||||||
|
)
|
||||||
|
.setText(String.format("""
|
||||||
Bonjour,
|
Bonjour,
|
||||||
|
|
||||||
Votre demande d'affiliation pour le club %s a été acceptée.
|
Votre demande d'affiliation pour le club %s a été acceptée.
|
||||||
@ -366,8 +372,8 @@ public class AffiliationService {
|
|||||||
|
|
||||||
Cordialement,
|
Cordialement,
|
||||||
L'équipe de la FFSAF
|
L'équipe de la FFSAF
|
||||||
""", club.getName(), club.getNo_affiliation())
|
""", club.getName(), club.getNo_affiliation()))
|
||||||
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr")
|
.setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr")
|
||||||
.addTo(form.getM2_email(), form.getM3_email())
|
.addTo(form.getM2_email(), form.getM3_email())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -458,10 +464,16 @@ public class AffiliationService {
|
|||||||
public Uni<?> deleteReqAffiliation(long id, String reason, boolean federationAdmin) {
|
public Uni<?> deleteReqAffiliation(long id, String reason, boolean federationAdmin) {
|
||||||
return repositoryRequest.findById(id)
|
return repositoryRequest.findById(id)
|
||||||
.call(aff -> federationAdmin ? reactiveMailer.send(
|
.call(aff -> federationAdmin ? reactiveMailer.send(
|
||||||
Mail.withText(aff.getM1_email(),
|
Mail.withHtml(aff.getM1_email(), "FFSAF - Votre demande d'affiliation a été rejetée.",
|
||||||
"FFSAF - Votre demande d'affiliation a été rejetée.",
|
String.format(Utils.HTML_HEADER, "FFSAF - Votre demande d'affiliation a été rejetée.") +
|
||||||
String.format(
|
String.format("""
|
||||||
"""
|
<p>Votre demande d'affiliation pour le club %s a été rejetée pour la/les raison(s) suivante(s):<br/>%s</p>
|
||||||
|
<p>Si vous rencontrez un problème ou si vous avez des questions, n'hésitez pas à nous contacter à l'adresse <a href="mailto:contact@ffsaf.fr">contact@ffsaf.fr</a>.</p>
|
||||||
|
""",
|
||||||
|
aff.getName(), reason) +
|
||||||
|
Utils.HTML_FOOTER
|
||||||
|
)
|
||||||
|
.setText(String.format("""
|
||||||
Bonjour,
|
Bonjour,
|
||||||
|
|
||||||
Votre demande d'affiliation pour le club %s a été rejetée pour la/les raison(s) suivante(s):
|
Votre demande d'affiliation pour le club %s a été rejetée pour la/les raison(s) suivante(s):
|
||||||
@ -471,8 +483,8 @@ public class AffiliationService {
|
|||||||
|
|
||||||
Cordialement,
|
Cordialement,
|
||||||
L'équipe de la FFSAF
|
L'équipe de la FFSAF
|
||||||
""", aff.getName(), reason)
|
""", aff.getName(), reason))
|
||||||
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr")
|
.setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr")
|
||||||
.addTo(aff.getM2_email(), aff.getM3_email())
|
.addTo(aff.getM2_email(), aff.getM3_email())
|
||||||
) : Uni.createFrom().nullItem())
|
) : Uni.createFrom().nullItem())
|
||||||
.chain(aff -> Panache.withTransaction(() -> repositoryRequest.delete(aff)))
|
.chain(aff -> Panache.withTransaction(() -> repositoryRequest.delete(aff)))
|
||||||
|
|||||||
@ -156,10 +156,18 @@ public class KeycloakService {
|
|||||||
return oldEmail;
|
return oldEmail;
|
||||||
}).call(oldEmail -> oldEmail == null || !enabled_email ? Uni.createFrom().item("") :
|
}).call(oldEmail -> oldEmail == null || !enabled_email ? Uni.createFrom().item("") :
|
||||||
reactiveMailer.send(
|
reactiveMailer.send(
|
||||||
Mail.withText(oldEmail,
|
Mail.withHtml(oldEmail, "FFSAF - Changement de votre adresse email",
|
||||||
"FFSAF - Changement de votre adresse email",
|
String.format(Utils.HTML_HEADER, "FFSAF - Changement de votre adresse email") +
|
||||||
String.format(
|
String.format("""
|
||||||
"""
|
<p>Suite à la modification de votre adresse email fournie lors de votre (ré)inscription à la FFSAF,<br/>
|
||||||
|
vous allez recevoir dans les prochaines minutes un email de vérification de votre nouvelle adresse sur celle-ci.</p>
|
||||||
|
<p>Ancienne adresse email : <span class="highlight">%s</span><br/>Nouvelle adresse email : <span class="highlight">%s</span></p>
|
||||||
|
<p>Si vous n'avez pas demandé cette modification, veuillez contacter le support à l'adresse <a href="mailto:support@ffsaf.fr">support@ffsaf.fr</a>.</p>
|
||||||
|
""",
|
||||||
|
oldEmail, email) +
|
||||||
|
Utils.HTML_FOOTER
|
||||||
|
)
|
||||||
|
.setText(String.format("""
|
||||||
Bonjour,
|
Bonjour,
|
||||||
|
|
||||||
Suite à la modification de votre adresse email fournie lors de votre (ré)inscription à la FFSAF,
|
Suite à la modification de votre adresse email fournie lors de votre (ré)inscription à la FFSAF,
|
||||||
@ -172,8 +180,8 @@ public class KeycloakService {
|
|||||||
|
|
||||||
Cordialement,
|
Cordialement,
|
||||||
L'équipe de la FFSAF
|
L'équipe de la FFSAF
|
||||||
""", oldEmail, email)
|
""", oldEmail, email))
|
||||||
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
|
.setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
|
||||||
).onFailure().invoke(e -> LOGGER.error("Fail to send email", e)));
|
).onFailure().invoke(e -> LOGGER.error("Fail to send email", e)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,72 +278,10 @@ public class KeycloakService {
|
|||||||
.invoke(user -> membreModel.setUserId(user.getId()))
|
.invoke(user -> membreModel.setUserId(user.getId()))
|
||||||
.call(user -> updateRole(user.getId(), List.of("safca_user"), List.of()))
|
.call(user -> updateRole(user.getId(), List.of("safca_user"), List.of()))
|
||||||
.call(user -> enabled_email ? reactiveMailer.send(
|
.call(user -> enabled_email ? reactiveMailer.send(
|
||||||
Mail.withHtml(user.getEmail(), "FFSAF - Creation de votre compte sur l'intranet", String.format(
|
Mail.withHtml(user.getEmail(), "FFSAF - Creation de votre compte sur l'intranet",
|
||||||
|
String.format(Utils.HTML_HEADER, "Création de votre compte intranet FFSAF") +
|
||||||
|
String.format(
|
||||||
"""
|
"""
|
||||||
<!DOCTYPE html>
|
|
||||||
<html data-lt-installed="true">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Création de votre compte intranet FFSAF</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: #333;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
background-color: #003366;
|
|
||||||
color: white;
|
|
||||||
padding: 20px;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 5px 5px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 20px;
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
border-radius: 0 0 5px 5px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px 20px;
|
|
||||||
background-color: #003366;
|
|
||||||
color: white !important;
|
|
||||||
text-decoration: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
margin: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
margin-top: 20px;
|
|
||||||
font-size: 0.9em;
|
|
||||||
color: #666;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #003366;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body data-gramm="false" data-lt-tmp-id="lt-957854">
|
|
||||||
<div class="header">
|
|
||||||
<div><img src="https://intra.ffsaf.fr/Logo-FFSAF-2023.png" alt="ffsaf" height="128">
|
|
||||||
<h1>Fédération France Soft Armored Fighting</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<p>Bonjour,</p>
|
|
||||||
<p>Suite à votre première inscription <span class="highlight">%s</span> à la <strong>Fédération France Soft Armored Fighting (FFSAF)</strong>, votre compte intranet a été créé.</p>
|
<p>Suite à votre première inscription <span class="highlight">%s</span> à la <strong>Fédération France Soft Armored Fighting (FFSAF)</strong>, votre compte intranet a été créé.</p>
|
||||||
<p>Ce compte vous permettra de :</p>
|
<p>Ce compte vous permettra de :</p>
|
||||||
<ul>
|
<ul>
|
||||||
@ -349,14 +295,10 @@ public class KeycloakService {
|
|||||||
<p>Pour définir votre mot de passe, rendez-vous sur l’intranet : <strong>Connexion > Mot de passe oublié ?</strong></p>
|
<p>Pour définir votre mot de passe, rendez-vous sur l’intranet : <strong>Connexion > Mot de passe oublié ?</strong></p>
|
||||||
<p>Si vous n’avez pas demandé cette inscription, veuillez contacter le support à l’adresse : <a href="mailto:support@ffsaf.fr">support@ffsaf.fr</a>.</p>
|
<p>Si vous n’avez pas demandé cette inscription, veuillez contacter le support à l’adresse : <a href="mailto:support@ffsaf.fr">support@ffsaf.fr</a>.</p>
|
||||||
<p class="footer">(Pas de panique, nous ne vous enverrons pas de message autre que ceux concernant votre compte.)</p>
|
<p class="footer">(Pas de panique, nous ne vous enverrons pas de message autre que ceux concernant votre compte.)</p>
|
||||||
<p>Cordialement,<br>L’équipe de la FFSAF</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
""",
|
""",
|
||||||
membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub()
|
membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub()
|
||||||
.getName() + ") " : "", user.getUsername())
|
.getName() + ") " : "", user.getUsername()) +
|
||||||
|
Utils.HTML_FOOTER
|
||||||
)
|
)
|
||||||
.setText(String.format(
|
.setText(String.format(
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -21,6 +21,79 @@ import java.util.concurrent.Future;
|
|||||||
public class Utils {
|
public class Utils {
|
||||||
private static final Logger LOGGER = Logger.getLogger(Utils.class);
|
private static final Logger LOGGER = Logger.getLogger(Utils.class);
|
||||||
|
|
||||||
|
public static String HTML_HEADER = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-lt-installed="true">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>%s</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background-color: #003366;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #003366;
|
||||||
|
color: white !important;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #003366;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body data-gramm="false" data-lt-tmp-id="lt-957854">
|
||||||
|
<div class="header">
|
||||||
|
<div><img src="https://intra.ffsaf.fr/Logo-FFSAF-2023.png" alt="ffsaf" height="128">
|
||||||
|
<h1>Fédération France Soft Armored Fighting</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>Bonjour,</p>
|
||||||
|
""";
|
||||||
|
public static String HTML_FOOTER = """
|
||||||
|
<p>Cordialement,<br>L’équipe de la FFSAF</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
""";
|
||||||
|
|
||||||
public static int getSaison() {
|
public static int getSaison() {
|
||||||
return getSaison(new Date());
|
return getSaison(new Date());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -292,9 +292,10 @@ public class RMatch {
|
|||||||
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
|
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
|
||||||
throw new DForbiddenException("Permission denied");
|
throw new DForbiddenException("Permission denied");
|
||||||
}))
|
}))
|
||||||
.call(cm -> matchRepository.delete("id IN ?1 AND category = ?2", data.matchesToRemove, cm)
|
.call(cm -> Panache.withTransaction(
|
||||||
|
() -> matchRepository.delete("id IN ?1 AND category = ?2", data.matchesToRemove, cm))
|
||||||
.call(__ -> SSMatch.sendDeleteMatch(connection, data.matchesToRemove)))
|
.call(__ -> SSMatch.sendDeleteMatch(connection, data.matchesToRemove)))
|
||||||
.call(cm -> matchRepository.list("id IN ?1 AND category = ?2",
|
.call(cm -> Panache.withSession(() -> matchRepository.list("id IN ?1 AND category = ?2",
|
||||||
Stream.concat(data.matchOrderToUpdate.keySet().stream(),
|
Stream.concat(data.matchOrderToUpdate.keySet().stream(),
|
||||||
data.matchPouleToUpdate.keySet().stream())
|
data.matchPouleToUpdate.keySet().stream())
|
||||||
.distinct().toList(), cm)
|
.distinct().toList(), cm)
|
||||||
@ -305,13 +306,14 @@ public class RMatch {
|
|||||||
model.setCategory_ord(data.matchOrderToUpdate.get(model.getId()));
|
model.setCategory_ord(data.matchOrderToUpdate.get(model.getId()));
|
||||||
}))
|
}))
|
||||||
.call(mm -> Panache.withTransaction(() -> matchRepository.persist(mm)))
|
.call(mm -> Panache.withTransaction(() -> matchRepository.persist(mm)))
|
||||||
.invoke(mm -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList()))
|
.invoke(mm -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList())))
|
||||||
)
|
)
|
||||||
.chain(categoryModel -> {
|
.chain(categoryModel -> {
|
||||||
Uni<List<MatchModel>> uni = Uni.createFrom().item(new ArrayList<>());
|
Uni<List<MatchModel>> uni = Uni.createFrom().item(new ArrayList<>());
|
||||||
for (AddMatch match : data.newMatch)
|
for (AddMatch match : data.newMatch)
|
||||||
uni = uni.call(l -> creatMatch(categoryModel, match).invoke(l::add));
|
uni = uni.call(l -> creatMatch(categoryModel, match).invoke(l::add));
|
||||||
return uni;
|
Uni<List<MatchModel>> finalUni = uni;
|
||||||
|
return Panache.withSession(() -> finalUni);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm))
|
.chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm))
|
||||||
|
|||||||
@ -299,7 +299,7 @@ function AssoInfo({initData, needFile}) {
|
|||||||
|
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
<label className="input-group-text" htmlFor="status">Statue{needFile && "*"}</label>
|
<label className="input-group-text" htmlFor="status">Statuts{needFile && "*"}</label>
|
||||||
<input type="file" className="form-control" id="status" name="status" accept=".pdf,.txt" required={needFile}/>
|
<input type="file" className="form-control" id="status" name="status" accept=".pdf,.txt" required={needFile}/>
|
||||||
</div>
|
</div>
|
||||||
{!needFile && <div className="form-text" id="status">Laissez vide pour ne rien changer. (Si un statu a déjà été envoyé lors de cette
|
{!needFile && <div className="form-text" id="status">Laissez vide pour ne rien changer. (Si un statu a déjà été envoyé lors de cette
|
||||||
@ -313,7 +313,7 @@ function MembreInfo({role, initData}) {
|
|||||||
|
|
||||||
return <>
|
return <>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<label className="input-group-text" htmlFor="inputGroupSelect01">Rôles</label>
|
<label className="input-group-text" htmlFor="inputGroupSelect01">Rôle</label>
|
||||||
<select className="form-select" id="inputGroupSelect01" defaultValue={initData.role ? initData.role : (role === "m1" ? "PRESIDENT" : 0)}
|
<select className="form-select" id="inputGroupSelect01" defaultValue={initData.role ? initData.role : (role === "m1" ? "PRESIDENT" : 0)}
|
||||||
disabled={initData.role ? initData.role === "PRESIDENT" : role === "m1"} name={role + "_role"} required>
|
disabled={initData.role ? initData.role === "PRESIDENT" : role === "m1"} name={role + "_role"} required>
|
||||||
<option value="0">Sélectionner...</option>
|
<option value="0">Sélectionner...</option>
|
||||||
|
|||||||
@ -155,8 +155,8 @@ function ModalContent2({clubData, data}) {
|
|||||||
aria-label="Close"></button>
|
aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<p>Veuillez sélectionner 3 membres du bureau pour remplir la pré-demande. (Si un membre non-bureau va le devenir l'an prochain,
|
<p>Veuillez sélectionner 0 à 3 membres du bureau pour remplir la pré-demande. (Si un membre non-bureau va le devenir l'an prochain,
|
||||||
vous pourrez toujours remplacer un des membres sélectionné à la prochaine étape)</p>
|
vous pourrez les renseigner à la prochaine étape)</p>
|
||||||
{data && data.map((d, index) => {
|
{data && data.map((d, index) => {
|
||||||
return <div key={index} className="input-group mb-1">
|
return <div key={index} className="input-group mb-1">
|
||||||
<div className="input-group-text">
|
<div className="input-group-text">
|
||||||
|
|||||||
@ -116,7 +116,7 @@ export function CategoryContent({cat, catId, setCat}) {
|
|||||||
|
|
||||||
const activeMatches = matches2.filter(m => m.poule !== '-')
|
const activeMatches = matches2.filter(m => m.poule !== '-')
|
||||||
|
|
||||||
const combsIDs = activeMatches.flatMap(d => [d.c1, d.c2]).filter((v, i, a) => v != null && a.indexOf(v) === i)
|
const combsIDs = matches2.flatMap(d => [d.c1, d.c2]).filter((v, i, a) => v != null && a.indexOf(v) === i)
|
||||||
.map(d => {
|
.map(d => {
|
||||||
let poule = activeMatches.find(m => (m.c1 === d || m.c2 === d) && m.categorie_ord !== -42)?.poule
|
let poule = activeMatches.find(m => (m.c1 === d || m.c2 === d) && m.categorie_ord !== -42)?.poule
|
||||||
if (!poule)
|
if (!poule)
|
||||||
|
|||||||
@ -111,11 +111,11 @@ function Home2({perm}) {
|
|||||||
<h4 className="col-auto" style={{margin: "auto 0"}}>Sélectionne les modes d'affichage</h4>
|
<h4 className="col-auto" style={{margin: "auto 0"}}>Sélectionne les modes d'affichage</h4>
|
||||||
<div className="col">
|
<div className="col">
|
||||||
{perm === "ADMIN" && <>
|
{perm === "ADMIN" && <>
|
||||||
<button className="btn btn-primary" onClick={() => nav("table")}>Table de marque</button>
|
<button className="btn btn-primary" onClick={() => nav("table")}>Secrétariats de lice</button>
|
||||||
<button className="btn btn-primary ms-3" onClick={() => nav("admin")}>Administration</button>
|
<button className="btn btn-primary ms-3" onClick={() => nav("admin")}>Administration</button>
|
||||||
</>}
|
</>}
|
||||||
{perm === "TABLE" && <>
|
{perm === "TABLE" && <>
|
||||||
<button className="btn btn-primary" onClick={() => nav("table")}>Table de marque</button>
|
<button className="btn btn-primary" onClick={() => nav("table")}>Secrétariats de lice</button>
|
||||||
</>}
|
</>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user