Files
ms1inscription-v5/js/v2/bib-assignments.js
stephan ea52e72086 Update anomaly navigation badge functionality and localization, increment version code to 4.72.771
This commit enhances the anomaly navigation badge by updating the label format to include a count of items to review. The JavaScript and PHP files are modified to support this new format, improving user feedback on the number of anomalies. Additionally, new localization keys are added for the formatted label in both French and English. The version code is incremented to 4.72.771 to reflect these updates.
2026-07-08 15:04:30 -04:00

3307 lines
129 KiB
JavaScript
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.

/**
* MSIN-4435 / MSIN-4440 — Bib assignments v4 (#module-bib)
* Chargé uniquement sur inc_tableau_gestion_epreuves.
*/
(function () {
'use strict';
const moduleBib = document.getElementById('module-bib');
if (moduleBib) {
function bibAjaxLangSuffix() {
var lang = moduleBib.dataset.lang || 'fr';
return '&lang=' + encodeURIComponent(lang)
+ '&csrf_token=' + encodeURIComponent(bibCsrfToken());
}
function bibJs(attr) {
return moduleBib.dataset[attr] || '';
}
function bibJsConfirm(attr) {
return bibJs(attr).replace(/\\n/g, '\n');
}
function bibJsFmt(attr) {
var tpl = bibJs(attr);
var args = Array.prototype.slice.call(arguments, 1);
var i = 0;
return tpl.replace(/%d/g, function () {
return String(args[i++] ?? 0);
});
}
var bibLoaderDepth = 0;
function bibLoaderShow() {
if (!window.Ms1Loader) {
return;
}
bibLoaderDepth++;
if (bibLoaderDepth === 1) {
var msg = bibJs('jsLoaderWait');
Ms1Loader.show(msg || undefined);
}
}
function bibLoaderHide() {
if (!window.Ms1Loader) {
return;
}
bibLoaderDepth = Math.max(0, bibLoaderDepth - 1);
if (bibLoaderDepth === 0) {
Ms1Loader.hide();
}
}
/** fetch ajax_bib_range.php — loader plein ecran par defaut (compteur si appels imbriques). */
function bibFetch(url, options, settings) {
settings = settings || {};
var useLoader = settings.loader !== false;
if (useLoader) {
bibLoaderShow();
}
return fetch(url, options).finally(function () {
if (useLoader) {
bibLoaderHide();
}
});
}
var BIB_BATCH_CHUNK_SIZE = 50;
function bibBatchProgressShow(processed, total) {
var intTotal = total > 0 ? total : 1;
var msg = bibJsFmt('jsBatchProgress', processed, intTotal);
if (window.Ms1Loader && Ms1Loader.showProgress) {
Ms1Loader.showProgress(processed, intTotal, msg);
} else {
bibLoaderShow();
}
}
function bibBatchProgressHide() {
if (window.Ms1Loader && Ms1Loader.hide) {
Ms1Loader.hide();
} else {
bibLoaderHide();
}
}
/** MSIN-4436 — Force la fermeture du loader (batch global : évite overlay bloqué). */
function bibBatchProgressForceHide() {
bibLoaderDepth = 0;
bibBatchProgressHide();
}
function bibAfterBatchGoSuccess(row, data, isResetMode, options) {
options = options || {};
let existing = document.querySelector('.epr-row-view');
if (existing) {
existing.remove();
}
if (data.html) {
row.insertAdjacentHTML('afterend', data.html);
}
bibAfterBatchGoRefreshOnly(row, isResetMode, options);
}
function bibAfterBatchGoRefreshOnly(row, isResetMode, options) {
options = options || {};
if (!row) {
return Promise.resolve();
}
if (isResetMode) {
row.classList.remove('reset-mode');
row.dataset.mode = '';
let btnReset = row.querySelector('.btn-reset');
if (btnReset) {
btnReset.textContent = row.dataset.resetLabel || btnReset.textContent;
}
}
row.classList.remove('batch-mode');
let container = row.querySelector('.bib-container');
if (container) {
container.classList.remove('batch-mode');
}
let btnBatch = row.querySelector('.btn-assign-batch');
if (btnBatch) {
btnBatch.textContent = row.dataset.batchLabel || btnBatch.textContent;
}
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.removeAttribute('readonly');
});
row.querySelectorAll('.batch-select-range').forEach(cb => {
cb.checked = false;
cb.disabled = false;
});
syncBibUiState(row);
var useLoader = options.loader !== false;
var skipAnomalies = options.skipAnomalies === true;
var refreshLite = options.refreshLite === true || isResetMode === true;
return bibFetch('/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'
+ (refreshLite ? '&lite=1' : '')
+ bibAjaxLangSuffix()
}, { loader: useLoader })
.then(function (res) {
if (!res.ok) {
throw new Error(bibJs('jsErrGeneric'));
}
return res.json();
})
.then(function (refresh) {
if (!refresh.success) {
return;
}
let containerRef = setBibContainerHtml(row, refresh.html, { skipAnomalies: skipAnomalies });
if (!containerRef) {
return;
}
return bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=batch_analysis'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ bibAjaxLangSuffix()
}, { loader: false })
.then(function (res) { return res.json(); })
.then(function (stats) {
if (!stats.success) {
return;
}
bibSyncEprBibStats(row, stats.info);
syncBibUiState(row);
});
});
}
function bibGetRowSortKeys(row) {
if (!row) {
return { sort1: '', sort2: '' };
}
var s1 = row.querySelector('.batch-order');
var s2 = row.querySelector('.batch-order-2');
return {
sort1: s1 ? s1.value : '',
sort2: s2 ? s2.value : ''
};
}
function bibGetGlobalBatchSortKeys(panel) {
if (!panel) {
return { sort1: '', sort2: '' };
}
var s1 = panel.querySelector('.bib-global-batch-order');
var s2 = panel.querySelector('.bib-global-batch-order-2');
return {
sort1: s1 ? s1.value : '',
sort2: s2 ? s2.value : ''
};
}
function bibAppendBatchSortParams(body, sortKeys) {
sortKeys = sortKeys || {};
return body
+ '&sort_1=' + encodeURIComponent(sortKeys.sort1 || '')
+ '&sort_2=' + encodeURIComponent(sortKeys.sort2 || '');
}
function bibFetchBatchApplyChunk(row, selected, sortKeys, opts) {
opts = opts || {};
sortKeys = sortKeys || bibGetRowSortKeys(row);
var body =
'action=batch_apply_chunk'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
+ bibAppendBatchSortParams('', sortKeys)
+ '&chunk_size=' + BIB_BATCH_CHUNK_SIZE
+ '&total_initial=' + (opts.totalInitial || 0)
+ '&batch_reset=' + (opts.batchReset ? 1 : 0)
+ bibAjaxLangSuffix();
return fetch('/ajax_bib_range.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body
})
.then(function (res) {
if (!res.ok) {
throw new Error(bibJs('jsErrGeneric'));
}
return res.json();
})
.catch(function (err) {
if (err && err.message) {
throw err;
}
throw new Error(bibJs('jsErrGeneric'));
});
}
function bibRunBatchApplyChunks(row, selected, sortKeys, options) {
options = options || {};
var showResult = options.showResult !== false;
var manageLoader = options.manageLoader !== false;
var deferUiRefresh = options.deferUiRefresh === true;
var onProgress = options.onProgress;
var totalInitial = options.totalInitial > 0
? options.totalInitial
: bibRowPendingBibs(row);
var batchReset = true;
var chunkGuard = 0;
var maxChunks = Math.max(50, Math.ceil((totalInitial || 1) / BIB_BATCH_CHUNK_SIZE) + 5);
if (manageLoader) {
bibBatchProgressShow(0, totalInitial > 0 ? totalInitial : 1);
}
function runChunk() {
chunkGuard++;
if (chunkGuard > maxChunks) {
return Promise.reject(new Error(bibJs('jsErrGeneric')));
}
return bibFetchBatchApplyChunk(row, selected, sortKeys, {
batchReset: batchReset,
totalInitial: totalInitial
}).then(function (data) {
if (!data || !data.success) {
throw new Error((data && data.message) || bibJs('jsErrGeneric'));
}
if (data.total_initial) {
totalInitial = data.total_initial;
}
batchReset = false;
var processed = data.processed || 0;
if (onProgress) {
onProgress(processed, totalInitial);
} else if (manageLoader) {
bibBatchProgressShow(processed, totalInitial);
}
if (data.complete) {
if (showResult) {
bibAfterBatchGoSuccess(row, data, false);
} else if (!deferUiRefresh) {
bibAfterBatchGoRefreshOnly(row, false, { loader: false, skipAnomalies: true });
}
return data;
}
return runChunk();
});
}
return runChunk()
.catch(function (err) {
if (manageLoader) {
alert(err.message || bibJs('jsErrGeneric'));
}
throw err;
})
.finally(function () {
if (manageLoader) {
bibBatchProgressHide();
}
});
}
// MSIN-4436 — Batch global (épreuves solo), chargement différé à l'ouverture.
function bibGetGlobalBatchPanel() {
return document.getElementById('bib-global-batch');
}
// MSIN-4440 — Grille outils : un panneau de détail, contenu déplacé depuis #bib-tool-store.
var bibActiveTool = null;
var bibToolContentSlots = {};
function bibGetToolPanel(toolId) {
return document.querySelector('#bib-tool-store [data-bib-tool="' + toolId + '"]');
}
function bibGetToolContentNode(panel, toolId) {
if (!panel) {
return null;
}
if (toolId === 'global_batch') {
return panel.querySelector('.bib-global-batch__body');
}
return panel.querySelector('.epr-content');
}
function bibInvalidateToolSlot(toolId) {
if (bibToolContentSlots[toolId]) {
delete bibToolContentSlots[toolId];
}
}
function bibRestoreToolContent(toolId) {
var slot = bibToolContentSlots[toolId];
if (!slot || !slot.content || !slot.placeholder || !slot.placeholder.parentNode) {
return;
}
slot.placeholder.parentNode.insertBefore(slot.content, slot.placeholder.nextSibling);
if (toolId === 'global_batch') {
slot.content.classList.add('bib-ui-hidden');
}
}
function bibMountToolContent(toolId) {
var panel = bibGetToolPanel(toolId);
var detailBody = document.getElementById('bib-tool-detail-body');
var content = bibGetToolContentNode(panel, toolId);
if (!panel || !detailBody || !content) {
return false;
}
if (!bibToolContentSlots[toolId]) {
var placeholder = document.createComment('bib-tool-slot-' + toolId);
content.parentNode.insertBefore(placeholder, content);
bibToolContentSlots[toolId] = {
content: content,
placeholder: placeholder,
panel: panel
};
}
detailBody.appendChild(content);
if (toolId === 'global_batch') {
content.classList.remove('bib-ui-hidden');
}
return true;
}
function bibSetActiveToolButton(toolId) {
moduleBib.querySelectorAll('.bib-tool-btn').forEach(function (btn) {
var active = !!toolId && btn.getAttribute('data-bib-tool') === toolId;
btn.classList.toggle('is-active', active);
btn.setAttribute('aria-expanded', active ? 'true' : 'false');
});
}
function bibSetToolDetailTitle(toolId) {
var titleEl = document.getElementById('bib-tool-detail-title');
if (!titleEl) {
return;
}
if (!toolId) {
titleEl.textContent = '';
return;
}
var btn = moduleBib.querySelector('.bib-tool-btn[data-bib-tool="' + toolId + '"]');
titleEl.textContent = btn
? (btn.getAttribute('data-bib-tool-label') || '')
: '';
}
function bibCloseTool() {
if (!bibActiveTool) {
return;
}
bibRestoreToolContent(bibActiveTool);
bibInvalidateToolSlot(bibActiveTool);
bibActiveTool = null;
bibSetActiveToolButton(null);
bibSetToolDetailTitle(null);
var detail = document.getElementById('bib-tool-detail');
var detailBody = document.getElementById('bib-tool-detail-body');
if (detailBody) {
detailBody.innerHTML = '';
}
if (detail) {
detail.classList.add('bib-ui-hidden');
}
}
function bibSyncToolNavBadges(toolId) {
var panel = bibGetToolPanel(toolId);
var btn = moduleBib.querySelector('.bib-tool-btn[data-bib-tool="' + toolId + '"]');
if (!panel || !btn) {
return;
}
var dest = btn.querySelector('.bib-tool-btn__badges');
if (!dest) {
return;
}
if (toolId === 'event_config') {
var srcNote = panel.querySelector('[data-bib-inter-epr-note]');
var destNote = dest.querySelector('[data-bib-inter-epr-note]');
if (srcNote && destNote) {
destNote.className = srcNote.className;
}
return;
}
if (toolId === 'qty_summary') {
dest.innerHTML = '';
return;
}
if (toolId === 'anomalies') {
var anomCount = panel.querySelector('.bib-anomalies-count');
var destBadge = dest.querySelector('[data-bib-anomalies-nav-badge]');
var strTodoFmt = bibJs('jsAnomaliesNavTodoFmt') || 'Élément à valider : %d';
var intCount = 0;
var blnPending = true;
if (anomCount) {
blnPending = anomCount.getAttribute('aria-busy') === 'true';
if (!blnPending) {
intCount = parseInt(String(anomCount.textContent || '').trim(), 10);
if (isNaN(intCount)) {
intCount = 0;
}
}
}
function bibAnomaliesNavBadgeLabel(count) {
return strTodoFmt.replace(/%d/g, String(count));
}
if (!destBadge) {
dest.innerHTML = '';
if (!blnPending && intCount > 0) {
var strLabel = bibAnomaliesNavBadgeLabel(intCount);
dest.innerHTML = '<span class="epr-header-summary bib-event-config-note bib-anomalies-nav-badge"'
+ ' data-bib-anomalies-nav-badge="1"'
+ ' data-bib-anomalies-nav-count="' + intCount + '"'
+ ' title="' + strLabel.replace(/"/g, '&quot;') + '">'
+ strLabel
+ '</span>';
}
return;
}
if (blnPending || intCount <= 0) {
destBadge.classList.add('bib-ui-hidden');
destBadge.setAttribute('aria-hidden', 'true');
destBadge.textContent = '';
destBadge.removeAttribute('data-bib-anomalies-nav-count');
} else {
var strBadgeLabel = bibAnomaliesNavBadgeLabel(intCount);
destBadge.classList.remove('bib-ui-hidden');
destBadge.removeAttribute('aria-hidden');
destBadge.textContent = strBadgeLabel;
destBadge.setAttribute('title', strBadgeLabel);
destBadge.setAttribute('data-bib-anomalies-nav-count', String(intCount));
}
}
}
function bibSyncAllToolNavBadges() {
bibSyncToolNavBadges('event_config');
bibSyncToolNavBadges('anomalies');
}
function bibEnsureToolLoaded(toolId) {
if (toolId === 'qty_summary') {
var qtyPanel = bibGetToolPanel('qty_summary');
if (qtyPanel && qtyPanel.getAttribute('data-bib-qty-summary-deferred') === '1') {
return refreshBibQtySummaryPanel();
}
}
if (toolId === 'dist_print') {
var printPanel = bibGetToolPanel('dist_print');
if (printPanel && printPanel.getAttribute('data-bib-dist-print-deferred') === '1') {
return refreshBibDistPrintPanel();
}
}
if (toolId === 'global_batch') {
var batchPanel = bibGetToolPanel('global_batch');
if (batchPanel && batchPanel.getAttribute('data-global-batch-deferred') === '1') {
return bibEnsureGlobalBatchPanelLoaded();
}
}
return Promise.resolve();
}
function bibOpenTool(toolId) {
if (!toolId) {
return Promise.resolve();
}
if (bibActiveTool === toolId) {
bibCloseTool();
return Promise.resolve();
}
var prevTool = bibActiveTool;
if (prevTool) {
bibRestoreToolContent(prevTool);
bibInvalidateToolSlot(prevTool);
}
return bibEnsureToolLoaded(toolId).then(function () {
var panel = bibGetToolPanel(toolId);
if (!panel || !bibMountToolContent(toolId)) {
return;
}
bibActiveTool = toolId;
bibSetActiveToolButton(toolId);
bibSetToolDetailTitle(toolId);
var detail = document.getElementById('bib-tool-detail');
if (detail) {
detail.classList.remove('bib-ui-hidden');
detail.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
if (toolId === 'global_batch') {
updateGlobalBatchAnalysis();
}
bibSyncToolNavBadges(toolId);
initModuleBibTippy(document.getElementById('bib-tool-detail'));
});
}
function bibRemountActiveToolAfterRefresh(toolId) {
if (bibActiveTool !== toolId) {
return;
}
bibInvalidateToolSlot(toolId);
bibMountToolContent(toolId);
initModuleBibTippy(document.getElementById('bib-tool-detail'));
if (toolId === 'global_batch') {
updateGlobalBatchAnalysis();
}
}
var bibGlobalBatchLoadPromise = null;
function bibEnsureGlobalBatchPanelLoaded() {
var mount = document.getElementById('bib-global-batch-mount');
var panel = bibGetGlobalBatchPanel();
if (!mount || !panel) {
return Promise.resolve(null);
}
if (panel.getAttribute('data-global-batch-loaded') === '1') {
return Promise.resolve(panel);
}
if (bibGlobalBatchLoadPromise) {
return bibGlobalBatchLoadPromise;
}
bibGlobalBatchLoadPromise = bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body:
'action=global_batch_panel'
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
+ bibAjaxLangSuffix()
})
.then(function (res) { return res.json(); })
.then(function (data) {
if (!data.success || !data.html) {
throw new Error(data.message || bibJs('jsErrGeneric'));
}
mount.innerHTML = data.html;
panel = bibGetGlobalBatchPanel();
if (panel) {
panel.setAttribute('data-global-batch-loaded', '1');
panel.removeAttribute('data-global-batch-deferred');
}
initModuleBibTippy(mount);
bibRemountActiveToolAfterRefresh('global_batch');
return panel;
})
.finally(function () {
bibGlobalBatchLoadPromise = null;
});
return bibGlobalBatchLoadPromise;
}
function bibGlobalBatchSetToggleState(toggle, isOpen) {
if (!toggle) {
return;
}
toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
var label = isOpen
? (toggle.getAttribute('data-label-close') || '')
: (toggle.getAttribute('data-label-open') || '');
if (label) {
toggle.textContent = label;
}
}
function bibGlobalBatchOpenPanel(panel) {
if (!panel) {
return;
}
var body = panel.querySelector('.bib-global-batch__body');
var toggle = panel.querySelector('.bib-global-batch-toggle');
if (body) {
body.classList.remove('bib-ui-hidden');
}
bibGlobalBatchSetToggleState(toggle, true);
updateGlobalBatchAnalysis();
}
function bibSetGlobalBatchInfo(infoEl, text, state) {
if (!infoEl) {
return;
}
infoEl.textContent = text || '';
infoEl.classList.remove('text-muted', 'text-danger', 'text-warning', 'text-success');
if (state === 'error') {
infoEl.classList.add('text-danger');
} else if (state === 'warning') {
infoEl.classList.add('text-warning');
} else if (state === 'ok') {
infoEl.classList.add('text-success');
} else {
infoEl.classList.add('text-muted');
}
}
function bibCollectGlobalBatchPlans() {
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
if (!bibGlobalBatchPanel) {
return [];
}
var plans = [];
bibGlobalBatchPanel.querySelectorAll('.bib-global-epr').forEach(function (eprBlock) {
var eprCb = eprBlock.querySelector('.bib-global-epr-select');
if (!eprCb || !eprCb.checked) {
return;
}
var eprId = parseInt(eprCb.dataset.eprId || eprBlock.dataset.eprId || '0', 10);
if (!eprId) {
return;
}
var ranges = [];
eprBlock.querySelectorAll('.bib-global-range-select:checked').forEach(function (rangeCb) {
ranges.push(rangeCb.dataset.rangeId);
});
if (ranges.length > 0) {
plans.push({ epr_id: eprId, ranges: ranges });
}
});
return plans;
}
function updateGlobalBatchAnalysis() {
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
if (!bibGlobalBatchPanel) {
return Promise.resolve();
}
var plans = bibCollectGlobalBatchPlans();
var infoEl = bibGlobalBatchPanel.querySelector('.bib-global-batch__info');
var sortKeys = bibGetGlobalBatchSortKeys(bibGlobalBatchPanel);
if (!infoEl) {
return Promise.resolve();
}
if (plans.length === 0) {
bibSetGlobalBatchInfo(
infoEl,
bibJs('jsGlobalNoEpr') || bibJs('jsBatchNone'),
'error'
);
return Promise.resolve(null);
}
var hasRange = plans.some(function (p) { return p.ranges.length > 0; });
if (!hasRange) {
bibSetGlobalBatchInfo(
infoEl,
bibJs('jsGlobalNoSeq') || bibJs('jsNoSeqSelected'),
'error'
);
return Promise.resolve(null);
}
bibSetGlobalBatchInfo(infoEl, bibJs('jsLoaderWait') || '…', 'normal');
return fetch('/ajax_bib_range.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body:
'action=batch_global_analysis'
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
+ bibAppendBatchSortParams('', sortKeys)
+ '&plans=' + encodeURIComponent(JSON.stringify(plans))
+ bibAjaxLangSuffix()
})
.then(function (res) { return res.json(); })
.then(function (data) {
if (!data.success) {
bibSetGlobalBatchInfo(
infoEl,
data.message || bibJs('jsErrGeneric'),
'error'
);
return data;
}
var state = (data.stats && data.stats.nb_manque > 0) ? 'warning' : 'normal';
bibSetGlobalBatchInfo(infoEl, data.info || '', state);
return data;
})
.catch(function () {
bibSetGlobalBatchInfo(infoEl, bibJs('jsErrGeneric'), 'error');
return null;
});
}
function bibRunGlobalBatchGo() {
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
if (!bibGlobalBatchPanel) {
return;
}
var plans = bibCollectGlobalBatchPlans();
var sortKeys = bibGetGlobalBatchSortKeys(bibGlobalBatchPanel);
if (plans.length === 0) {
alert(bibJs('jsGlobalNoEpr') || bibJs('jsBatchNone'));
return;
}
if (!plans.some(function (p) { return p.ranges.length > 0; })) {
alert(bibJs('jsGlobalNoSeq') || bibJs('jsNoSeqSelected'));
return;
}
fetch('/ajax_bib_range.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body:
'action=batch_global_analysis'
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
+ bibAppendBatchSortParams('', sortKeys)
+ '&plans=' + encodeURIComponent(JSON.stringify(plans))
+ bibAjaxLangSuffix()
})
.then(function (res) {
if (!res.ok) {
throw new Error(bibJs('jsErrGeneric'));
}
return res.json();
})
.then(function (analysis) {
if (!analysis || !analysis.success) {
throw new Error((analysis && analysis.message) || bibJs('jsErrGeneric'));
}
var globalTotal = (analysis.stats && analysis.stats.nb_participants)
? analysis.stats.nb_participants
: 1;
var completedOffset = 0;
var runResults = [];
bibBatchProgressShow(0, globalTotal);
var chain = Promise.resolve();
plans.forEach(function (plan) {
chain = chain.then(function () {
var row = moduleBib.querySelector('.epr-row[data-epr-id="' + plan.epr_id + '"]');
if (!row) {
throw new Error(bibJs('jsErrGeneric'));
}
var pendingBefore = bibRowPendingBibs(row);
var offset = completedOffset;
return bibRunBatchApplyChunks(row, plan.ranges, sortKeys, {
showResult: false,
manageLoader: false,
deferUiRefresh: true,
totalInitial: pendingBefore,
onProgress: function (processed) {
bibBatchProgressShow(offset + processed, globalTotal);
}
}).then(function (data) {
runResults.push({
epr_id: plan.epr_id,
assigned: data.assigned_total || 0,
total: data.total_initial || pendingBefore
});
completedOffset = offset + pendingBefore;
});
});
});
return chain.then(function () {
bibBatchProgressShow(globalTotal, globalTotal);
var refreshChain = Promise.resolve();
runResults.forEach(function (result) {
refreshChain = refreshChain.then(function () {
var row = moduleBib.querySelector('.epr-row[data-epr-id="' + result.epr_id + '"]');
if (!row) {
return null;
}
return bibAfterBatchGoRefreshOnly(row, false, {
loader: false,
skipAnomalies: true
});
});
});
return refreshChain.then(function () {
if (typeof refreshBibAnomaliesPanel === 'function') {
refreshBibAnomaliesPanel();
}
var panelRef = bibGetGlobalBatchPanel();
var infoEl = panelRef ? panelRef.querySelector('.bib-global-batch__info') : null;
var totalAssigned = 0;
var totalExpected = 0;
runResults.forEach(function (result) {
totalAssigned += result.assigned;
totalExpected += result.total;
});
var remaining = Math.max(0, totalExpected - totalAssigned);
return updateGlobalBatchAnalysis().then(function () {
if (totalAssigned === 0 && totalExpected > 0) {
var msgNone = bibJs('jsAssignNone') || bibJs('jsErrGeneric');
bibSetGlobalBatchInfo(infoEl, msgNone, 'error');
alert(msgNone);
} else if (remaining > 0) {
var msgPartial = bibJsFmt('jsAssignPartial', totalAssigned, remaining);
bibSetGlobalBatchInfo(infoEl, msgPartial, 'warning');
alert(msgPartial);
} else if (totalAssigned > 0) {
bibSetGlobalBatchInfo(
infoEl,
bibJsFmt('jsAssignFull', totalAssigned),
'ok'
);
}
});
});
});
})
.catch(function (err) {
alert(err.message || bibJs('jsErrGeneric'));
})
.finally(function () {
bibBatchProgressForceHide();
});
}
moduleBib.addEventListener('keydown', function (e) {
if (e.key !== 'Enter' && e.key !== ' ') {
return;
}
var toolBtn = e.target.closest('.bib-tool-btn[role="button"]');
if (!toolBtn || !moduleBib.contains(toolBtn)) {
return;
}
e.preventDefault();
bibOpenTool(toolBtn.getAttribute('data-bib-tool'));
});
moduleBib.addEventListener('click', function (e) {
if (e.target.closest('.bib-tool-detail__close')) {
e.preventDefault();
bibCloseTool();
return;
}
var toolBtn = e.target.closest('.bib-tool-btn');
if (toolBtn && moduleBib.contains(toolBtn)) {
if (e.target.closest('.btn-aide-bib, .bib-aide-trigger, .btn-aide-trad, .btn-doc-trigger, .btn-admin-doc, .btn-trad-admin')) {
return;
}
e.preventDefault();
bibOpenTool(toolBtn.getAttribute('data-bib-tool'));
return;
}
if (e.target.closest('.btn-simuler-global-batch')) {
e.preventDefault();
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
var plans = bibCollectGlobalBatchPlans();
var sortKeys = bibGlobalBatchPanel
? bibGetGlobalBatchSortKeys(bibGlobalBatchPanel)
: { sort1: '', sort2: '' };
if (plans.length === 0) {
alert(bibJs('jsGlobalNoEpr') || bibJs('jsBatchNone'));
return;
}
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body:
'action=batch_global_simulate'
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
+ bibAppendBatchSortParams('', sortKeys)
+ '&plans=' + encodeURIComponent(JSON.stringify(plans))
+ bibAjaxLangSuffix()
})
.then(function (res) { return res.json(); })
.then(function (data) {
if (!data.success) {
alert(data.message || bibJs('jsErrGeneric'));
return;
}
var existing = document.querySelector('.epr-row-view');
if (existing) {
existing.remove();
}
var anchor = bibGetGlobalBatchPanel();
if (anchor) {
anchor.insertAdjacentHTML('afterend', data.html);
}
});
return;
}
if (e.target.closest('.btn-go-global-batch')) {
e.preventDefault();
bibRunGlobalBatchGo();
}
});
moduleBib.addEventListener('change', function (e) {
if (!e.target.matches('.bib-global-epr-select, .bib-global-range-select, .bib-global-batch-order, .bib-global-batch-order-2')) {
return;
}
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
if (!bibGlobalBatchPanel || !bibGlobalBatchPanel.contains(e.target)) {
return;
}
var eprBlock = e.target.closest('.bib-global-epr');
if (eprBlock && e.target.classList.contains('bib-global-epr-select')) {
var checked = e.target.checked;
eprBlock.querySelectorAll('.bib-global-range-select').forEach(function (cb) {
cb.disabled = !checked;
if (!checked) {
cb.checked = false;
}
});
}
updateGlobalBatchAnalysis();
});
function bibRowPendingBibs(row) {
if (!row) return 0;
return parseInt(row.dataset.bibAAssigner || '0', 10) || 0;
}
function bibSyncEprBibStats(row, info) {
if (!row || !info) return;
if (info.total !== undefined) {
let totalEl = row.querySelector('.bib-total');
if (totalEl) totalEl.textContent = info.total;
}
if (info.avec_bib !== undefined) {
let avecEl = row.querySelector('.bib-avec');
if (avecEl) avecEl.textContent = info.avec_bib;
}
let pending = (info.a_assigner !== undefined && info.a_assigner !== null)
? info.a_assigner
: (info.sans_bib || 0);
row.dataset.bibAAssigner = String(parseInt(pending, 10) || 0);
}
function bibAlertAutoPendingBibs(row) {
alert(bibJsFmt('jsAutoPendingBibs', bibRowPendingBibs(row)).replace(/\\n/g, '\n'));
}
/** Bloque l'entrée en mode auto si des inscriptions n'ont pas encore de dossard. */
function bibBlockAutoActivation(row) {
if (!row || row.dataset.autoActive === '1') {
return false;
}
if (bibRowPendingBibs(row) > 0) {
bibAlertAutoPendingBibs(row);
return true;
}
return false;
}
// MSIN-4379 — Mise à jour affichage quantités (panneau gestion + pastille en-tête).
function bibApplyQteData(data) {
if (!data || typeof data !== 'object') {
return;
}
Object.keys(data).forEach(function (eprId) {
if (eprId === 'total') {
return;
}
let row = data[eprId];
if (!row) {
return;
}
let elOrigine = document.getElementById('qte_origine_' + eprId);
let elAjustement = document.getElementById('qte_ajustement_' + eprId);
let elCourante = document.getElementById('qte_courante_' + eprId);
let elInscrits = document.getElementById('qte_inscrits_' + eprId);
let elCheckin = document.getElementById('qte_checkin_' + eprId);
let elRestante = document.getElementById('qte_restante_' + eprId);
if (elOrigine) {
elOrigine.textContent = row.qte_origine;
}
if (elAjustement) {
elAjustement.textContent = row.qte_ajustement;
}
if (elCourante) {
elCourante.textContent = row.qte_courante;
}
if (elInscrits) {
elInscrits.textContent = row.qte_inscrits;
}
if (elCheckin) {
elCheckin.textContent = row.qte_checkin;
}
if (elRestante) {
elRestante.value = row.qte_restante;
}
let dispoBadge = document.querySelector(
'.epr-row[data-epr-id="' + eprId + '"] .epr-header-summary--dispo'
);
if (dispoBadge && row.qte_restante !== undefined) {
let labelParts = dispoBadge.textContent.split(':');
let label = labelParts.length > 1 ? labelParts[0].trim() : '';
dispoBadge.textContent = label + ' : ' + row.qte_restante;
}
let btnQte = document.querySelector(
'.epr-gestion-panel[data-epr-id="' + eprId + '"] .btn_qte'
);
if (btnQte) {
btnQte.setAttribute('data-qte_initiale', row.qte_restante);
}
});
}
function bibSaveQte(btn) {
let eprId = btn.getAttribute('data-epr_id');
if (!eprId) {
return;
}
let input = document.getElementById('qte_restante_' + eprId);
if (!input) {
return;
}
let intQte = parseInt(input.value, 10);
if (isNaN(intQte) || intQte < 0) {
alert(bibJs('err-generic'));
return;
}
bibLoaderShow();
fetch('/ajax_promoteur.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
credentials: 'same-origin',
body:
'a=qte'
+ '&epr_id=' + encodeURIComponent(eprId)
+ '&qte=' + encodeURIComponent(intQte)
+ '&lang=' + encodeURIComponent(moduleBib.dataset.lang || 'fr')
})
.then(function (res) {
return res.json();
})
.then(function (result) {
if (result && result.state === 'success' && result.data) {
bibApplyQteData(result.data);
return;
}
alert(bibJs('err-generic'));
})
.catch(function () {
alert(bibJs('server-error'));
})
.finally(function () {
bibLoaderHide();
});
}
// MSIN-4379 — Réduire / développer les blocs gestion et assignation (en-tête seul visible).
moduleBib.addEventListener('click', function (e) {
let btnToggle = e.target.closest('.epr-block-toggle');
if (!btnToggle || !moduleBib.contains(btnToggle)) {
return;
}
let block = btnToggle.closest('.epr-block');
if (!block || block.closest('#bib-tool-store')) {
return;
}
let collapsed = block.classList.toggle('is-collapsed');
btnToggle.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
let label = collapsed
? (btnToggle.getAttribute('data-label-expand') || '')
: (btnToggle.getAttribute('data-label-collapse') || '');
if (label) {
btnToggle.setAttribute('aria-label', label);
btnToggle.setAttribute('title', label);
}
let icon = btnToggle.querySelector('.fa');
if (icon) {
icon.classList.toggle('fa-chevron-up', !collapsed);
icon.classList.toggle('fa-chevron-down', collapsed);
}
// MSIN-4424 — Sommaire quantités : chargement à la première ouverture (accordéon épreuve).
if (!collapsed && block.id === 'bib-qty-summary-panel'
&& block.getAttribute('data-bib-qty-summary-deferred') === '1') {
refreshBibQtySummaryPanel();
}
// MSIN-4433 — Impression PDF : chargement à la première ouverture (accordéon épreuve).
if (!collapsed && block.id === 'bib-dist-print-panel'
&& block.getAttribute('data-bib-dist-print-deferred') === '1') {
refreshBibDistPrintPanel();
}
});
// ============================================================
// MSIN-4379 — Tippy.js (module #module-bib uniquement)
// info_texte → data-tippy-content (tip court)
// info_aide → data-tippy-content sur .btn-aide-bib (pop-up long)
// Ré-init après chaque refresh AJAX des séquences.
// ============================================================
function getBibContainer(row) {
if (!row) return null;
return row.querySelector('.epr-block-assign .epr-table.bib-container')
|| row.querySelector('.epr-table.bib-container')
|| row.querySelector('.epr-block-assign .bib-container')
|| row.querySelector('.bib-container');
}
function bibTippyEscapeHtml(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function bibTippyAideContent(reference) {
let span = reference.querySelector('.bib-aide-text');
if (!span) {
return '';
}
// Mini-formatage : retours à la ligne → <br> ; double saut → paragraphe.
let lines = span.textContent.replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim().split('\n');
let html = '';
let para = [];
lines.forEach(function (line) {
if (line.trim() === '') {
if (para.length) {
html += '<p>' + para.join('<br>') + '</p>';
para = [];
}
} else {
para.push(bibTippyEscapeHtml(line));
}
});
if (para.length) {
html += '<p>' + para.join('<br>') + '</p>';
}
return html;
}
function initModuleBibTippy(root) {
if (typeof tippy === 'undefined') return;
let scope = root || moduleBib;
scope.querySelectorAll('[data-tippy-content], .bib-aide-trigger').forEach(function (el) {
if (el._tippy) {
el._tippy.destroy();
}
});
tippy(scope.querySelectorAll('[data-tippy-content]'), {
theme: 'ms1-bib',
animation: 'fade',
allowHTML: false,
maxWidth: 280,
interactive: false
});
tippy(scope.querySelectorAll('.bib-aide-trigger'), {
theme: 'ms1-bib ms1-bib-aide',
animation: 'fade',
allowHTML: true,
maxWidth: 420,
interactive: true,
content: bibTippyAideContent
});
}
/** Visibilité UI v4 — bib-ui-hidden sur le conteneur (bouton + ? ensemble). */
function bibQuery(row, selector) {
return (row || moduleBib).querySelector(selector);
}
function bibSetVisible(target, show, row) {
let el = target;
if (typeof target === 'string') {
el = bibQuery(row, target);
} else if (el && el.nodeType === 1
&& !el.classList.contains('epr-action-group')
&& !el.classList.contains('batch-config-container')
&& !el.classList.contains('auto-config-container')
&& !el.classList.contains('epr-add-range-row')) {
el = el.closest('.epr-action-group') || el;
}
if (el) {
el.classList.toggle('bib-ui-hidden', !show);
}
}
function bibRowModes(row) {
return {
batch: row.classList.contains('batch-mode'),
auto: row.classList.contains('auto-mode'),
reset: row.classList.contains('reset-mode'),
};
}
function bibHasSavedSequences(row) {
return Array.from(row.querySelectorAll('.bib-range[data-id]')).some(function (line) {
return parseInt(line.getAttribute('data-id') || '0', 10) > 0;
});
}
function bibCountSelectedRanges(row) {
return row.querySelectorAll('.batch-select-range:checked').length;
}
/** MSIN-4436 — Développe un bloc repliable #module-bib. */
function bibExpandBlock(block) {
if (!block || !block.classList.contains('is-collapsed')) {
return;
}
block.classList.remove('is-collapsed');
let btn = block.querySelector('.epr-block-toggle');
if (btn) {
btn.setAttribute('aria-expanded', 'true');
let label = btn.getAttribute('data-label-collapse') || '';
if (label) {
btn.setAttribute('aria-label', label);
btn.setAttribute('title', label);
}
let icon = btn.querySelector('.fa');
if (icon) {
icon.classList.add('fa-chevron-up');
icon.classList.remove('fa-chevron-down');
}
}
}
let bibFocusApplied = false;
/** MSIN-4436 — Retour depuis fiche inscription : rouvrir le panneau ciblé. */
function bibApplyFocusFromUrlOnce() {
if (bibFocusApplied) {
return;
}
let focus = new URLSearchParams(window.location.search).get('bib_focus');
if (!focus) {
return;
}
bibFocusApplied = true;
let focusMap = {
anomalies: 'anomalies',
qty_summary: 'qty_summary',
dist_print: 'dist_print',
event_config: 'event_config'
};
let toolId = focusMap[focus];
if (!toolId) {
return;
}
bibOpenTool(toolId).then(function () {
let detail = document.getElementById('bib-tool-detail');
if (detail) {
detail.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
}
/** MSIN-4379 — Rafraîchit le dashboard anomalies (chien de garde). */
function refreshBibAnomaliesPanel() {
let mount = document.getElementById('bib-anomalies-mount');
if (!mount || !moduleBib) {
return Promise.resolve();
}
let eveId = moduleBib.dataset.eveId || '';
if (!eveId) {
return Promise.resolve();
}
return bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=anomalies&eve_id=' + encodeURIComponent(eveId) + bibAjaxLangSuffix()
}, { loader: false })
.then(function (res) { return res.json(); })
.then(function (data) {
if (!data.success || !data.html) {
return;
}
let blnWasActive = bibActiveTool === 'anomalies';
if (blnWasActive) {
bibRestoreToolContent('anomalies');
}
bibInvalidateToolSlot('anomalies');
mount.innerHTML = data.html;
initModuleBibTippy(mount);
bibSyncToolNavBadges('anomalies');
bibRemountActiveToolAfterRefresh('anomalies');
});
}
/** MSIN-4433 — Rafraîchit le panneau impression PDF. */
function refreshBibDistPrintPanel() {
let mount = document.getElementById('bib-dist-print-mount');
if (!mount || !moduleBib) {
return Promise.resolve();
}
let panel = document.getElementById('bib-dist-print-panel');
let blnDeferred = panel && panel.getAttribute('data-bib-dist-print-deferred') === '1';
let blnLoaded = panel && panel.getAttribute('data-bib-dist-print-loaded') === '1';
if (!blnDeferred && !blnLoaded) {
return Promise.resolve();
}
let eveId = moduleBib.dataset.eveId || '';
if (!eveId) {
return Promise.resolve();
}
let blnWasActive = bibActiveTool === 'dist_print';
return bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=dist_print_panel&eve_id=' + encodeURIComponent(eveId) + bibAjaxLangSuffix()
}, { loader: false })
.then(function (res) { return res.json(); })
.then(function (data) {
if (!data.success || !data.html) {
return;
}
if (blnWasActive) {
bibRestoreToolContent('dist_print');
}
bibInvalidateToolSlot('dist_print');
mount.innerHTML = data.html;
initModuleBibTippy(mount);
initBibDistPrintPanel(mount);
bibRemountActiveToolAfterRefresh('dist_print');
});
}
/** MSIN-4433 — Limite questions + rafraîchissement après génération PDF. */
function initBibDistPrintPanel(root) {
root = root || document;
let panel = root.querySelector ? root.querySelector('#bib-dist-print-panel') : null;
if (!panel) {
panel = document.getElementById('bib-dist-print-panel');
}
if (!panel || panel.getAttribute('data-bib-dist-print-init') === '1') {
return;
}
panel.setAttribute('data-bib-dist-print-init', '1');
let intMax = parseInt(panel.getAttribute('data-max-questions') || '5', 10);
if (!intMax || intMax < 1) {
intMax = 5;
}
panel.addEventListener('change', function (ev) {
let cb = ev.target;
if (!cb || !cb.classList || !cb.classList.contains('bib-dist-print-question-cb')) {
return;
}
if (!cb.checked) {
return;
}
let section = cb.closest('.bib-dist-print-epr');
if (!section) {
return;
}
let tabChecked = section.querySelectorAll('.bib-dist-print-question-cb:checked');
if (tabChecked.length > intMax) {
cb.checked = false;
}
});
let form = panel.querySelector('.bib-dist-print-form');
if (form) {
form.addEventListener('submit', function () {
window.setTimeout(function () {
refreshBibDistPrintPanel();
}, 1500);
});
}
}
/** MSIN-4424 — Rafraîchit le sommaire des quantités (si déjà chargé ou ouverture). */
function refreshBibQtySummaryPanel() {
let mount = document.getElementById('bib-qty-summary-mount');
if (!mount || !moduleBib) {
return Promise.resolve();
}
let panel = document.getElementById('bib-qty-summary-panel');
let blnDeferred = panel && panel.getAttribute('data-bib-qty-summary-deferred') === '1';
let blnLoaded = panel && panel.getAttribute('data-bib-qty-summary-loaded') === '1';
if (!blnDeferred && !blnLoaded) {
return Promise.resolve();
}
let eveId = moduleBib.dataset.eveId || '';
if (!eveId) {
return Promise.resolve();
}
let blnWasActive = bibActiveTool === 'qty_summary';
return bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=qty_summary&eve_id=' + encodeURIComponent(eveId) + bibAjaxLangSuffix()
}, { loader: false })
.then(function (res) { return res.json(); })
.then(function (data) {
if (!data.success || !data.html) {
return;
}
if (blnWasActive) {
bibRestoreToolContent('qty_summary');
}
bibInvalidateToolSlot('qty_summary');
mount.innerHTML = data.html;
initModuleBibTippy(mount);
bibSyncToolNavBadges('qty_summary');
bibRemountActiveToolAfterRefresh('qty_summary');
});
}
function bibQtySummaryShouldRefresh() {
let panel = document.getElementById('bib-qty-summary-panel');
return panel && panel.getAttribute('data-bib-qty-summary-loaded') === '1';
}
function setBibContainerHtml(row, html, opts) {
opts = opts || {};
let container = getBibContainer(row);
if (!container) return null;
// renderBibRanges renvoie un bloc .epr-table.bib-container complet.
if (html.indexOf('bib-container') !== -1) {
container.outerHTML = html;
container = getBibContainer(row);
} else {
container.innerHTML = html;
}
if (container) {
initModuleBibTippy(row);
initBibRangeRows(container);
}
syncBibUiState(row);
if (!opts.skipAnomalies) {
refreshBibAnomaliesPanel();
}
if (!opts.skipQtySummary && bibQtySummaryShouldRefresh()) {
refreshBibQtySummaryPanel();
}
return container;
}
// MSIN-4429 — Séquence : Début puis Qté ou Fin (pilote / calculé).
function bibRangeParseInt(val) {
var n = parseInt(String(val || '').trim(), 10);
return isNaN(n) ? 0 : n;
}
function bibRangeGetFields(row) {
if (!row) return null;
return {
start: row.querySelector('.bib-start'),
qty: row.querySelector('.bib-qty'),
end: row.querySelector('.bib-end')
};
}
function bibRangeGetErrorEl(row) {
var el = row && row.nextElementSibling;
if (el && el.classList.contains('bib-error')) {
return el;
}
return null;
}
function bibRangeClearRangeError(row) {
var errEl = bibRangeGetErrorEl(row);
if (!errEl) return;
var msg = errEl.querySelector('.bib-range-validate-msg');
if (msg) {
msg.remove();
}
if (!errEl.querySelector('div:not(.bib-range-validate-msg)') && !errEl.textContent.trim()) {
errEl.style.display = 'none';
}
}
function bibRangeClearFieldClasses(row) {
var fields = bibRangeGetFields(row);
if (!fields) return;
[fields.start, fields.qty, fields.end].forEach(function (el) {
if (!el) return;
el.classList.remove('bib-field--idle', 'bib-field--pick', 'bib-field--calc', 'bib-field--active');
});
}
function bibRangeClearValidationUi(row) {
var fields = bibRangeGetFields(row);
if (!fields) return;
[fields.start, fields.qty, fields.end].forEach(function (el) {
if (el) {
el.classList.remove('bib-field--invalid');
}
});
bibRangeClearRangeError(row);
}
/** MSIN-4429 — Validation différée (blur / OK), pas pendant la frappe. */
function bibRangeValidate(row) {
var fields = bibRangeGetFields(row);
if (!fields) return null;
var start = bibRangeParseInt(fields.start && fields.start.value);
if (start <= 0) {
return null;
}
var pilot = row.dataset.rangePilot || '';
if (!pilot) {
return null;
}
if (pilot === 'end') {
var strEnd = String(fields.end && fields.end.value || '').trim();
if (strEnd === '') {
return null;
}
var end = bibRangeParseInt(strEnd);
if (end <= 0) {
return { key: 'incomplete', field: 'end' };
}
if (end < start) {
return { key: 'invalidEnd', field: 'end', start: start };
}
}
if (pilot === 'qty') {
var strQty = String(fields.qty && fields.qty.value || '').trim();
if (strQty === '') {
return null;
}
var qty = bibRangeParseInt(strQty);
if (qty <= 0) {
return { key: 'invalidQty', field: 'qty' };
}
}
return null;
}
function bibRangeValidationMessage(validation) {
if (!validation) {
return '';
}
if (validation.key === 'invalidEnd') {
return bibJsFmt('jsRangeInvalidEnd', validation.start);
}
if (validation.key === 'invalidQty') {
return bibJs('jsRangeInvalidQty');
}
if (validation.key === 'incomplete') {
return bibJs('jsRangeIncomplete') || bibJs('jsFieldsRequired');
}
return bibJs('jsRangeInvalid') || bibJs('jsFieldsRequired');
}
function bibRangeShowValidation(row, validation) {
var fields = bibRangeGetFields(row);
if (!fields) {
return;
}
bibRangeClearValidationUi(row);
if (!validation) {
return;
}
var target = validation.field === 'qty' ? fields.qty : fields.end;
if (target) {
target.classList.add('bib-field--invalid');
}
var errEl = bibRangeGetErrorEl(row);
if (!errEl) {
return;
}
var msgEl = errEl.querySelector('.bib-range-validate-msg');
if (!msgEl) {
msgEl = document.createElement('div');
msgEl.className = 'bib-range-validate-msg';
errEl.insertBefore(msgEl, errEl.firstChild);
}
msgEl.textContent = bibRangeValidationMessage(validation);
errEl.style.display = 'block';
}
function bibRangeValidateOnBlur(row) {
applyBibRangeFieldState(row);
bibRangeShowValidation(row, bibRangeValidate(row));
}
function applyBibRangeFieldState(row) {
var fields = bibRangeGetFields(row);
if (!fields || !fields.start || !fields.qty || !fields.end) return;
if (row.dataset.locked === '1') {
bibRangeClearFieldClasses(row);
return;
}
var start = bibRangeParseInt(fields.start.value);
var pilot = row.dataset.rangePilot || '';
bibRangeClearFieldClasses(row);
if (start <= 0) {
fields.qty.classList.add('bib-field--idle');
fields.end.classList.add('bib-field--idle');
fields.qty.readOnly = true;
fields.end.readOnly = true;
fields.qty.value = '';
fields.end.value = '';
row.dataset.rangePilot = '';
return;
}
if (!pilot) {
fields.qty.classList.add('bib-field--pick');
fields.end.classList.add('bib-field--pick');
fields.qty.readOnly = true;
fields.end.readOnly = true;
return;
}
if (pilot === 'qty') {
var qty = bibRangeParseInt(fields.qty.value);
fields.qty.classList.add('bib-field--active');
fields.end.classList.add('bib-field--calc');
fields.qty.readOnly = false;
fields.end.readOnly = true;
if (qty > 0) {
fields.end.value = String(start + qty - 1);
} else {
fields.end.value = '';
}
} else if (pilot === 'end') {
var end = bibRangeParseInt(fields.end.value);
fields.end.classList.add('bib-field--active');
fields.qty.classList.add('bib-field--calc');
fields.end.readOnly = false;
fields.qty.readOnly = true;
if (end >= start) {
fields.qty.value = String(end - start + 1);
} else {
fields.qty.value = '';
}
}
}
function onBibRangeFieldPick(row, pilot) {
if (!row || row.dataset.locked === '1') return;
var fields = bibRangeGetFields(row);
if (!fields || !fields.start) return;
if (bibRangeParseInt(fields.start.value) <= 0) {
fields.start.focus();
return;
}
row.dataset.rangePilot = pilot;
applyBibRangeFieldState(row);
var target = pilot === 'qty' ? fields.qty : fields.end;
if (target) {
target.focus();
target.select();
}
}
function onBibRangeStartChange(row) {
var fields = bibRangeGetFields(row);
if (!fields || !fields.start) return;
var start = bibRangeParseInt(fields.start.value);
var lastStart = bibRangeParseInt(row.dataset.rangeLastStart || '0');
if (start !== lastStart && !row.dataset.rangePilot) {
fields.qty.value = '';
fields.end.value = '';
row.dataset.hasValues = '0';
}
row.dataset.rangeLastStart = String(start);
if (start <= 0) {
row.dataset.rangePilot = '';
}
applyBibRangeFieldState(row);
}
function bindBibRangeRow(row) {
if (!row || row.dataset.bibRangeBound === '1') return;
row.dataset.bibRangeBound = '1';
var fields = bibRangeGetFields(row);
if (!fields || !fields.start || !fields.qty || !fields.end) return;
row.dataset.rangeLastStart = String(bibRangeParseInt(fields.start.value));
fields.start.addEventListener('input', function () {
bibRangeClearValidationUi(row);
onBibRangeStartChange(row);
});
fields.qty.addEventListener('input', function () {
bibRangeClearValidationUi(row);
row.dataset.rangePilot = 'qty';
applyBibRangeFieldState(row);
});
fields.end.addEventListener('input', function () {
bibRangeClearValidationUi(row);
row.dataset.rangePilot = 'end';
applyBibRangeFieldState(row);
});
fields.start.addEventListener('blur', function () {
bibRangeValidateOnBlur(row);
});
fields.qty.addEventListener('blur', function () {
bibRangeValidateOnBlur(row);
});
fields.end.addEventListener('blur', function () {
bibRangeValidateOnBlur(row);
});
fields.qty.addEventListener('click', function () {
onBibRangeFieldPick(row, 'qty');
});
fields.end.addEventListener('click', function () {
onBibRangeFieldPick(row, 'end');
});
fields.qty.addEventListener('focus', function () {
onBibRangeFieldPick(row, 'qty');
});
fields.end.addEventListener('focus', function () {
onBibRangeFieldPick(row, 'end');
});
applyBibRangeFieldState(row);
if (row.dataset.id === '0' && !fields.start.value) {
fields.start.focus();
}
}
function initBibRangeRows(root) {
if (!root) return;
root.querySelectorAll('.bib-range').forEach(bindBibRangeRow);
}
function bibCsrfToken() {
return moduleBib ? (moduleBib.dataset.csrfToken || '') : '';
}
initModuleBibTippy(moduleBib);
initBibRangeRows(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-text');
if (!info) return;
if (count === 0) {
info.textContent = bibJs('jsAutoSelectHint');
} else {
info.textContent = bibJsFmt('jsAutoSelectCount', count);
}
}
function syncAutoUiState(row, isActive) {
if (!row) return;
let btnAuto = row.querySelector('.btn-auto');
row.dataset.autoActive = isActive ? '1' : '0';
row.classList.toggle('auto-enabled', isActive);
if (btnAuto) {
btnAuto.textContent = isActive ? row.dataset.autoLabelConfig : row.dataset.autoLabel;
btnAuto.classList.toggle('btn-bib-auto--active', isActive);
let autoAide = bibQuery(row, '.epr-action-auto-group .epr-btn-aide-segment .bib-aide-trigger');
if (autoAide) {
autoAide.classList.add('btn-aide-tone-auto');
autoAide.classList.remove('btn-aide-tone-success', 'btn-aide-tone-secondary');
}
}
}
/** 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-qty, .bib-end').forEach(input => {
input.removeAttribute('readonly');
});
bibFetch('/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'
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) return;
let bibContainer = setBibContainerHtml(row, data.html);
});
}
/** 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;
}
if (bibBlockAutoActivation(row)) {
return;
}
row.classList.add('auto-mode');
let container = row.querySelector('.bib-container');
if (container) {
container.classList.add('batch-mode');
}
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.setAttribute('readonly', true);
});
syncBibUiState(row);
bibFetch('/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'
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) return;
let bibContainer = setBibContainerHtml(row, data.html);
if (!bibContainer) return;
bibContainer.classList.add('batch-mode');
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.setAttribute('readonly', true);
});
updateAutoSelectionInfo(row);
syncBibUiState(row);
});
}
function bibSyncResetAllEprButton(row) {
if (!row) {
return;
}
let wrap = row.querySelector('.epr-identity-reset-all');
if (!wrap) {
return;
}
let avecBib = parseInt(bibQuery(row, '.bib-avec')?.textContent || '0', 10) || 0;
if (avecBib <= 0) {
wrap.classList.add('bib-ui-hidden');
return;
}
wrap.classList.remove('bib-ui-hidden');
let btn = wrap.querySelector('.btn-reset-all-epr');
if (!btn) {
return;
}
let hasLock = row.querySelector('.btn-bib-lock--closed') !== null;
btn.disabled = hasLock;
}
function syncBibUiState(row) {
if (!row) return;
let modes = bibRowModes(row);
let avecBib = parseInt(bibQuery(row, '.bib-avec')?.textContent || '0', 10) || 0;
let hasSequences = bibHasSavedSequences(row);
let hasSelection = bibCountSelectedRanges(row) > 0;
let inBatchFlow = modes.batch || modes.reset;
let inAutoFlow = modes.auto;
let inPickFlow = inBatchFlow || inAutoFlow;
row.querySelectorAll('.team-mode-box input[type="radio"]').forEach(function (radio) {
if (!radio.closest('.team-mode-option.disabled')) {
radio.disabled = avecBib > 0;
}
});
let showReset = hasSequences && (avecBib > 0 || modes.reset)
&& !modes.auto
&& (!modes.batch || modes.reset);
bibSetVisible('.epr-action-batch-group',
hasSequences && ((!modes.reset && !modes.auto) || modes.batch), row);
bibSetVisible('.epr-action-reset-group', showReset, row);
bibSetVisible('.epr-action-auto-group',
hasSequences && !modes.reset && !modes.auto && !modes.batch, row);
if (hasSequences) {
syncAutoUiState(row, row.dataset.autoActive === '1');
}
bibSetVisible('.epr-add-range-row', !inPickFlow, row);
bibSetVisible('.batch-config-container', inBatchFlow, row);
bibSetVisible('.auto-config-container', inAutoFlow, row);
let showPick = inPickFlow && !hasSelection;
let showBatchReady = inBatchFlow && hasSelection;
let showAutoReady = inAutoFlow && hasSelection;
bibSetVisible('.bib-seq-pick-prompt', showPick, row);
bibSetVisible('.batch-config-ready', showBatchReady, row);
bibSetVisible('.auto-config-ready', showAutoReady, row);
let bibContainer = getBibContainer(row);
if (bibContainer) {
bibContainer.classList.toggle('batch-awaiting-selection', showPick);
}
bibSetVisible('.epr-action-desactiver-group',
hasSequences && row.dataset.autoActive === '1' && inAutoFlow, row);
bibSetVisible('.epr-action-cancel-auto-group', inAutoFlow, row);
bibSetVisible('.epr-action-accept-auto-group', showAutoReady, row);
bibSetVisible('.epr-auto-info-group', showAutoReady, row);
bibSetVisible('.batch-reset-warning', showBatchReady && modes.reset, row);
bibSetVisible('.epr-batch-order-wrap', showBatchReady && !modes.reset, row);
bibSetVisible('.epr-batch-order-wrap--secondary', showBatchReady && !modes.reset, row);
bibSetVisible('.epr-action-sim-group', showBatchReady && !modes.reset, row);
bibSetVisible('.epr-action-go-group', showBatchReady, row);
bibSyncResetAllEprButton(row);
}
function updateBatchAnalysis(row) {
if (!row) return;
let totalDispo = 0;
let totalReset = 0;
// =====================
// TOTAL DISPO
// Source officielle = PHP
// JS ne recalcule PAS les disponibilités.
// Il additionne seulement les valeurs affichées dans .bib-dispo.
// =====================
row.querySelectorAll('.batch-select-range:checked').forEach(cb => {
let line = cb.closest('.epr-line');
if (!line) return;
let usedDiv = line.querySelector('.bib-used');
let dispoDiv = line.querySelector('.bib-dispo');
let used = parseInt((usedDiv?.textContent || '0'), 10);
let dispo = parseInt((dispoDiv?.textContent || '0'), 10);
if (isNaN(used)) {
used = 0;
}
if (isNaN(dispo)) {
dispo = 0;
}
totalReset += used;
totalDispo += dispo;
});
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=batch_analysis&epr_id=' + encodeURIComponent(row.dataset.eprId) + bibAjaxLangSuffix()
}, { loader: false })
.then(res => res.json())
.then(data => {
if (!data.success) return;
bibSyncEprBibStats(row, data.info);
syncBibUiState(row);
let sansBib = bibRowPendingBibs(row);
let isResetMode = row.dataset.mode === 'reset';
let message = '';
if (isResetMode) {
if (totalReset === 0) {
message = bibJs('jsBatchNone');
} else {
message = bibJsFmt('jsBatchResetCount', totalReset);
}
} else {
if (totalDispo === 0) {
message = bibJs('jsBatchNone');
} else if (totalDispo < sansBib) {
message = bibJsFmt('jsBatchSummaryShort', totalDispo, sansBib, sansBib - totalDispo);
} else {
message = bibJsFmt('jsBatchSummaryOk', totalDispo, sansBib);
}
}
let info = row.querySelector('.epr-actions .batch-info-text');
if (info && bibCountSelectedRanges(row) > 0) {
info.textContent = message;
}
syncBibUiState(row);
});
}
// =====================
// BATCH CHECKBOX CHANGE (PROPRE)
// =====================
moduleBib.addEventListener('change', function (e) {
// =====================
// TEAM MODE
// =====================
let teamRadio = e.target.closest('.team-mode-box input[type="radio"]');
if (teamRadio) {
if (teamRadio.disabled) return;
let box = teamRadio.closest('.team-mode-box');
if (!box) return;
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=save_team_mode'
+ '&epr_id=' + encodeURIComponent(box.dataset.eprId)
+ '&team_mode=' + encodeURIComponent(teamRadio.value)
+ bibAjaxLangSuffix()
}, { loader: false });
return;
}
let cb = e.target.closest('.batch-select-range');
if (!cb) return;
let row = cb.closest('.epr-row');
if (!row) return;
// MSIN-4379 — Mode auto : même sélection de séquences que le batch, sans GO/simulation.
if (row.classList.contains('auto-mode')) {
updateAutoSelectionInfo(row);
syncBibUiState(row);
return;
}
if (row.dataset.loading === '1') return;
let existing = document.querySelector('.epr-row-view');
if (existing) existing.remove();
row.dataset.loading = '1';
// 1. garder sélection
let selected = [];
row.querySelectorAll('.batch-select-range:checked').forEach(el => {
selected.push(el.dataset.rangeId);
});
// 2. analyse gauche/droite
updateBatchAnalysis(row);
// 3. sortir du cycle du change
setTimeout(() => {
bibFetch('/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=' + encodeURIComponent(row.dataset.mode || 'assign')
+ bibAjaxLangSuffix()
}, { loader: false })
.then(res => res.json())
.then(data => {
if (!data.success) {
row.dataset.loading = '0';
return;
}
setBibContainerHtml(row, data.html);
let container = getBibContainer(row);
if (!container) {
row.dataset.loading = '0';
return;
}
// 4. refresh complet serveur
// Re-sync après refresh serveur
container.classList.add('batch-mode');
// 5. remettre readonly
container.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.setAttribute('readonly', true);
});
// 6. restaurer checkbox
container.querySelectorAll('.batch-select-range').forEach(el => {
if (selected.includes(el.dataset.rangeId)) {
el.checked = true;
}
});
updateBatchAnalysis(row);
row.dataset.loading = '0';
})
.catch(() => {
row.dataset.loading = '0';
});
}, 0);
});
moduleBib.querySelectorAll('.epr-row').forEach(syncBibUiState);
moduleBib.addEventListener('click', function (e) {
let btnQte = e.target.closest('.btn_qte');
if (btnQte && moduleBib.contains(btnQte)) {
e.preventDefault();
bibSaveQte(btnQte);
return;
}
let btnGotoAssign = e.target.closest('.bib-anomaly-goto-assign');
if (btnGotoAssign) {
e.preventDefault();
let eprId = btnGotoAssign.dataset.eprId;
if (!eprId) {
return;
}
let row = moduleBib.querySelector('.epr-row[data-epr-id="' + eprId + '"]');
if (row) {
row.scrollIntoView({ behavior: 'smooth', block: 'start' });
let btnView = row.querySelector('.btn-view-range[data-range-id="0"]');
if (btnView) {
btnView.click();
}
}
return;
}
let btnTrad = e.target.closest('.btn-admin-trad, .btn-bib-trad');
if (btnTrad) {
e.preventDefault();
e.stopPropagation();
let url = btnTrad.getAttribute('data-trad-url');
if (!url) {
return;
}
let clef = btnTrad.getAttribute('data-info-clef') || 'bib_trad';
let popup = window.open(
url,
'bib_trad_' + clef,
'width=960,height=640,scrollbars=yes,resizable=yes'
);
if (popup) {
let timer = setInterval(function () {
if (popup.closed) {
clearInterval(timer);
window.location.reload();
}
}, 400);
}
return;
}
// =====================
// LOCK / UNLOCK SEQUENCE
// =====================
let btnLock = e.target.closest('.btn-bib-lock');
if (btnLock) {
e.preventDefault();
let row = btnLock.closest('.epr-row');
if (!row) return;
let isLocked = btnLock.dataset.locked === '1';
let confirmMsg = isLocked
? bibJsConfirm('jsUnlockConfirm')
: bibJsConfirm('jsLockConfirm');
if (!confirm(confirmMsg)) {
return;
}
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=toggle_lock'
+ '&epr_bib_id=' + encodeURIComponent(btnLock.dataset.rangeId)
+ '&epr_id=' + encodeURIComponent(btnLock.dataset.eprId || row.dataset.eprId)
+ '&locked=' + encodeURIComponent(isLocked ? '0' : '1')
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) {
alert(data.message || bibJs('jsErrGeneric'));
return;
}
if (typeof data.auto_active !== 'undefined') {
row.dataset.autoActive = data.auto_active ? '1' : '0';
syncAutoUiState(row, data.auto_active);
syncBibUiState(row);
}
if (data.html) {
setBibContainerHtml(row, data.html);
bibSyncResetAllEprButton(row);
}
});
return;
}
// =====================
// MSIN-4436 — Réinitialiser tous les dossards (épreuve entière)
// =====================
let btnResetAllEpr = e.target.closest('.btn-reset-all-epr');
if (btnResetAllEpr) {
e.preventDefault();
let row = btnResetAllEpr.closest('.epr-row');
if (!row) {
return;
}
if (btnResetAllEpr.disabled) {
alert(bibJsConfirm('jsResetAllLocked'));
return;
}
if (row.querySelector('.btn-bib-lock--closed')) {
alert(bibJsConfirm('jsResetAllLocked'));
bibSyncResetAllEprButton(row);
return;
}
if (!confirm(bibJsConfirm('jsResetAllConfirm'))) {
return;
}
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=reset_all_apply'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) {
alert(data.message || bibJs('jsErrGeneric'));
return;
}
bibAfterBatchGoSuccess(row, data, false);
});
return;
}
// =====================
// DELETE
// =====================
let btnDelete = e.target.closest('.btn-delete-range');
if (btnDelete) {
e.preventDefault();
let container = btnDelete.closest('.bib-container');
let errorDiv = container.querySelector('.bib-error-global');
// reset erreur
if (errorDiv) {
errorDiv.style.display = 'none';
errorDiv.innerText = '';
}
let id = btnDelete.dataset.id;
if (!id) return;
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=delete&id=' + encodeURIComponent(id) + bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {
let data;
try {
data = JSON.parse(raw);
} catch (err) {
if (errorDiv) {
errorDiv.innerText = bibJs('jsServerError');
errorDiv.style.display = 'block';
}
return;
}
if (!data.success) {
if (errorDiv) {
errorDiv.innerText = data.message || bibJs('jsErrGeneric');
errorDiv.style.display = 'block';
}
return;
}
setBibContainerHtml(btnDelete.closest('.epr-row'), data.html);
});
return;
}
// =====================
// SAVE
// =====================
let btnSave = e.target.closest('.btn-save-range');
if (btnSave) {
e.preventDefault();
let row = btnSave.closest('.bib-range');
let errorDiv = row.nextElementSibling;
let epr_id = btnSave.dataset.eprId;
// reset
if (errorDiv) {
errorDiv.style.display = 'none';
errorDiv.innerText = '';
}
applyBibRangeFieldState(row);
let start = bibRangeParseInt(row.querySelector('.bib-start').value);
let end = bibRangeParseInt(row.querySelector('.bib-end').value);
let id = btnSave.dataset.id;
let validation = bibRangeValidate(row);
// ligne temporaire vide = on la retire
if (id == 0 && start <= 0) {
row.remove();
if (errorDiv && errorDiv.classList.contains('bib-error')) {
errorDiv.remove();
}
return;
}
if (start <= 0 || end <= 0) {
validation = validation || { key: 'incomplete' };
}
if (!validation && end < start) {
validation = { key: 'invalidEnd', field: 'end', start: start };
}
if (validation) {
bibRangeShowValidation(row, validation);
if (errorDiv) {
var msgEl = errorDiv.querySelector('.bib-range-validate-msg');
if (!msgEl) {
errorDiv.innerText = bibRangeValidationMessage(validation);
}
errorDiv.style.display = 'block';
}
var invalidField = validation.field === 'qty'
? row.querySelector('.bib-qty')
: row.querySelector('.bib-end');
if (invalidField) {
invalidField.focus();
}
return;
}
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=save'
+ '&id=' + encodeURIComponent(id)
+ '&epr_id=' + encodeURIComponent(epr_id)
+ '&start=' + encodeURIComponent(start)
+ '&end=' + encodeURIComponent(end)
+ bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {
let data;
try {
data = JSON.parse(raw);
} catch (err) {
errorDiv.innerText = bibJs('jsServerError');
errorDiv.style.display = 'block';
return;
}
if (!data.success) {
errorDiv.innerText = data.message || bibJs('jsErrGeneric');
errorDiv.style.display = 'block';
return;
}
setBibContainerHtml(btnSave.closest('.epr-row'), data.html);
});
return;
}
// =====================
// VIEW
// =====================
let btnView = e.target.closest('.btn-view-range');
if (btnView) {
e.preventDefault();
let epr_id = btnView.dataset.eprId;
let range_id = btnView.dataset.rangeId;
console.log('epr_id:', epr_id);
console.log('range_id:', range_id);
if (!epr_id || typeof range_id === 'undefined') return;
let container = btnView.closest('.epr-block');
// Vérifier si une vue est déjà ouverte
let existing = document.querySelector('.epr-row-view');
// Toggle : si c'est le même œil qui a ouvert la vue, on la ferme et on s'arrête
if (existing
&& existing.dataset.eprId === epr_id
&& existing.dataset.rangeId === range_id
) {
existing.remove();
return;
}
// Un autre œil a été cliqué : fermer la vue précédente avant d'ouvrir la nouvelle
if (existing) {
existing.remove();
}
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=view'
+ '&epr_id=' + encodeURIComponent(epr_id)
+ '&range_id=' + encodeURIComponent(range_id)
+ bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {
let data;
try {
data = JSON.parse(raw);
} catch (err) {
console.log(bibJs('jsServerError'));
return;
}
if (!data.success) {
console.log(data.message || bibJs('jsErrGeneric'));
return;
}
let row = btnView.closest('.epr-row');
// Injecter la nouvelle vue sous la ligne du bouton cliqué,
// en mémorisant epr_id et range_id pour le toggle suivant
row.insertAdjacentHTML('afterend', data.html);
// Stocker les identifiants sur la vue injectée pour pouvoir détecter
// le 2e clic sur le même œil
let newView = row.nextElementSibling;
if (newView && newView.classList.contains('epr-row-view')) {
newView.dataset.eprId = epr_id;
newView.dataset.rangeId = range_id;
}
});
return;
}
// =====================
// CLOSE VIEW
// =====================
let btnClose = e.target.closest('.btn-close-view');
if (btnClose) {
e.preventDefault();
let view = btnClose.closest('.epr-row-view');
if (view) {
view.remove();
}
return;
}
// =====================
// ASSIGN BATCH
// =====================
// Active/désactive le mode batch pour UNE épreuve.
// - Affiche les checkbox
// - Bloque Début/Fin
// - Affiche le bloc de configuration
// - Recalcule lanalyse initiale
// =====================
let btnBatch = e.target.closest('.btn-assign-batch');
if (btnBatch) {
e.preventDefault();
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;
// OFF
if (row.classList.contains('batch-mode')) {
row.classList.remove('batch-mode');
row.querySelectorAll('.batch-select-range').forEach(cb => {
cb.disabled = false;
});
container.classList.remove('batch-mode');
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.removeAttribute('readonly');
});
btnBatch.textContent = row.dataset.batchLabel || btnBatch.textContent;
let goBtn = row.querySelector('.btn-go-batch');
if (goBtn) {
goBtn.textContent = row.dataset.goLabel || goBtn.textContent;
}
row.querySelectorAll('.batch-select-range').forEach(cb => {
cb.checked = false;
});
let info = row.querySelector('.epr-actions .batch-info-text');
if (info) info.textContent = '';
syncBibUiState(row);
return;
}
// ON
row.classList.add('batch-mode');
container.classList.add('batch-mode');
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.setAttribute('readonly', true);
});
btnBatch.textContent = row.dataset.batchLabelCancel || btnBatch.textContent;
let goBtn = row.querySelector('.btn-go-batch');
if (goBtn) {
goBtn.textContent = row.dataset.goLabel || goBtn.textContent;
}
if (typeof updateBatchAnalysis === 'function') {
updateBatchAnalysis(row);
}
syncBibUiState(row);
return;
}
// =====================
// SIMULER BATCH
// =====================
let btnSim = e.target.closest('.btn-simuler-batch');
if (btnSim) {
e.preventDefault();
let row = btnSim.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(bibJs('jsNoSeqSelected'));
return;
}
let isResetMode = row.dataset.mode === 'reset';
let sortKeys = bibGetRowSortKeys(row);
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
(isResetMode ? 'action=reset_preview' : 'action=batch_go')
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
+ bibAppendBatchSortParams('', sortKeys)
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) {
alert(data.message || bibJs('jsErrGeneric'));
return;
}
let existing = document.querySelector('.epr-row-view');
if (existing) {
existing.remove();
}
row.insertAdjacentHTML('afterend', data.html);
});
return;
}
// =====================
// RESET MODE
// =====================
let btnReset = e.target.closest('.btn-reset');
if (btnReset) {
e.preventDefault();
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;
// =====================
// OFF
// =====================
if (row.classList.contains('reset-mode')) {
row.classList.remove('reset-mode');
btnReset.textContent = row.dataset.resetLabel || btnReset.textContent;
container.classList.remove('batch-mode');
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.removeAttribute('readonly');
});
row.querySelectorAll('.batch-select-range').forEach(cb => {
cb.checked = false;
});
let goBtn = row.querySelector('.btn-go-batch');
if (goBtn) {
goBtn.textContent = row.dataset.goLabel || goBtn.textContent;
}
let info = row.querySelector('.epr-actions .batch-info-text');
if (info) {
info.innerHTML = '';
}
row.dataset.mode = '';
syncBibUiState(row);
return;
}
// =====================
// ON
// =====================
row.classList.add('reset-mode');
btnReset.textContent = row.dataset.resetCancelLabel || btnReset.textContent;
row.dataset.mode = 'reset';
container.classList.add('batch-mode');
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.setAttribute('readonly', true);
});
syncBibUiState(row);
let goBtn = row.querySelector('.btn-go-batch');
if (goBtn) {
goBtn.textContent = row.dataset.resetLabel || goBtn.textContent;
}
bibFetch('/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=reset'
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) return;
let container = setBibContainerHtml(row, data.html);
if (!container) return;
container.classList.add('batch-mode');
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
input.setAttribute('readonly', true);
});
syncBibUiState(row);
});
return;
}
// =====================
// GO BATCH
// =====================
let btnGo = e.target.closest('.btn-go-batch');
if (btnGo) {
e.preventDefault();
let row = btnGo.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(bibJs('jsNoSeqSelected'));
return;
}
let isResetMode = row.dataset.mode === 'reset';
let sortKeys = bibGetRowSortKeys(row);
if (isResetMode) {
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=reset_apply'
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
+ bibAppendBatchSortParams('', sortKeys)
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) {
alert(data.message || bibJs('jsErrGeneric'));
return;
}
bibAfterBatchGoSuccess(row, data, true);
});
return;
}
bibRunBatchApplyChunks(row, selected, sortKeys);
return;
}
// =====================
// MSIN-4379 — Étape 2 : AUTO DOSSARD (clics Accepter / Annuler / Désactiver / Activer)
// Prochain tour : étape 67 (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(bibJs('jsNoSeqSelected'));
return;
}
if (bibRowPendingBibs(row) > 0) {
bibAlertAutoPendingBibs(row);
return;
}
// MSIN-4379 — Persiste epr_bib_auto=1 sur les séquences choisies (save_auto_config).
bibFetch('/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))
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) {
alert(data.message || bibJs('jsErrGeneric'));
return;
}
syncAutoUiState(row, true);
exitAutoMode(row);
syncBibUiState(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(bibJs('jsAutoDisableConfirm'))) {
return;
}
bibFetch('/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('[]')
+ bibAjaxLangSuffix()
})
.then(res => res.json())
.then(data => {
if (!data.success) {
alert(data.message || bibJs('jsErrGeneric'));
return;
}
syncAutoUiState(row, false);
exitAutoMode(row);
syncBibUiState(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
// =====================
let btn = e.target.closest('.btn-add-range');
if (!btn) return;
e.preventDefault();
let container = btn.closest('.bib-container');
let errorDiv = container.querySelector('.bib-error-global');
// reset
if (errorDiv) {
errorDiv.style.display = 'none';
errorDiv.innerText = '';
}
let epr_id = btn.dataset.eprId;
if (!epr_id) return;
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=create&epr_id=' + encodeURIComponent(epr_id) + bibAjaxLangSuffix()
})
.then(res => res.text())
.then(raw => {
let data;
try {
data = JSON.parse(raw);
} catch (err) {
if (errorDiv) {
errorDiv.innerText = bibJs('jsServerError');
errorDiv.style.display = 'block';
}
return;
}
if (!data.success) {
console.log('CREATE ERROR:', data);
console.log('container:', container);
console.log('errorDiv:', errorDiv);
if (errorDiv) {
errorDiv.innerText = data.message || bibJs('jsErrGeneric');
errorDiv.style.display = 'block';
}
return;
}
setBibContainerHtml(btn.closest('.epr-row'), data.html);
});
});
function syncBibEventConfigHeaderNote() {
let chk = moduleBib.querySelector('.bib-event-allow-inter-epr');
if (!chk) {
return;
}
document.querySelectorAll('[data-bib-inter-epr-note]').forEach(function (note) {
note.classList.toggle('bib-ui-hidden', !chk.checked);
});
}
// MSIN-4424 — Autoriser mêmes numéros entre épreuves (réglage événement).
let chkAllowInterEpr = moduleBib.querySelector('.bib-event-allow-inter-epr');
if (chkAllowInterEpr) {
chkAllowInterEpr.addEventListener('change', function () {
let eveId = moduleBib.dataset.eveId || '';
if (!eveId) {
return;
}
bibFetch('/ajax_bib_range.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body:
'action=save_allow_inter_epr'
+ '&eve_id=' + encodeURIComponent(eveId)
+ '&allow=' + (chkAllowInterEpr.checked ? '1' : '0')
+ bibAjaxLangSuffix()
})
.then(function (res) { return res.json(); })
.then(function (data) {
if (!data.success) {
chkAllowInterEpr.checked = !chkAllowInterEpr.checked;
alert(data.message || bibJs('jsErrGeneric'));
return;
}
moduleBib.dataset.allowInterEpr = data.allow_inter_epr ? '1' : '0';
syncBibEventConfigHeaderNote();
let mount = document.getElementById('bib-anomalies-mount');
if (mount && data.anomalies_html) {
let blnWasActive = bibActiveTool === 'anomalies';
if (blnWasActive) {
bibRestoreToolContent('anomalies');
}
bibInvalidateToolSlot('anomalies');
mount.innerHTML = data.anomalies_html;
initModuleBibTippy(mount);
bibSyncToolNavBadges('anomalies');
bibRemountActiveToolAfterRefresh('anomalies');
}
if (bibQtySummaryShouldRefresh()) {
refreshBibQtySummaryPanel();
}
})
.catch(function () {
chkAllowInterEpr.checked = !chkAllowInterEpr.checked;
alert(bibJs('jsErrGeneric'));
});
});
}
// MSIN-4436 — Anomalies : coquille légère au chargement, détail en AJAX.
if (document.querySelector('#bib-anomalies-panel[data-bib-anomalies-deferred="1"]')) {
refreshBibAnomaliesPanel().then(function () {
bibSyncAllToolNavBadges();
bibApplyFocusFromUrlOnce();
});
} else {
bibSyncAllToolNavBadges();
bibApplyFocusFromUrlOnce();
}
}
})();