Compare commits
3 Commits
194986f880
...
8156c8f3d0
| Author | SHA1 | Date | |
|---|---|---|---|
| 8156c8f3d0 | |||
| 7249b45533 | |||
| 7e036c1966 |
@@ -21,6 +21,9 @@ public class Dotation {
|
||||
@Column(length = 10)
|
||||
private String taille;
|
||||
|
||||
@Column(length = 50)
|
||||
private String couleur;
|
||||
|
||||
@Column(length = 50)
|
||||
private String flocage;
|
||||
|
||||
@@ -47,6 +50,9 @@ public class Dotation {
|
||||
public String getTaille() { return taille; }
|
||||
public void setTaille(String taille) { this.taille = taille; }
|
||||
|
||||
public String getCouleur() { return couleur; }
|
||||
public void setCouleur(String couleur) { this.couleur = couleur; }
|
||||
|
||||
public String getFlocage() { return flocage; }
|
||||
public void setFlocage(String flocage) { this.flocage = flocage; }
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@ public class Equipement {
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String description;
|
||||
|
||||
@Column(name = "gestion_sexe", nullable = false)
|
||||
private boolean gestionSexe = false;
|
||||
|
||||
@Column(name = "tailles_disponibles", length = 500)
|
||||
private String taillesDisponibles;
|
||||
|
||||
@Column(name = "couleurs_disponibles", length = 500)
|
||||
private String couleursDisponibles;
|
||||
|
||||
|
||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "saison_id", nullable = false)
|
||||
@@ -39,6 +48,15 @@ public class Equipement {
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public boolean isGestionSexe() { return gestionSexe; }
|
||||
public void setGestionSexe(boolean gestionSexe) { this.gestionSexe = gestionSexe; }
|
||||
|
||||
public String getTaillesDisponibles() { return taillesDisponibles; }
|
||||
public void setTaillesDisponibles(String taillesDisponibles) { this.taillesDisponibles = taillesDisponibles; }
|
||||
|
||||
public String getCouleursDisponibles() { return couleursDisponibles; }
|
||||
public void setCouleursDisponibles(String couleursDisponibles) { this.couleursDisponibles = couleursDisponibles; }
|
||||
|
||||
public Saison getSaison() { return saison; }
|
||||
public void setSaison(Saison saison) { this.saison = saison; }
|
||||
}
|
||||
|
||||
@@ -29,6 +29,12 @@ public class Paiement {
|
||||
@Column(name = "gestionnaire")
|
||||
private String gestionnaire;
|
||||
|
||||
@Column(name = "numero_cheque", length = 50)
|
||||
private String numeroCheque;
|
||||
|
||||
@Column(name = "commentaire", columnDefinition = "TEXT")
|
||||
private String commentaire;
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
public Long getId() { return id; }
|
||||
@@ -48,4 +54,10 @@ public class Paiement {
|
||||
|
||||
public String getGestionnaire() { return gestionnaire; }
|
||||
public void setGestionnaire(String gestionnaire) { this.gestionnaire = gestionnaire; }
|
||||
|
||||
public String getNumeroCheque() { return numeroCheque; }
|
||||
public void setNumeroCheque(String numeroCheque) { this.numeroCheque = numeroCheque; }
|
||||
|
||||
public String getCommentaire() { return commentaire; }
|
||||
public void setCommentaire(String commentaire) { this.commentaire = commentaire; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE equipement ADD COLUMN gestion_sexe BOOLEAN DEFAULT FALSE NOT NULL;
|
||||
ALTER TABLE equipement ADD COLUMN tailles_disponibles VARCHAR(500);
|
||||
ALTER TABLE equipement ADD COLUMN couleurs_disponibles VARCHAR(500);
|
||||
|
||||
ALTER TABLE dotation ADD COLUMN couleur VARCHAR(50);
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE paiement ADD COLUMN numero_cheque VARCHAR(50);
|
||||
ALTER TABLE paiement ADD COLUMN commentaire TEXT;
|
||||
@@ -168,12 +168,14 @@ public class DotationController {
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid Dotation ID: " + id));
|
||||
|
||||
String taille = request.getParameter("taille_" + id);
|
||||
String couleur = request.getParameter("couleur_" + id);
|
||||
String numero = request.getParameter("numero_" + id);
|
||||
String flocage = request.getParameter("flocage_" + id);
|
||||
String choisiParam = request.getParameter("choisi_" + id);
|
||||
String fourniParam = request.getParameter("fourni_" + id);
|
||||
|
||||
if (taille != null) dotation.setTaille(taille);
|
||||
if (couleur != null) dotation.setCouleur(couleur);
|
||||
if (numero != null) dotation.setNumero(numero);
|
||||
if (flocage != null) dotation.setFlocage(flocage);
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ public class PaiementController {
|
||||
@RequestParam BigDecimal montant,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate datePaiement,
|
||||
@RequestParam Long modePaiementId,
|
||||
@RequestParam(required = false) String numeroCheque,
|
||||
@RequestParam(required = false) String commentaire,
|
||||
Principal principal) {
|
||||
|
||||
Licence licence = licenceRepository.findById(id)
|
||||
@@ -58,6 +60,8 @@ public class PaiementController {
|
||||
paiement.setModePaiement(mode);
|
||||
paiement.setMontant(montant);
|
||||
paiement.setDatePaiement(datePaiement);
|
||||
paiement.setNumeroCheque(numeroCheque);
|
||||
paiement.setCommentaire(commentaire);
|
||||
if (principal != null) {
|
||||
paiement.setGestionnaire(principal.getName());
|
||||
}
|
||||
@@ -82,6 +86,8 @@ public class PaiementController {
|
||||
@RequestParam BigDecimal montant,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate datePaiement,
|
||||
@RequestParam Long modePaiementId,
|
||||
@RequestParam(required = false) String numeroCheque,
|
||||
@RequestParam(required = false) String commentaire,
|
||||
@RequestParam(required = false) String redirect,
|
||||
Principal principal) {
|
||||
|
||||
@@ -106,6 +112,8 @@ public class PaiementController {
|
||||
paiement.setModePaiement(mode);
|
||||
paiement.setMontant(montant);
|
||||
paiement.setDatePaiement(datePaiement);
|
||||
paiement.setNumeroCheque(numeroCheque);
|
||||
paiement.setCommentaire(commentaire);
|
||||
if (principal != null) {
|
||||
paiement.setGestionnaire(principal.getName());
|
||||
}
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
<tr class="bg-gray-50 text-gray-500 uppercase font-medium">
|
||||
<th class="py-2 px-3 text-left">Date</th>
|
||||
<th class="py-2 px-3 text-left">Mode</th>
|
||||
<th class="py-2 px-3 text-left">Infos</th>
|
||||
<th class="py-2 px-3 text-left">Géré par</th>
|
||||
<th class="py-2 px-3 text-right font-medium">Montant</th>
|
||||
<th class="py-2 px-3 text-right font-medium pr-4">Actions</th>
|
||||
@@ -289,6 +290,14 @@
|
||||
<td class="py-2 px-3 text-gray-600">
|
||||
<span class="px-2 py-0.5 rounded bg-gray-100 text-gray-700 font-mono text-[10px]" th:text="${paiement.modePaiement.nom}">Chèque</span>
|
||||
</td>
|
||||
<td class="py-2 px-3 text-gray-500 text-xs">
|
||||
<div th:if="${paiement.numeroCheque != null and !paiement.numeroCheque.isEmpty()}" class="text-[10px]">
|
||||
<span class="font-semibold text-gray-600">N°:</span> <span th:text="${paiement.numeroCheque}">123</span>
|
||||
</div>
|
||||
<div th:if="${paiement.commentaire != null and !paiement.commentaire.isEmpty()}" class="text-[10px] italic mt-0.5 text-gray-400 truncate max-w-[120px]" th:title="${paiement.commentaire}" th:text="${paiement.commentaire}">
|
||||
Commentaire
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 px-3 text-gray-500 text-xs italic" th:text="${paiement.gestionnaire != null ? paiement.gestionnaire : '-'}">-</td>
|
||||
<td class="py-2 px-3 text-right font-semibold text-green-600" th:text="${paiement.montant + ' €'}">50.00 €</td>
|
||||
<td class="py-2 px-3 text-right pr-4">
|
||||
@@ -300,7 +309,9 @@
|
||||
th:data-mode-id="${paiement.modePaiement.id}"
|
||||
th:data-licence-id="${lic.id}"
|
||||
th:data-max-amount="${lic.getResteAPayer().add(paiement.montant)}"
|
||||
onclick="openEditPaiementModal(this.getAttribute('data-paiement-id'), this.getAttribute('data-montant'), this.getAttribute('data-date'), this.getAttribute('data-mode-id'), this.getAttribute('data-licence-id'), this.getAttribute('data-max-amount'))"
|
||||
th:data-cheque="${paiement.numeroCheque}"
|
||||
th:data-commentaire="${paiement.commentaire}"
|
||||
onclick="openEditPaiementModal(this.getAttribute('data-paiement-id'), this.getAttribute('data-montant'), this.getAttribute('data-date'), this.getAttribute('data-mode-id'), this.getAttribute('data-licence-id'), this.getAttribute('data-max-amount'), this.getAttribute('data-cheque'), this.getAttribute('data-commentaire'))"
|
||||
class="text-blue-600 hover:text-blue-900 bg-blue-50 hover:bg-blue-100 p-1.5 rounded transition-colors inline-flex items-center"
|
||||
title="Modifier">
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -354,17 +365,10 @@
|
||||
</div>
|
||||
<div class="text-[10px] text-gray-400 mb-2 truncate" th:title="${dot.equipement.description}" th:text="${dot.equipement.description != null and !dot.equipement.description.isEmpty() ? dot.equipement.description : 'Pas de description'}">Description</div>
|
||||
<!-- Special dynamic label for equipment style -->
|
||||
<div class="mb-2" th:if="${dot.equipement.nom == 'Maillot' or dot.equipement.nom == 'Short' or dot.equipement.nom == 'Chaussettes'}">
|
||||
<div class="mb-2" th:if="${dot.equipement.gestionSexe}">
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-semibold bg-blue-50 text-blue-700 border border-blue-100 dotation-style-label"
|
||||
th:data-equipement="${dot.equipement.nom}"
|
||||
th:text="${adherent.sexe == 'FEMININ' ? 'Modèle Femme' : 'Modèle Homme'} + ' - ' + ${adherent.typeMaillot == 'GARDIEN' ? 'Gardien' : 'Joueur'}">
|
||||
Modèle Homme - Joueur
|
||||
</span>
|
||||
</div>
|
||||
<div class="mb-2" th:if="${dot.equipement.nom == 'Survêtement'}">
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-semibold bg-indigo-50 text-indigo-700 border border-indigo-100 dotation-style-label"
|
||||
th:data-equipement="${dot.equipement.nom}"
|
||||
th:text="${adherent.sexe == 'FEMININ' ? 'Modèle Femme' : 'Modèle Homme'}">
|
||||
th:text="${adherent.sexe == 'FEMININ' ? 'Modèle Femme' : 'Modèle Homme'} + (${dot.equipement.nom == 'Maillot' or dot.equipement.nom == 'Short' or dot.equipement.nom == 'Chaussettes'} ? ' - ' + (${adherent.typeMaillot == 'GARDIEN' ? 'Gardien' : 'Joueur'}) : '')">
|
||||
Modèle Homme
|
||||
</span>
|
||||
</div>
|
||||
@@ -381,17 +385,43 @@
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-1.5 mb-1.5">
|
||||
<div>
|
||||
<div th:if="${dot.equipement.taillesDisponibles != null and !dot.equipement.taillesDisponibles.trim().isEmpty()}">
|
||||
<label class="block text-[9px] uppercase font-bold text-gray-400">Taille</label>
|
||||
<input type="text" th:name="'taille_' + ${dot.id}" th:value="${dot.taille}" placeholder="S, M, L..."
|
||||
class="w-full text-xs border border-gray-300 rounded px-1 py-0.5 focus:ring-1 focus:ring-blue-500 outline-none">
|
||||
<select th:name="'taille_' + ${dot.id}" class="w-full text-xs border border-gray-300 rounded px-1 py-0.5 focus:ring-1 focus:ring-blue-500 outline-none">
|
||||
<option value="">Choisir...</option>
|
||||
<option th:each="t : ${#strings.arraySplit(dot.equipement.taillesDisponibles, ',')}"
|
||||
th:value="${#strings.trim(t)}"
|
||||
th:text="${#strings.trim(t)}"
|
||||
th:selected="${dot.taille == #strings.trim(t)}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div th:if="${(dot.equipement.taillesDisponibles == null or dot.equipement.taillesDisponibles.trim().isEmpty()) and (dot.taille != null and !dot.taille.isEmpty())}">
|
||||
<label class="block text-[9px] uppercase font-bold text-gray-400">Taille</label>
|
||||
<input type="text" th:name="'taille_' + ${dot.id}" th:value="${dot.taille}" class="w-full text-xs border border-gray-300 rounded px-1 py-0.5 outline-none bg-gray-50 text-gray-500" readonly>
|
||||
</div>
|
||||
|
||||
<div th:if="${dot.equipement.couleursDisponibles != null and !dot.equipement.couleursDisponibles.trim().isEmpty()}">
|
||||
<label class="block text-[9px] uppercase font-bold text-gray-400">Couleur</label>
|
||||
<select th:name="'couleur_' + ${dot.id}" class="w-full text-xs border border-gray-300 rounded px-1 py-0.5 focus:ring-1 focus:ring-blue-500 outline-none">
|
||||
<option value="">Choisir...</option>
|
||||
<option th:each="c : ${#strings.arraySplit(dot.equipement.couleursDisponibles, ',')}"
|
||||
th:value="${#strings.trim(c)}"
|
||||
th:text="${#strings.trim(c)}"
|
||||
th:selected="${dot.couleur == #strings.trim(c)}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div th:if="${(dot.equipement.couleursDisponibles == null or dot.equipement.couleursDisponibles.trim().isEmpty()) and (dot.couleur != null and !dot.couleur.isEmpty())}">
|
||||
<label class="block text-[9px] uppercase font-bold text-gray-400">Couleur</label>
|
||||
<input type="text" th:name="'couleur_' + ${dot.id}" th:value="${dot.couleur}" class="w-full text-xs border border-gray-300 rounded px-1 py-0.5 outline-none bg-gray-50 text-gray-500" readonly>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-1.5 mb-1.5">
|
||||
<div>
|
||||
<label class="block text-[9px] uppercase font-bold text-gray-400">Numéro</label>
|
||||
<input type="text" th:name="'numero_' + ${dot.id}" th:value="${dot.numero}" placeholder="Ex: 10"
|
||||
class="w-full text-xs border border-gray-300 rounded px-1 py-0.5 focus:ring-1 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-[9px] uppercase font-bold text-gray-400">Flocage</label>
|
||||
<input type="text" th:name="'flocage_' + ${dot.id}" th:value="${dot.flocage}" placeholder="Nom du joueur"
|
||||
@@ -510,11 +540,19 @@
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Mode de paiement</label>
|
||||
<select name="modePaiementId" required class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<select id="addPaiementMode" name="modePaiementId" required class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none" onchange="toggleChequeVisibility(this, 'addChequeBlock', 'addNumeroCheque')">
|
||||
<option value="">Sélectionnez un mode...</option>
|
||||
<option th:each="mode : ${modesPaiement}" th:value="${mode.id}" th:text="${mode.nom}"></option>
|
||||
<option th:each="mode : ${modesPaiement}" th:value="${mode.id}" th:data-nom="${#strings.toLowerCase(mode.nom)}" th:text="${mode.nom}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="addChequeBlock" class="hidden">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Numéro du chèque <span class="text-red-500">*</span></label>
|
||||
<input type="text" id="addNumeroCheque" name="numeroCheque" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Commentaire (facultatif)</label>
|
||||
<textarea id="addCommentaire" name="commentaire" rows="2" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none"></textarea>
|
||||
</div>
|
||||
<div class="items-center px-4 py-3 flex justify-end space-x-2">
|
||||
<button type="button" onclick="closePaiementModal()" class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50">Annuler</button>
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-green-600 rounded-lg hover:bg-green-700">Payer</button>
|
||||
@@ -542,11 +580,19 @@
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Mode de paiement</label>
|
||||
<select id="editPaiementMode" name="modePaiementId" required class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<select id="editPaiementMode" name="modePaiementId" required class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none" onchange="toggleChequeVisibility(this, 'editChequeBlock', 'editNumeroCheque')">
|
||||
<option value="">Sélectionnez un mode...</option>
|
||||
<option th:each="mode : ${modesPaiement}" th:value="${mode.id}" th:text="${mode.nom}"></option>
|
||||
<option th:each="mode : ${modesPaiement}" th:value="${mode.id}" th:data-nom="${#strings.toLowerCase(mode.nom)}" th:text="${mode.nom}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="editChequeBlock" class="hidden">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Numéro du chèque <span class="text-red-500">*</span></label>
|
||||
<input type="text" id="editNumeroCheque" name="numeroCheque" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Commentaire (facultatif)</label>
|
||||
<textarea id="editCommentaire" name="commentaire" rows="2" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none"></textarea>
|
||||
</div>
|
||||
<div class="items-center px-4 py-3 flex justify-end space-x-2">
|
||||
<button type="button" onclick="closeEditPaiementModal()" class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50">Annuler</button>
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700">Enregistrer</button>
|
||||
@@ -669,17 +715,35 @@
|
||||
document.getElementById('paiementModal').classList.add('hidden');
|
||||
}
|
||||
|
||||
function openEditPaiementModal(paiementId, montant, date, modePaiementId, licenceId, maxAmount) {
|
||||
function openEditPaiementModal(paiementId, montant, date, modePaiementId, licenceId, maxAmount, numeroCheque, commentaire) {
|
||||
document.getElementById('editPaiementModal').classList.remove('hidden');
|
||||
document.getElementById('editPaiementForm').action = '/paiements/' + paiementId + '/update';
|
||||
document.getElementById('editPaiementMontant').value = montant;
|
||||
document.getElementById('editPaiementMontant').max = maxAmount;
|
||||
document.getElementById('editPaiementDate').value = date;
|
||||
document.getElementById('editPaiementMode').value = modePaiementId;
|
||||
document.getElementById('editNumeroCheque').value = numeroCheque || '';
|
||||
document.getElementById('editCommentaire').value = commentaire || '';
|
||||
toggleChequeVisibility(document.getElementById('editPaiementMode'), 'editChequeBlock', 'editNumeroCheque');
|
||||
}
|
||||
function closeEditPaiementModal() {
|
||||
document.getElementById('editPaiementModal').classList.add('hidden');
|
||||
}
|
||||
|
||||
function toggleChequeVisibility(selectElement, blockId, inputId) {
|
||||
const block = document.getElementById(blockId);
|
||||
const input = document.getElementById(inputId);
|
||||
const selectedOption = selectElement.options[selectElement.selectedIndex];
|
||||
|
||||
if (selectedOption && selectedOption.getAttribute('data-nom') && selectedOption.getAttribute('data-nom').includes('chèque')) {
|
||||
block.classList.remove('hidden');
|
||||
input.required = true;
|
||||
} else {
|
||||
block.classList.add('hidden');
|
||||
input.required = false;
|
||||
input.value = '';
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const dateInput = document.getElementById('dateNaissance');
|
||||
const repBlock = document.getElementById('representantBlock');
|
||||
|
||||
@@ -62,30 +62,95 @@
|
||||
|
||||
<div class="pt-4 border-t border-gray-100">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">Équipements liés à la catégorie</label>
|
||||
<div class="space-y-3 max-h-64 overflow-y-auto">
|
||||
<th:block th:each="equi : ${allEquipements}">
|
||||
<div class="flex items-center space-x-4 bg-gray-50 p-2 rounded-lg border border-gray-100">
|
||||
<div class="w-1/3">
|
||||
|
||||
<div class="flex space-x-2 mb-4">
|
||||
<select id="equipementToAdd" class="flex-1 border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<option value="">Sélectionner un équipement à ajouter...</option>
|
||||
<th:block th:each="equi : ${allEquipements}">
|
||||
<option th:value="${equi.id}" th:text="${equi.nom}"></option>
|
||||
</th:block>
|
||||
</select>
|
||||
<button type="button" onclick="addEquipement()" class="px-4 py-1.5 text-sm font-medium text-white bg-green-600 rounded-lg hover:bg-green-700 transition-colors">Ajouter</button>
|
||||
</div>
|
||||
|
||||
<div id="equipementsContainer" class="space-y-3 max-h-64 overflow-y-auto">
|
||||
<th:block th:each="equi : ${allEquipements}" th:if="${categorie.hasEquipement(equi.id)}">
|
||||
<div class="flex items-center space-x-4 bg-gray-50 p-2 rounded-lg border border-gray-100 equipement-row" th:id="'eq-row-' + ${equi.id}">
|
||||
<div class="w-1/4">
|
||||
<span class="block text-sm font-medium text-gray-900" th:text="${equi.nom}"></span>
|
||||
</div>
|
||||
<div class="w-1/3">
|
||||
<select th:name="'etatEquipement_' + ${equi.id}" class="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<option value="NON_LIE" th:selected="${!categorie.hasEquipement(equi.id)}">Non lié</option>
|
||||
<option value="OBLIGATOIRE" th:selected="${categorie.hasEquipement(equi.id) and categorie.isEquipementObligatoire(equi.id)}">Obligatoire (inclus)</option>
|
||||
<option value="OPTIONNEL" th:selected="${categorie.hasEquipement(equi.id) and !categorie.isEquipementObligatoire(equi.id)}">Optionnel (payant)</option>
|
||||
<option value="OBLIGATOIRE" th:selected="${categorie.isEquipementObligatoire(equi.id)}">Obligatoire (inclus)</option>
|
||||
<option value="OPTIONNEL" th:selected="${!categorie.isEquipementObligatoire(equi.id)}">Optionnel (payant)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="w-1/3 flex items-center space-x-2">
|
||||
<div class="w-1/4 flex items-center space-x-2">
|
||||
<label class="text-xs text-gray-500">Prix (€)</label>
|
||||
<input type="number" step="0.01" th:name="'prixEquipement_' + ${equi.id}"
|
||||
th:value="${categorie.getEquipementPrix(equi.id)}"
|
||||
class="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
<div class="w-auto">
|
||||
<button type="button" th:onclick="'removeEquipement(' + ${equi.id} + ')'" class="text-red-600 hover:text-red-800 text-sm font-medium">Retirer</button>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function addEquipement() {
|
||||
const select = document.getElementById('equipementToAdd');
|
||||
const selectedOption = select.options[select.selectedIndex];
|
||||
|
||||
if (!selectedOption.value) return;
|
||||
|
||||
const id = selectedOption.value;
|
||||
const nom = selectedOption.text;
|
||||
|
||||
if (document.getElementById('eq-row-' + id)) {
|
||||
alert("Cet équipement est déjà lié à la catégorie.");
|
||||
return;
|
||||
}
|
||||
|
||||
const container = document.getElementById('equipementsContainer');
|
||||
|
||||
const row = document.createElement('div');
|
||||
row.className = 'flex items-center space-x-4 bg-gray-50 p-2 rounded-lg border border-gray-100 equipement-row';
|
||||
row.id = 'eq-row-' + id;
|
||||
|
||||
row.innerHTML = `
|
||||
<div class="w-1/4">
|
||||
<span class="block text-sm font-medium text-gray-900">${nom}</span>
|
||||
</div>
|
||||
<div class="w-1/3">
|
||||
<select name="etatEquipement_${id}" class="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<option value="OBLIGATOIRE">Obligatoire (inclus)</option>
|
||||
<option value="OPTIONNEL">Optionnel (payant)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="w-1/4 flex items-center space-x-2">
|
||||
<label class="text-xs text-gray-500">Prix (€)</label>
|
||||
<input type="number" step="0.01" name="prixEquipement_${id}" value="0.00" class="w-full border border-gray-300 rounded-lg px-3 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
<div class="w-auto">
|
||||
<button type="button" onclick="removeEquipement(${id})" class="text-red-600 hover:text-red-800 text-sm font-medium">Retirer</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.appendChild(row);
|
||||
select.value = '';
|
||||
}
|
||||
|
||||
function removeEquipement(id) {
|
||||
const row = document.getElementById('eq-row-' + id);
|
||||
if (row) {
|
||||
row.remove();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="pt-4 flex justify-end space-x-3 border-t border-gray-100">
|
||||
<a th:href="@{/categories}" class="px-4 py-2 text-sm font-medium text-gray-700 border border-gray-300 rounded-lg hover:bg-gray-50">Annuler</a>
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700">Enregistrer</button>
|
||||
|
||||
@@ -36,10 +36,28 @@
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Description (ex: Maillot domicile officiel)</label>
|
||||
<textarea th:field="*{description}" rows="3" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none"></textarea>
|
||||
</div>
|
||||
<div class="pt-4 border-t border-gray-100">
|
||||
<h3 class="text-sm font-medium text-gray-900 mb-4">Options de déclinaison (facultatif)</h3>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox" th:field="*{gestionSexe}" class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
|
||||
<label class="ml-2 block text-sm text-gray-700">Gérer les coupes Homme/Femme</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Tailles disponibles</label>
|
||||
<input type="text" th:field="*{taillesDisponibles}" placeholder="ex: XS, S, M, L, XL ou 5/6 ANS, 7/8 ANS..." class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<p class="text-xs text-gray-500 mt-1">Séparez les tailles par des virgules. Laissez vide si taille unique ou standard.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Couleurs disponibles</label>
|
||||
<input type="text" th:field="*{couleursDisponibles}" placeholder="ex: Bleu, Rouge, Blanc..." class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<p class="text-xs text-gray-500 mt-1">Séparez les couleurs par des virgules. Laissez vide si couleur unique.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-4 flex justify-end space-x-3 border-t border-gray-100">
|
||||
<a th:href="@{/equipements}" class="px-4 py-2 text-sm font-medium text-gray-700 border border-gray-300 rounded-lg hover:bg-gray-50">Annuler</a>
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700">Enregistrer</button>
|
||||
|
||||
Reference in New Issue
Block a user