diff --git a/ajax_bib_range.php b/ajax_bib_range.php index 60fba08..99cdb02 100644 --- a/ajax_bib_range.php +++ b/ajax_bib_range.php @@ -605,6 +605,45 @@ if ($action == 'save_team_mode') { exit; } + +// MSIN-4379 — Étape 2 +// Endpoint AJAX : sauvegarde ou désactivation de la config auto (epr_bib_auto). +// Paramètres : epr_id, active (0|1), ranges (JSON des epr_bib_id). +// Prochain tour : étape 6–7 (assignation réelle à l'achat, sans passer par cet endpoint). +if ($action == 'save_auto_config') { + + $epr_id = intval($_POST['epr_id'] ?? 0); + $active = intval($_POST['active'] ?? 1) === 1; + $ranges = json_decode($_POST['ranges'] ?? '[]', true); + + if ($epr_id <= 0) { + echo json_encode([ + 'success' => false, + 'message' => 'epr_id invalide' + ]); + exit; + } + + $result = fxSaveBibAutoConfig($epr_id, is_array($ranges) ? $ranges : [], $active); + + if (!$result['success']) { + echo json_encode([ + 'success' => false, + 'message' => $result['message'] ?? 'Erreur' + ]); + exit; + } + + $tabBibStats = fxInfosBibRange($epr_id); + + echo json_encode([ + 'success' => true, + 'auto_active' => !empty($result['auto_active']), + 'html' => renderBibRanges($tabBibStats, $epr_id, 'assign') + ]); + exit; +} + // ===================== // ACTION INVALIDE // ===================== diff --git a/css/style.css b/css/style.css index 9fc7316..4fd14cd 100644 --- a/css/style.css +++ b/css/style.css @@ -1101,6 +1101,30 @@ ul.ms1-menu-compte li a:hover, ul.ms1-menu-compte li a:active { display:none; } +/* MSIN-4379 — Étape 2 : styles du mode « auto » (masque batch, verrouille édition des plages). + Prochain tour : étape 6–7 (logique PHP à l'achat, pas de CSS supplémentaire prévu). */ +.epr-row.auto-mode .btn-assign-batch, +.epr-row.auto-mode .btn-reset, +.epr-row.auto-mode .batch-config-container { + display: none; +} + +.epr-row.auto-mode .btn-auto { + display: none; +} + +.epr-row.auto-mode .btn-save-range, +.epr-row.auto-mode .btn-delete-range, +.epr-row.auto-mode .btn-add-range { + visibility: hidden; +} + +.epr-row.auto-mode .bib-start, +.epr-row.auto-mode .bib-end { + pointer-events: none; + background: #eee; +} + .epr-row.batch-mode .btn-go-batch { display: none; } diff --git a/inc_footer_scripts.php b/inc_footer_scripts.php index 62c64ec..a4181ac 100644 --- a/inc_footer_scripts.php +++ b/inc_footer_scripts.php @@ -1948,6 +1948,189 @@ if ($strLangue == 'fr') { if (moduleBib) { + // ============================================================ + // MSIN-4379 — Étape 2 : assignation automatique (interface JS) + // Prochain tour : étape 6 (fxAssignAutoBibForParticipant), étape 7 (fxMajCommande). + // ============================================================ + + /** MSIN-4379 — Compte les séquences cochées et met à jour le texte d'aide. */ + function updateAutoSelectionInfo(row) { + + if (!row) return; + + let count = row.querySelectorAll('.batch-select-range:checked').length; + let info = row.querySelector('.auto-info'); + + if (!info) return; + + if (count === 0) { + info.textContent = 'Sélectionnez au moins une séquence.'; + } else { + info.textContent = count + ' séquence(s) sélectionnée(s).'; + } + } + + /** MSIN-4379 — Après sauvegarde : badge, libellé du bouton, bouton Désactiver. */ + function syncAutoUiState(row, isActive) { + + if (!row) return; + + let btnAuto = row.querySelector('.btn-auto'); + let badge = row.querySelector('.bib-auto-badge'); + let btnDesactiver = row.querySelector('.btn-desactiver-auto'); + + row.dataset.autoActive = isActive ? '1' : '0'; + + if (isActive) { + row.classList.add('auto-enabled'); + } else { + row.classList.remove('auto-enabled'); + } + + if (btnAuto) { + btnAuto.textContent = isActive ? 'Configurer automatique' : 'Activer automatique'; + btnAuto.classList.toggle('btn-success', isActive); + btnAuto.classList.toggle('btn-secondary', !isActive); + } + + if (badge) { + badge.style.display = isActive ? '' : 'none'; + } + + if (btnDesactiver) { + btnDesactiver.style.display = isActive ? '' : 'none'; + } + } + + /** MSIN-4379 — Quitte le mode édition auto sans sauver ; recharge les plages (mode assign). */ + function exitAutoMode(row) { + + if (!row) return; + + row.classList.remove('auto-mode'); + + let container = row.querySelector('.bib-container'); + if (container) { + container.classList.remove('batch-mode'); + } + + row.querySelectorAll('.bib-start, .bib-end').forEach(input => { + input.removeAttribute('readonly'); + }); + + let autoConfig = row.querySelector('.auto-config-container'); + if (autoConfig) { + autoConfig.style.display = 'none'; + } + + let btnAuto = row.querySelector('.btn-auto'); + if (btnAuto) { + btnAuto.style.display = ''; + } + + let btnBatch = row.querySelector('.btn-assign-batch'); + if (btnBatch) { + btnBatch.style.display = ''; + } + + let btnReset = row.querySelector('.btn-reset'); + if (btnReset) { + btnReset.style.display = ''; + } + + fetch('/ajax_bib_range.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: + 'action=refresh_ranges' + + '&epr_id=' + encodeURIComponent(row.dataset.eprId) + + '&mode=assign' + }) + .then(res => res.json()) + .then(data => { + + if (!data.success) return; + + let bibContainer = row.querySelector('.epr-block:nth-child(2) .bib-container'); + if (bibContainer) { + bibContainer.innerHTML = data.html; + } + + syncBibUiState(row); + }); + } + + /** MSIN-4379 — Ouvre le mode édition : checkboxes, bloc Accepter/Annuler, refresh mode=auto. */ + function enterAutoMode(row) { + + if (!row) return; + + if (row.classList.contains('batch-mode') || row.classList.contains('reset-mode')) { + return; + } + + row.classList.add('auto-mode'); + + let container = row.querySelector('.bib-container'); + if (container) { + container.classList.add('batch-mode'); + } + + row.querySelectorAll('.bib-start, .bib-end').forEach(input => { + input.setAttribute('readonly', true); + }); + + let autoConfig = row.querySelector('.auto-config-container'); + if (autoConfig) { + autoConfig.style.display = 'block'; + } + + let btnAuto = row.querySelector('.btn-auto'); + if (btnAuto) { + btnAuto.style.display = 'none'; + } + + let btnBatch = row.querySelector('.btn-assign-batch'); + if (btnBatch) { + btnBatch.style.display = 'none'; + } + + let btnReset = row.querySelector('.btn-reset'); + if (btnReset) { + btnReset.style.display = 'none'; + } + + fetch('/ajax_bib_range.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: + 'action=refresh_ranges' + + '&epr_id=' + encodeURIComponent(row.dataset.eprId) + + '&mode=auto' + }) + .then(res => res.json()) + .then(data => { + + if (!data.success) return; + + let bibContainer = row.querySelector('.epr-block:nth-child(2) .bib-container'); + if (!bibContainer) return; + + bibContainer.innerHTML = data.html; + bibContainer.classList.add('batch-mode'); + + row.querySelectorAll('.bib-start, .bib-end').forEach(input => { + input.setAttribute('readonly', true); + }); + + updateAutoSelectionInfo(row); + }); + } + function syncBibUiState(row) { let avecEl = row.querySelector('.bib-avec'); @@ -2113,6 +2296,12 @@ if ($strLangue == 'fr') { let row = cb.closest('.epr-row'); if (!row) return; + // MSIN-4379 — En mode auto, pas de logique batch (refresh_ranges / GO). + if (row.classList.contains('auto-mode')) { + updateAutoSelectionInfo(row); + return; + } + if (row.dataset.loading === '1') return; let existing = document.querySelector('.epr-row-view'); if (existing) existing.remove(); @@ -2430,6 +2619,11 @@ if ($strLangue == 'fr') { let row = btnBatch.closest('.epr-row'); if (!row) return; + // MSIN-4379 — Batch et auto sont mutuellement exclusifs. + if (row.classList.contains('auto-mode')) { + return; + } + let container = row.querySelector('.bib-container'); if (!container) return; @@ -2554,6 +2748,11 @@ if ($strLangue == 'fr') { let row = btnReset.closest('.epr-row'); if (!row) return; + // MSIN-4379 — Reset et auto sont mutuellement exclusifs. + if (row.classList.contains('auto-mode')) { + return; + } + let container = row.querySelector('.bib-container'); if (!container) return; @@ -2855,6 +3054,125 @@ if ($strLangue == 'fr') { return; } +// ===================== +// MSIN-4379 — Étape 2 : AUTO DOSSARD (clics Accepter / Annuler / Désactiver / Activer) +// Prochain tour : étape 6–7 (assignation PHP à l'inscription). +// ===================== + let btnAccepterAuto = e.target.closest('.btn-accepter-auto'); + if (btnAccepterAuto) { + + e.preventDefault(); + + let row = btnAccepterAuto.closest('.epr-row'); + if (!row) return; + + let selected = []; + + row.querySelectorAll('.batch-select-range:checked').forEach(cb => { + selected.push(cb.dataset.rangeId); + }); + + if (selected.length === 0) { + alert('Sélectionnez au moins une séquence'); + return; + } + + // MSIN-4379 — Persiste epr_bib_auto=1 sur les séquences choisies (save_auto_config). + fetch('/ajax_bib_range.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: + 'action=save_auto_config' + + '&epr_id=' + encodeURIComponent(row.dataset.eprId) + + '&active=1' + + '&ranges=' + encodeURIComponent(JSON.stringify(selected)) + }) + .then(res => res.json()) + .then(data => { + + if (!data.success) { + alert(data.message || 'Erreur'); + return; + } + + syncAutoUiState(row, true); + exitAutoMode(row); + }); + + return; + } + + // MSIN-4379 — Annule l'édition sans appeler save_auto_config. + let btnAnnulerAuto = e.target.closest('.btn-annuler-auto'); + if (btnAnnulerAuto) { + + e.preventDefault(); + + let row = btnAnnulerAuto.closest('.epr-row'); + if (!row) return; + + exitAutoMode(row); + return; + } + + // MSIN-4379 — Désactive l'auto en base (active=0, toutes les séquences à 0). + let btnDesactiverAuto = e.target.closest('.btn-desactiver-auto'); + if (btnDesactiverAuto) { + + e.preventDefault(); + + let row = btnDesactiverAuto.closest('.epr-row'); + if (!row) return; + + if (!confirm('Désactiver l\'assignation automatique pour cette épreuve ?')) { + return; + } + + fetch('/ajax_bib_range.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: + 'action=save_auto_config' + + '&epr_id=' + encodeURIComponent(row.dataset.eprId) + + '&active=0' + + '&ranges=' + encodeURIComponent('[]') + }) + .then(res => res.json()) + .then(data => { + + if (!data.success) { + alert(data.message || 'Erreur'); + return; + } + + syncAutoUiState(row, false); + exitAutoMode(row); + }); + + return; + } + + // MSIN-4379 — Entrée dans le mode configuration auto. + let btnAuto = e.target.closest('.btn-auto'); + if (btnAuto) { + + e.preventDefault(); + + let row = btnAuto.closest('.epr-row'); + if (!row) return; + + if (row.classList.contains('batch-mode') || row.classList.contains('reset-mode')) { + return; + } + + enterAutoMode(row); + return; + } + // ===================== // CREATE // ===================== diff --git a/php/inc_fx_promoteur.php b/php/inc_fx_promoteur.php index 40886f0..0356b19 100644 --- a/php/inc_fx_promoteur.php +++ b/php/inc_fx_promoteur.php @@ -2636,14 +2636,16 @@ function fxShowBibTool4($str_code, $int_eve_id, $strLangue){ $tabBibStats=fxInfosBibRange(intval($tabEpreuves[$i]['epr_id'])); $infoBib = fxInfosBibEpreuve(intval($tabEpreuves[$i]['epr_id'])); - - - + // MSIN-4379 — Étape 2 : détecte si l'auto est actif (au moins une séquence epr_bib_auto=1). + // Prochain tour : étape 6–7 (assignation à l'achat). + $blnAutoActive = fxIsBibAutoActive((int)$tabEpreuves[$i]['epr_id']); ?> -