feat: Refonte du schéma Adhérent (Lieu de naissance, Nationalité, Type Licence), suppression du téléphone, email obligatoire
This commit is contained in:
@@ -64,16 +64,38 @@
|
||||
<p th:if="${#fields.hasErrors('dateNaissance')}" th:errors="*{dateNaissance}" class="mt-1 text-xs text-red-600"></p>
|
||||
</div>
|
||||
|
||||
<!-- Téléphone -->
|
||||
<!-- Lieu de naissance (Ville) -->
|
||||
<div>
|
||||
<label for="telephone" class="block text-sm font-medium text-gray-700 mb-1">Téléphone</label>
|
||||
<input type="tel" id="telephone" th:field="*{telephone}"
|
||||
<label for="lieuNaissanceVille" class="block text-sm font-medium text-gray-700 mb-1">Ville de naissance <span class="text-red-500">*</span></label>
|
||||
<input type="text" id="lieuNaissanceVille" th:field="*{lieuNaissanceVille}" required
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
|
||||
th:classappend="${#fields.hasErrors('telephone')} ? 'border-red-500' : ''">
|
||||
<p th:if="${#fields.hasErrors('telephone')}" th:errors="*{telephone}" class="mt-1 text-xs text-red-600"></p>
|
||||
th:classappend="${#fields.hasErrors('lieuNaissanceVille')} ? 'border-red-500' : ''">
|
||||
<p th:if="${#fields.hasErrors('lieuNaissanceVille')}" th:errors="*{lieuNaissanceVille}" class="mt-1 text-xs text-red-600"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Lieu de naissance (Pays) -->
|
||||
<div>
|
||||
<label for="lieuNaissancePays" class="block text-sm font-medium text-gray-700 mb-1">Pays de naissance <span class="text-red-500">*</span></label>
|
||||
<input type="text" id="lieuNaissancePays" th:field="*{lieuNaissancePays}" required
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
|
||||
th:classappend="${#fields.hasErrors('lieuNaissancePays')} ? 'border-red-500' : ''">
|
||||
<p th:if="${#fields.hasErrors('lieuNaissancePays')}" th:errors="*{lieuNaissancePays}" class="mt-1 text-xs text-red-600"></p>
|
||||
</div>
|
||||
|
||||
<!-- Nationalité -->
|
||||
<div>
|
||||
<label for="nationalite" class="block text-sm font-medium text-gray-700 mb-1">Nationalité <span class="text-red-500">*</span></label>
|
||||
<input type="text" id="nationalite" th:field="*{nationalite}" required
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
|
||||
th:classappend="${#fields.hasErrors('nationalite')} ? 'border-red-500' : ''">
|
||||
<p th:if="${#fields.hasErrors('nationalite')}" th:errors="*{nationalite}" class="mt-1 text-xs text-red-600"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Removed telephone -->
|
||||
|
||||
<!-- Représentant Légal (Dynamique) -->
|
||||
<div id="representantBlock" class="hidden-block bg-blue-50 p-4 rounded-lg border border-blue-100">
|
||||
<label for="representantLegal" class="block text-sm font-medium text-blue-800 mb-1">
|
||||
@@ -89,20 +111,12 @@
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Email -->
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium text-gray-700 mb-1">Email</label>
|
||||
<input type="email" id="email" th:field="*{email}"
|
||||
<label for="email" class="block text-sm font-medium text-gray-700 mb-1">Email <span class="text-red-500">*</span></label>
|
||||
<input type="email" id="email" th:field="*{email}" required
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
|
||||
th:classappend="${#fields.hasErrors('email')} ? 'border-red-500' : ''">
|
||||
<p th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="mt-1 text-xs text-red-600"></p>
|
||||
</div>
|
||||
|
||||
<!-- Résident Talange -->
|
||||
<div class="flex items-center space-x-3 mt-7">
|
||||
<input type="checkbox" id="residentTalange" th:field="*{residentTalange}" class="w-5 h-5 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
|
||||
<label for="residentTalange" class="text-sm font-medium text-gray-700">
|
||||
Résident de la commune de Talange
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
@@ -125,14 +139,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Adresse -->
|
||||
<div>
|
||||
<label for="adresse" class="block text-sm font-medium text-gray-700 mb-1">Adresse postale</label>
|
||||
<textarea id="adresse" th:field="*{adresse}" rows="3"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
|
||||
th:classappend="${#fields.hasErrors('adresse')} ? 'border-red-500' : ''"></textarea>
|
||||
<p th:if="${#fields.hasErrors('adresse')}" th:errors="*{adresse}" class="mt-1 text-xs text-red-600"></p>
|
||||
</div>
|
||||
<!-- Removed Adresse -->
|
||||
|
||||
<div class="pt-4 flex justify-end space-x-3 border-t border-gray-100">
|
||||
<a th:href="@{/adherents}" class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors">Annuler</a>
|
||||
@@ -150,11 +157,13 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table class="w-full text-left border-collapse">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse min-w-[800px]">
|
||||
<thead>
|
||||
<tr class="bg-gray-50 text-gray-500 text-sm uppercase tracking-wider border-b border-gray-200">
|
||||
<th class="py-3 px-4 font-medium">Saison</th>
|
||||
<th class="py-3 px-4 font-medium">Catégorie</th>
|
||||
<th class="py-3 px-4 font-medium">Demande / Type</th>
|
||||
<th class="py-3 px-4 font-medium">N° Licence</th>
|
||||
<th class="py-3 px-4 font-medium">État</th>
|
||||
<th class="py-3 px-4 font-medium">Tarif Global</th>
|
||||
@@ -164,7 +173,7 @@
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 text-sm">
|
||||
<tr th:if="${#lists.isEmpty(licences)}">
|
||||
<td colspan="7" class="py-4 px-4 text-center text-gray-500">Aucune licence enregistrée.</td>
|
||||
<td colspan="8" class="py-4 px-4 text-center text-gray-500">Aucune licence enregistrée.</td>
|
||||
</tr>
|
||||
<th:block th:each="lic : ${licences}">
|
||||
<tr class="hover:bg-gray-50 border-b border-gray-100 licence-row"
|
||||
@@ -177,6 +186,10 @@
|
||||
<span th:text="${lic.categorie.nom + (lic.equipe != null ? ' (' + lic.equipe.nom + ')' : '')}">U15</span>
|
||||
<span class="text-[10px] text-gray-400 block cell-tarif-categorie" th:text="${(lic.adherent != null && lic.adherent.residentTalange ? lic.categorie.tarifBase : lic.categorie.tarifExterieur) + ' € (Catégorie)'}">100.00 € (Catégorie)</span>
|
||||
</td>
|
||||
<td class="py-4 px-4 text-gray-600 text-xs">
|
||||
<div th:text="${lic.typeDemande != null ? lic.typeDemande : '-'}">Nouvelle</div>
|
||||
<div class="text-[10px] text-gray-500" th:text="${lic.typeLicence != null ? lic.typeLicence : '-'}">Libre</div>
|
||||
</td>
|
||||
<td class="py-4 px-4 text-gray-600 font-mono text-xs" th:text="${lic.numeroLicence != null and !lic.numeroLicence.isEmpty() ? lic.numeroLicence : '-'}">-</td>
|
||||
<td class="py-4 px-4">
|
||||
<span class="px-2 py-1 text-xs font-semibold rounded-full"
|
||||
@@ -193,8 +206,10 @@
|
||||
th:data-categorie-id="${lic.categorie.id}"
|
||||
th:data-numero-licence="${lic.numeroLicence}"
|
||||
th:data-etat="${lic.etat}"
|
||||
th:data-type-demande="${lic.typeDemande}"
|
||||
th:data-type-licence="${lic.typeLicence}"
|
||||
th:data-equipe-id="${lic.equipe != null ? lic.equipe.id : ''}"
|
||||
onclick="openLicenceModal(this.getAttribute('data-licence-id'), this.getAttribute('data-categorie-id'), this.getAttribute('data-numero-licence'), this.getAttribute('data-etat'), this.getAttribute('data-equipe-id'))"
|
||||
onclick="openLicenceModal(this.getAttribute('data-licence-id'), this.getAttribute('data-categorie-id'), this.getAttribute('data-numero-licence'), this.getAttribute('data-etat'), this.getAttribute('data-type-demande'), this.getAttribute('data-type-licence'), this.getAttribute('data-equipe-id'))"
|
||||
class="text-blue-600 hover:text-blue-800 font-medium bg-blue-50 px-3 py-1 rounded-lg">Modifier</button>
|
||||
<button th:if="${lic.getResteAPayer() > 0}"
|
||||
type="button"
|
||||
@@ -205,7 +220,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:if="${!#lists.isEmpty(lic.paiements)}" class="bg-gray-50/50">
|
||||
<td colspan="7" class="py-3 px-6">
|
||||
<td colspan="8" class="py-3 px-6">
|
||||
<div class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">Historique des paiements</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 bg-white rounded-lg border border-gray-200 shadow-sm text-xs">
|
||||
@@ -344,8 +359,8 @@
|
||||
</tr>
|
||||
</th:block>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
@@ -382,6 +397,27 @@
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Numéro de licence</label>
|
||||
<input id="numeroLicenceInput" type="text" name="numeroLicence" placeholder="Ex: FFF-123456" 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">Type de demande</label>
|
||||
<select id="typeDemandeSelect" name="typeDemande" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<option value="">Sélectionnez...</option>
|
||||
<option value="Renouvellement">Renouvellement</option>
|
||||
<option value="Nouvelle demande">Nouvelle demande</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Type de licence</label>
|
||||
<select id="typeLicenceSelect" name="typeLicence" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<option value="">Sélectionnez...</option>
|
||||
<option value="Animateur">Animateur</option>
|
||||
<option value="Arbitre">Arbitre</option>
|
||||
<option value="Dirigeant">Dirigeant</option>
|
||||
<option value="Educateur Fédéral">Educateur Fédéral</option>
|
||||
<option value="Foot loisir">Foot loisir</option>
|
||||
<option value="Libre">Libre</option>
|
||||
<option value="Technique">Technique</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Saison</label>
|
||||
<input id="saisonInput" type="text" name="saison" value="Saison Actuelle" readonly class="w-full border border-gray-200 bg-gray-50 rounded-lg px-4 py-2 text-sm text-gray-500 outline-none cursor-not-allowed">
|
||||
@@ -468,7 +504,7 @@
|
||||
</div>
|
||||
|
||||
<script th:inline="javascript">
|
||||
function openLicenceModal(licenceId = null, categorieId = '', numeroLicence = '', etat = 'Brouillon', equipeId = '') {
|
||||
function openLicenceModal(licenceId = null, categorieId = '', numeroLicence = '', etat = 'Brouillon', typeDemande = '', typeLicence = '', equipeId = '') {
|
||||
document.getElementById('licenceModal').classList.remove('hidden');
|
||||
const form = document.getElementById('licenceForm');
|
||||
const title = document.getElementById('licenceModalTitle');
|
||||
@@ -485,6 +521,8 @@
|
||||
catSelect.value = categorieId;
|
||||
document.getElementById('numeroLicenceInput').value = numeroLicence;
|
||||
document.getElementById('etatSelect').value = etat;
|
||||
document.getElementById('typeDemandeSelect').value = typeDemande;
|
||||
document.getElementById('typeLicenceSelect').value = typeLicence;
|
||||
|
||||
// Fetch and populate teams
|
||||
if (categorieId) {
|
||||
@@ -500,6 +538,8 @@
|
||||
form.action = '/adherents/' + adherentId + '/licences';
|
||||
document.getElementById('numeroLicenceInput').value = '';
|
||||
document.getElementById('etatSelect').value = 'Brouillon';
|
||||
document.getElementById('typeDemandeSelect').value = '';
|
||||
document.getElementById('typeLicenceSelect').value = '';
|
||||
|
||||
// Pré-sélection de la catégorie selon l'année de naissance
|
||||
const dateNaissanceStr = document.getElementById('dateNaissance').value;
|
||||
|
||||
@@ -27,9 +27,26 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Date de naissance <span class="text-red-500">*</span></label>
|
||||
<input type="date" id="dateNaissance" th:field="*{dateNaissance}" 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">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Date de naissance <span class="text-red-500">*</span></label>
|
||||
<input type="date" id="dateNaissance" th:field="*{dateNaissance}" 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">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Ville de naissance <span class="text-red-500">*</span></label>
|
||||
<input type="text" th:field="*{lieuNaissanceVille}" 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">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Pays de naissance <span class="text-red-500">*</span></label>
|
||||
<input type="text" th:field="*{lieuNaissancePays}" 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">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Nationalité <span class="text-red-500">*</span></label>
|
||||
<input type="text" th:field="*{nationalite}" 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">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="representantBlock" class="hidden bg-blue-50 p-4 rounded-lg border border-blue-100">
|
||||
@@ -38,21 +55,12 @@
|
||||
<input type="text" id="representantLegal" th:field="*{representantLegal}" placeholder="Nom et Prénom du parent" 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 class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Téléphone</label>
|
||||
<input type="tel" th:field="*{telephone}" 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">Email</label>
|
||||
<input type="email" th:field="*{email}" 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">Email <span class="text-red-500">*</span></label>
|
||||
<input type="email" th:field="*{email}" 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">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Adresse postale</label>
|
||||
<textarea th:field="*{adresse}" 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>
|
||||
<!-- Removed Adresse -->
|
||||
|
||||
<button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-4 rounded-lg transition-colors mt-4">
|
||||
Soumettre le dossier
|
||||
|
||||
Reference in New Issue
Block a user