fix: recalculate member category and tariffs dynamically on birthdate change

This commit is contained in:
2026-05-30 00:14:02 +02:00
parent 0baca4a334
commit 3ae296aa91
3 changed files with 189 additions and 2 deletions
@@ -322,8 +322,11 @@
<select id="categorieSelect" name="categorieId" 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:data-nom="${cat.nom}"
th:data-annee-min="${cat.anneeMin}"
th:data-annee-max="${cat.anneeMax}"
th:data-tarif-base="${cat.tarifBase}"
th:data-tarif-exterieur="${cat.tarifExterieur}"
th:text="${cat.nom} + ' (Talange: ' + ${cat.tarifBase} + ' € / Ext: ' + ${cat.tarifExterieur} + ' €)'"></option>
</select>
</div>
@@ -443,6 +446,7 @@
document.addEventListener("DOMContentLoaded", function() {
const dateInput = document.getElementById('dateNaissance');
const repBlock = document.getElementById('representantBlock');
const residentCheckbox = document.getElementById('residentTalange');
function calculateAge(birthday) {
const ageDifMs = Date.now() - birthday.getTime();
@@ -464,7 +468,92 @@
}
}
dateInput.addEventListener('change', updateRepresentantBlock);
function updateLicencesCategoryAndPrices() {
if (!dateInput.value) return;
const dob = new Date(dateInput.value);
const birthYear = dob.getFullYear();
const isResident = residentCheckbox ? residentCheckbox.checked : true;
const categories = [];
const catSelect = document.getElementById('categorieSelect');
if (catSelect) {
Array.from(catSelect.options).forEach(opt => {
const id = opt.value;
const nom = opt.getAttribute('data-nom');
const min = parseInt(opt.getAttribute('data-annee-min'));
const max = parseInt(opt.getAttribute('data-annee-max'));
const tarifBase = parseFloat(opt.getAttribute('data-tarif-base') || '0');
const tarifExterieur = parseFloat(opt.getAttribute('data-tarif-exterieur') || '0');
if (id) {
categories.push({ id, nom, min, max, tarifBase, tarifExterieur });
}
});
}
if (categories.length === 0) return;
const matchingCat = categories.find(c => birthYear >= c.min && birthYear <= c.max);
if (!matchingCat) return;
document.querySelectorAll('.licence-row').forEach(row => {
row.setAttribute('data-tarif-base', matchingCat.tarifBase);
row.setAttribute('data-tarif-exterieur', matchingCat.tarifExterieur);
const baseTarif = isResident ? matchingCat.tarifBase : matchingCat.tarifExterieur;
const equipContrib = parseFloat(row.getAttribute('data-equipements-contrib') || '0');
const totalPaye = parseFloat(row.getAttribute('data-total-paye') || '0');
const newTotal = baseTarif + equipContrib;
const newReste = Math.max(0, newTotal - totalPaye);
const catCell = row.querySelector('.cell-tarif-categorie');
if (catCell) {
const parentTd = catCell.parentNode;
const spanName = parentTd.querySelector('span:not(.cell-tarif-categorie)');
if (spanName) {
spanName.textContent = matchingCat.nom;
}
catCell.textContent = baseTarif.toFixed(2) + ' € (Catégorie)';
}
const globalCell = row.querySelector('.cell-tarif-global');
if (globalCell) {
globalCell.textContent = newTotal.toFixed(2) + ' €';
}
const resteCell = row.querySelector('.cell-reste-payer');
if (resteCell) {
resteCell.textContent = newReste.toFixed(2) + ' €';
if (newReste === 0) {
resteCell.classList.remove('text-red-600');
resteCell.classList.add('text-green-600');
} else {
resteCell.classList.remove('text-green-600');
resteCell.classList.add('text-red-600');
}
}
const payerBtn = row.querySelector('.btn-payer');
if (payerBtn) {
if (newReste > 0) {
payerBtn.classList.remove('hidden');
const licId = payerBtn.getAttribute('data-licence-id');
payerBtn.setAttribute('onclick', `openPaiementModal(${licId}, ${newReste})`);
} else {
payerBtn.classList.add('hidden');
}
}
const modifierBtn = row.querySelector('button[onclick^="openLicenceModal"]');
if (modifierBtn) {
modifierBtn.setAttribute('data-categorie-id', matchingCat.id);
}
});
}
dateInput.addEventListener('change', function() {
updateRepresentantBlock();
updateLicencesCategoryAndPrices();
});
// Initial check in case it's a validation error reload
updateRepresentantBlock();
@@ -475,7 +564,6 @@
}
// Recalculate price dynamically when residentTalange checkbox changes
const residentCheckbox = document.getElementById('residentTalange');
if (residentCheckbox) {
residentCheckbox.addEventListener('change', function() {
const isResident = this.checked;