feat: implement educator management and display educator initials on training schedule
AS Talange CI/CD Pipeline / Build & Run Unit Tests (push) Successful in 3m2s
AS Talange CI/CD Pipeline / Build & Run in Docker Container (push) Successful in 3m20s

This commit is contained in:
2026-06-01 21:44:02 +02:00
parent e39921f049
commit aba4ed0770
12 changed files with 349 additions and 4 deletions
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Éducateur - AS Talange</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style> body { font-family: 'Inter', sans-serif; } </style>
</head>
<body class="bg-gray-50 text-gray-900 flex h-screen overflow-hidden">
<!-- Sidebar -->
<div th:replace="~{fragments/sidebar :: sidebar}"></div>
<main class="flex-1 flex flex-col h-screen overflow-hidden">
<header class="h-16 bg-white border-b border-gray-200 flex items-center px-6">
<h2 class="text-lg font-semibold text-gray-800" th:text="${educateur.id == null ? 'Nouvel Éducateur' : 'Modifier Éducateur'}">Éducateur</h2>
</header>
<div class="flex-1 overflow-auto p-6">
<div class="max-w-xl mx-auto bg-white rounded-xl shadow-sm border border-gray-100 p-8">
<form th:action="@{/educateurs}" th:object="${educateur}" method="post" class="space-y-6">
<input type="hidden" th:field="*{id}" />
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1 font-semibold">Nom <span class="text-red-500">*</span></label>
<input type="text" th:field="*{nom}" 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 font-semibold">Prénom <span class="text-red-500">*</span></label>
<input type="text" th:field="*{prenom}" 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>
<label class="block text-sm font-medium text-gray-700 mb-1 font-semibold">Numéro de Téléphone (non obligatoire)</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 font-semibold">Adresse E-mail (facultatif)</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 class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1 font-semibold">Catégorie</label>
<select th:field="*{categorie}" 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="">-- Aucune --</option>
<option th:each="cat : ${categories}" th:value="${cat.id}" th:text="${cat.nom}">U15</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1 font-semibold">Équipe</label>
<select th:field="*{equipe}" 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="">-- Aucune --</option>
<option th:each="equip : ${equipes}" th:value="${equip.id}" th:text="${equip.nom + ' (' + equip.categorie.nom + ')'}">Équipe A (U15)</option>
</select>
</div>
</div>
<div class="pt-4 flex justify-end space-x-3 border-t border-gray-100">
<a th:href="@{/educateurs}" 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>
</div>
</form>
</div>
</div>
</main>
</body>
</html>
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Paramétrage - Éducateurs</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style> body { font-family: 'Inter', sans-serif; } </style>
</head>
<body class="bg-gray-50 text-gray-900 flex h-screen overflow-hidden">
<!-- Sidebar -->
<div th:replace="~{fragments/sidebar :: sidebar}"></div>
<main class="flex-1 flex flex-col h-screen overflow-hidden">
<header class="h-16 bg-white border-b border-gray-200 flex items-center px-6">
<h2 class="text-lg font-semibold text-gray-800">Éducateurs / Entraîneurs</h2>
</header>
<div class="flex-1 overflow-auto p-6">
<div class="flex justify-between items-center mb-6">
<h3 class="text-xl font-bold text-gray-900">Liste des Éducateurs</h3>
<a th:href="@{/educateurs/new}" class="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-blue-700">
+ Nouvel Éducateur
</a>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-left border-collapse">
<thead>
<tr class="bg-gray-50 text-gray-500 text-sm uppercase tracking-wider border-b border-gray-200">
<th class="py-3 px-6 font-medium text-left">Nom</th>
<th class="py-3 px-6 font-medium text-left">Prénom</th>
<th class="py-3 px-6 font-medium text-left">Téléphone</th>
<th class="py-3 px-6 font-medium text-left">Email</th>
<th class="py-3 px-6 font-medium text-left">Catégorie</th>
<th class="py-3 px-6 font-medium text-left">Équipe</th>
<th class="py-3 px-6 font-medium text-right">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 text-sm">
<tr th:if="${#lists.isEmpty(educateurs)}">
<td colspan="7" class="py-8 text-center text-gray-500">Aucun éducateur n'est paramétré.</td>
</tr>
<tr th:each="ed : ${educateurs}" class="hover:bg-gray-50 transition-colors">
<td class="py-4 px-6 font-medium text-gray-900" th:text="${ed.nom}">Dupont</td>
<td class="py-4 px-6 text-gray-600" th:text="${ed.prenom}">Jean</td>
<td class="py-4 px-6 text-gray-600" th:text="${ed.telephone != null and !ed.telephone.isEmpty() ? ed.telephone : '-'}">-</td>
<td class="py-4 px-6 text-gray-600" th:text="${ed.email != null and !ed.email.isEmpty() ? ed.email : '-'}">-</td>
<td class="py-4 px-6 text-gray-600">
<span th:if="${ed.categorie != null}" th:text="${ed.categorie.nom}" class="px-2.5 py-1 rounded-full text-xs font-semibold bg-blue-100 text-blue-800">U15</span>
<span th:if="${ed.categorie == null}">-</span>
</td>
<td class="py-4 px-6 text-gray-600">
<span th:if="${ed.equipe != null}" th:text="${ed.equipe.nom}" class="px-2.5 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-800">Équipe A</span>
<span th:if="${ed.equipe == null}">-</span>
</td>
<td class="py-4 px-6 text-right flex justify-end space-x-3 items-center">
<a th:href="@{/educateurs/{id}/edit(id=${ed.id})}" class="text-indigo-600 hover:text-indigo-900 font-medium bg-indigo-50 px-3 py-1 rounded-lg">Modifier</a>
<form th:action="@{/educateurs/{id}/delete(id=${ed.id})}" method="post" onsubmit="return confirm('Supprimer cet éducateur ?');">
<button type="submit" class="text-red-600 hover:text-red-800 font-medium">Supprimer</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
</body>
</html>