feat: add weekly training schedule planning with Gantt chart and conflict detection
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Créneau d'Entraînement - 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 -->
|
||||
<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="${creneau.id == null ? 'Ajouter un Créneau d''Entraînement' : 'Modifier le Créneau d''Entraînement'}">Créneau</h2>
|
||||
</header>
|
||||
|
||||
<!-- Form content -->
|
||||
<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="@{/planning}" th:object="${creneau}" method="post" class="space-y-6">
|
||||
<input type="hidden" th:field="*{id}" />
|
||||
<input type="hidden" th:field="*{saison.id}" th:if="${creneau.saison != null}" />
|
||||
|
||||
<!-- Catégorie -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Catégorie <span class="text-red-500">*</span></label>
|
||||
<select th:field="*{categorie.id}" 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">
|
||||
<option value="">Sélectionnez une catégorie</option>
|
||||
<option th:each="cat : ${categories}" th:value="${cat.id}" th:text="${cat.nom}">U15</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Terrain -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Terrain <span class="text-red-500">*</span></label>
|
||||
<select th:field="*{terrain.id}" 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">
|
||||
<option value="">Sélectionnez un terrain</option>
|
||||
<option th:each="t : ${terrains}" th:value="${t.id}" th:text="${t.nom}">Terrain Vert</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Zone de terrain -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Zone de terrain <span class="text-red-500">*</span></label>
|
||||
<select th:field="*{zone}" 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">
|
||||
<option value="">Sélectionnez la zone occupée</option>
|
||||
<option th:each="z : ${zones}" th:value="${z.name()}" th:text="${z.libelle}">Terrain Complet</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Jour de la semaine -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Jour de la semaine <span class="text-red-500">*</span></label>
|
||||
<select th:field="*{jourSemaine}" 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">
|
||||
<option value="">Sélectionnez le jour</option>
|
||||
<option th:each="j : ${jours}" th:value="${j.name()}" th:text="${j.libelle}">Lundi</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Horaires (Début & Fin) -->
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Heure de début <span class="text-red-500">*</span></label>
|
||||
<input type="time" th:field="*{heureDebut}" required min="08:00" max="22:00"
|
||||
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">Heure de fin <span class="text-red-500">*</span></label>
|
||||
<input type="time" th:field="*{heureFin}" required min="08:00" max="22:00"
|
||||
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>
|
||||
|
||||
<!-- Custom Validation Error Display -->
|
||||
<div th:if="${#fields.hasErrors('heureDebut')}" class="text-red-500 text-xs font-semibold mt-1">
|
||||
<p th:errors="*{heureDebut}"></p>
|
||||
</div>
|
||||
|
||||
<!-- Info notice -->
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 text-xs text-gray-500">
|
||||
<p class="font-semibold text-gray-700 mb-1">Information sur les plages horaires :</p>
|
||||
<p>Les entraînements doivent être planifiés entre 08:00 et 22:00.</p>
|
||||
<p class="mt-1">Les éventuels conflits de superposition d'horaires et de zones de terrain seront calculés et signalés automatiquement sur le tableau de bord.</p>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="pt-4 flex justify-end space-x-3 border-t border-gray-100">
|
||||
<a th:href="@{/planning}" 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>
|
||||
Reference in New Issue
Block a user