Files
as-talange/as-talange-web/src/main/resources/templates/public/formulaire.html
T
ucef af31766134
AS Talange CI/CD Pipeline / Build & Run Unit Tests (push) Successful in 3m52s
AS Talange CI/CD Pipeline / Deploy to Test Environment (push) Successful in 5m17s
feat: use exhaustive standard sizes list in pre-registration and adjust layout
2026-07-07 21:55:01 +02:00

302 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<script src="https://unpkg.com/htmx.org@1.9.11"></script>
<meta charset="UTF-8">
<title>AS Talange - Formulaire d'inscription</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; }
.was-validated input:invalid, .was-validated select:invalid {
border-color: #ef4444 !important;
background-color: #fef2f2 !important;
}
.was-validated input[type="radio"]:invalid, .was-validated input[type="checkbox"]:invalid {
outline: 2px solid #ef4444;
outline-offset: 2px;
}
</style>
</head>
<body class="bg-gray-50 flex items-center justify-center min-h-screen py-12">
<div class="max-w-xl w-full bg-white rounded-xl shadow-md p-8 border border-gray-100">
<img src="/images/logo.png" alt="AS Talange" class="h-24 w-auto mx-auto mb-4 object-contain drop-shadow-sm" onerror="this.style.display='none'">
<h2 class="text-2xl font-bold text-gray-900 mb-2 text-center">Formulaire de pré-inscription</h2>
<p class="text-sm text-gray-500 mb-8 text-center">Veuillez remplir les informations concernant le futur licencié.</p>
<div class="mb-6 p-4 bg-blue-50 border-l-4 border-blue-500 text-blue-700 text-sm rounded">
<h3 class="font-bold mb-1">Information sur le type de demande</h3>
<ul class="list-disc pl-5 space-y-1">
<li><strong>Nouvelle licence :</strong> Concerne les personnes qui n'étaient pas inscrites au club la saison précédente.</li>
<li><strong>Renouvellement :</strong> Réservé aux personnes déjà inscrites au club la saison précédente.</li>
</ul>
</div>
<form th:action="@{/inscription-public/formulaire}" th:object="${preInscription}" method="post" class="space-y-6" novalidate>
<input type="hidden" name="token" th:value="${tokenUuid}" />
<div class="space-y-3">
<label class="block text-sm font-medium text-gray-700">Type de demande <span class="text-red-500">*</span></label>
<div class="flex items-center space-x-6">
<label class="flex items-center">
<input type="radio" th:field="*{typeDemande}" value="NOUVELLE" required class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Nouvelle licence</span>
</label>
<label class="flex items-center">
<input type="radio" th:field="*{typeDemande}" value="RENOUVELLEMENT" required class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Renouvellement</span>
</label>
</div>
</div>
<div id="nouvelleLicenceBlock" class="hidden space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Ancien club</label>
<input type="text" id="ancienClub" th:field="*{ancienClub}" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none" placeholder="Nom du club (laisser vide si aucun)">
</div>
<div id="raisonChangementClubBlock" class="hidden">
<label class="block text-sm font-medium text-gray-700 mb-1">Raison du changement de club <span class="text-red-500">*</span></label>
<input type="text" id="raisonChangementClub" th:field="*{raisonChangementClub}" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none" placeholder="Pourquoi souhaitez-vous nous rejoindre ?">
</div>
<div id="ancienneCategorieBlock" class="hidden">
<label class="block text-sm font-medium text-gray-700 mb-1">Ancienne catégorie <span class="text-red-500">*</span></label>
<select id="ancienneCategorie" th:field="*{ancienneCategorie}" 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="NA">NA (Je ne sais plus)</option>
<option value="U6">U6</option>
<option value="U7">U7</option>
<option value="U8">U8</option>
<option value="U9">U9</option>
<option value="U10">U10</option>
<option value="U11">U11</option>
<option value="U12">U12</option>
<option value="U13">U13</option>
<option value="U14">U14</option>
<option value="U15">U15</option>
<option value="U16">U16</option>
<option value="U17">U17</option>
<option value="Senior">Senior</option>
</select>
</div>
<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 rounded-lg">
<h4 class="font-bold text-yellow-800 mb-2">Documents et informations à fournir</h4>
<p class="text-sm text-yellow-700 mb-2">Veuillez préparer les éléments suivants pour finaliser la licence :</p>
<ul class="list-disc pl-5 text-sm text-yellow-700 space-y-1">
<li>Photo didentité</li>
<li>Carte didentité ou passeport de l'adhérent</li>
<li>Livret de famille (si pas de pièce didentité)</li>
<li>Adresse e-mail de l'adhérent (représentant légal en cas de mineur)</li>
<li>Pour les adhérents nés à l'étranger : Passeport + justificatif de domicile (du représentant légal en cas de mineur)</li>
</ul>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Comment avez-vous connu l'AS Talange ?</label>
<input type="text" th:field="*{commentConnuClub}" class="w-full border border-gray-300 rounded-lg px-4 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none" placeholder="Ex: Réseaux sociaux, amis, forum des associations...">
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">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 uppercase">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">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 capitalize">
</div>
</div>
<div class="space-y-3">
<label class="block text-sm font-medium text-gray-700">Sexe <span class="text-red-500">*</span></label>
<div class="flex items-center space-x-6">
<label class="flex items-center">
<input type="radio" th:field="*{sexe}" value="MASCULIN" required class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Masculin</span>
</label>
<label class="flex items-center">
<input type="radio" th:field="*{sexe}" value="FEMININ" required class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Féminin</span>
</label>
</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">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">
<label class="block text-sm font-medium text-blue-800 mb-1">Représentant légal <span class="text-red-500">*</span></label>
<p class="text-xs text-blue-600 mb-2">Obligatoire pour les mineurs.</p>
<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-1 md:grid-cols-2 gap-4">
<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">Téléphone <span class="text-red-500">*</span></label>
<input type="tel" th:field="*{telephone}" 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">Taille de vêtement souhaitée (équipement)</label>
<select th:field="*{tailleVetement}" 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 taille...</option>
<option th:each="taille : ${taillesDisponibles}" th:value="${taille}" th:text="${taille}"></option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Pointure souhaitée (chaussettes)</label>
<select th:field="*{pointure}" 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 pointure...</option>
<option th:each="pt : ${pointuresDisponibles}" th:value="${pt}" th:text="${pt}"></option>
</select>
</div>
</div>
<div class="flex items-start pt-2">
<div class="flex items-center h-5">
<input id="consentementRgpd" name="consentementRgpd" type="checkbox" required class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
</div>
<div class="ml-3 text-sm">
<label for="consentementRgpd" class="font-medium text-gray-700">Consentement RGPD <span class="text-red-500">*</span></label>
<p class="text-gray-500 text-xs mt-1">J'accepte que l'AS Talange recueille et traite ces données pour la gestion de mon inscription et la logistique de la saison.</p>
</div>
</div>
<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
</button>
<p class="text-[10px] text-gray-400 text-center mt-4 leading-tight">
Les données sont stockées de manière sécurisée, accessibles uniquement au bureau du club. Vous pouvez demander leur suppression à tout moment.
</p>
<p class="text-[10px] text-gray-400 text-center mt-2">
v<span th:text="${appVersion}">1.0-SNAPSHOT</span>
</p>
</form>
</div>
<script>
const form = document.querySelector('form');
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault();
let errorMsg = document.getElementById('form-error-msg');
if (!errorMsg) {
errorMsg = document.createElement('div');
errorMsg.id = 'form-error-msg';
errorMsg.className = 'mb-6 p-4 bg-red-50 border-l-4 border-red-500 text-red-700 text-sm rounded transition-all duration-300';
errorMsg.innerHTML = '<h3 class="font-bold">Erreur de validation</h3><p>Veuillez renseigner tous les champs obligatoires (encadrés en rouge).</p>';
form.insertBefore(errorMsg, form.firstChild);
}
}
form.classList.add('was-validated');
// Scroll to the first invalid element for better mobile UX
const firstInvalid = form.querySelector(':invalid');
if (firstInvalid) {
firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
});
const typeDemandeRadios = document.querySelectorAll('input[name="typeDemande"]');
const nouvelleLicenceBlock = document.getElementById('nouvelleLicenceBlock');
typeDemandeRadios.forEach(radio => {
radio.addEventListener('change', function() {
if (this.value === 'NOUVELLE') {
nouvelleLicenceBlock.classList.remove('hidden');
} else {
nouvelleLicenceBlock.classList.add('hidden');
}
});
});
// Trigger on load if already checked (e.g. going back or validation error)
const checkedRadio = document.querySelector('input[name="typeDemande"]:checked');
if (checkedRadio && checkedRadio.value === 'NOUVELLE') {
nouvelleLicenceBlock.classList.remove('hidden');
}
const ancienClubInput = document.getElementById('ancienClub');
const ancienneCategorieBlock = document.getElementById('ancienneCategorieBlock');
const ancienneCategorieSelect = document.getElementById('ancienneCategorie');
const raisonChangementClubBlock = document.getElementById('raisonChangementClubBlock');
const raisonChangementClubInput = document.getElementById('raisonChangementClub');
if (ancienClubInput) {
ancienClubInput.addEventListener('input', function() {
if (this.value.trim().length > 0) {
ancienneCategorieBlock.classList.remove('hidden');
ancienneCategorieSelect.required = true;
raisonChangementClubBlock.classList.remove('hidden');
raisonChangementClubInput.required = true;
} else {
ancienneCategorieBlock.classList.add('hidden');
ancienneCategorieSelect.required = false;
raisonChangementClubBlock.classList.add('hidden');
raisonChangementClubInput.required = false;
}
});
// Initial check
if (ancienClubInput.value.trim().length > 0) {
ancienneCategorieBlock.classList.remove('hidden');
ancienneCategorieSelect.required = true;
raisonChangementClubBlock.classList.remove('hidden');
raisonChangementClubInput.required = true;
}
}
document.getElementById('dateNaissance').addEventListener('change', function() {
const dateInput = this.value;
const repBlock = document.getElementById('representantBlock');
const repInput = document.getElementById('representantLegal');
if (dateInput) {
const dob = new Date(dateInput);
const ageDifMs = Date.now() - dob.getTime();
const ageDate = new Date(ageDifMs);
const age = Math.abs(ageDate.getUTCFullYear() - 1970);
if (age < 18) {
repBlock.classList.remove('hidden');
repInput.required = true;
} else {
repBlock.classList.add('hidden');
repInput.required = false;
}
}
});
</script>
</body>
</html>