Implement quantity summary panel and global configuration settings for bib assignments (MSIN-4424)
This commit introduces a new AJAX action for retrieving a summary of quantities related to bib assignments, enhancing event management capabilities. A collapsible configuration panel is added for global settings, allowing users to manage bib assignment options more effectively. The CSS is updated to style the new elements, and relevant database entries are created to support the new features. The version code is incremented to 4.72.751 to reflect these changes.
This commit is contained in:
@ -1132,6 +1132,29 @@ if ($action == 'anomalies') {
|
||||
exit;
|
||||
}
|
||||
|
||||
// MSIN-4424 — Sommaire des quantités (toutes épreuves)
|
||||
if ($action == 'qty_summary') {
|
||||
|
||||
$int_eve_id = (int)($_POST['eve_id'] ?? $_GET['eve_id'] ?? 0);
|
||||
|
||||
if ($int_eve_id <= 0) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => fxBibMsg('bib_v4_ajax_epr_invalid')
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$tabSummary = fxBibCollectEventQtySummary($int_eve_id, $strLangue);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'totals' => $tabSummary['totals'] ?? [],
|
||||
'html' => renderBibQtySummaryPanel($int_eve_id, $strLangue, $tabSummary),
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// =====================
|
||||
// ACTION INVALIDE
|
||||
// =====================
|
||||
|
||||
136
css/style.css
136
css/style.css
@ -1064,34 +1064,8 @@ ul.ms1-menu-compte li a:hover, ul.ms1-menu-compte li a:active {
|
||||
line-height:1.45;
|
||||
}
|
||||
|
||||
/* MSIN-4424 — Bandeau réglages dossards (haut du module). */
|
||||
.bib-event-settings{
|
||||
border:1px solid #c8d6e5;
|
||||
border-radius:6px;
|
||||
background:#f8fafc;
|
||||
padding:10px 14px;
|
||||
margin-bottom:4px;
|
||||
}
|
||||
|
||||
.bib-event-settings__label{
|
||||
display:flex;
|
||||
align-items:flex-start;
|
||||
gap:8px;
|
||||
margin:0;
|
||||
font-weight:600;
|
||||
font-size:14px;
|
||||
line-height:1.4;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.bib-event-settings__label input[type="checkbox"]{
|
||||
margin-top:3px;
|
||||
flex-shrink:0;
|
||||
}
|
||||
|
||||
.bib-event-settings__text{
|
||||
flex:1 1 auto;
|
||||
}
|
||||
/* MSIN-4424 — ancien bandeau remplacé par panneau repliable .bib-event-config-panel */
|
||||
|
||||
.bib-anomaly-block--inter-epr-dupes .bib-anomaly-block-title{
|
||||
color:#8a3b12;
|
||||
@ -2537,6 +2511,114 @@ a.ms1-trad-link.btn-aide-trad{
|
||||
margin:0;
|
||||
}
|
||||
|
||||
/* MSIN-4424 — Panneau configuration globale (contenu dans .epr-content). */
|
||||
.bib-event-config-content{
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
.bib-event-config-content .bib-event-settings__label{
|
||||
display:flex;
|
||||
align-items:flex-start;
|
||||
gap:8px;
|
||||
margin:0;
|
||||
font-weight:600;
|
||||
font-size:14px;
|
||||
line-height:1.4;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.bib-event-config-content .bib-event-settings__label input[type="checkbox"]{
|
||||
margin-top:3px;
|
||||
flex-shrink:0;
|
||||
}
|
||||
|
||||
.bib-event-config-content .bib-event-settings__text{
|
||||
flex:1 1 auto;
|
||||
}
|
||||
|
||||
/* MSIN-4424 — Sommaire des quantités (même gabarit que anomalies). */
|
||||
.bib-qty-summary-panel--alert{
|
||||
border-color:#f0ad4e;
|
||||
}
|
||||
|
||||
.bib-qty-summary-badges{
|
||||
display:inline-flex;
|
||||
flex-wrap:wrap;
|
||||
align-items:center;
|
||||
gap:6px;
|
||||
}
|
||||
|
||||
.bib-qty-summary-badges--pending{
|
||||
font-size:12px;
|
||||
opacity:.85;
|
||||
}
|
||||
|
||||
.bib-qty-summary-badge{
|
||||
font-size:12px;
|
||||
font-weight:600;
|
||||
}
|
||||
|
||||
.bib-qty-summary-badge--warn{
|
||||
background:rgba(220,53,69,.9);
|
||||
border-color:rgba(220,53,69,.9);
|
||||
}
|
||||
|
||||
.bib-qty-summary-content{
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
.bib-qty-summary-section-title{
|
||||
margin:0 0 10px;
|
||||
font-size:14px;
|
||||
font-weight:700;
|
||||
color:#212529;
|
||||
}
|
||||
|
||||
.bib-qty-summary-totals{
|
||||
margin-bottom:16px;
|
||||
}
|
||||
|
||||
.bib-qty-summary-dl{
|
||||
display:grid;
|
||||
grid-template-columns:repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap:8px 16px;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.bib-qty-summary-dl__row{
|
||||
display:flex;
|
||||
justify-content:space-between;
|
||||
gap:10px;
|
||||
padding:8px 10px;
|
||||
background:#f8f9fa;
|
||||
border:1px solid #e9ecef;
|
||||
border-radius:4px;
|
||||
font-size:13px;
|
||||
}
|
||||
|
||||
.bib-qty-summary-dl__row dt{
|
||||
margin:0;
|
||||
font-weight:600;
|
||||
color:#495057;
|
||||
}
|
||||
|
||||
.bib-qty-summary-dl__row dd{
|
||||
margin:0;
|
||||
font-weight:700;
|
||||
color:#212529;
|
||||
}
|
||||
|
||||
.bib-qty-summary-table th,
|
||||
.bib-qty-summary-table td{
|
||||
font-size:13px;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.bib-qty-summary-by-epr{
|
||||
border-top:1px solid #e9ecef;
|
||||
padding-top:14px;
|
||||
}
|
||||
|
||||
.bib-anomalies-panel{
|
||||
margin-bottom:14px;
|
||||
border:1px solid #ced4da;
|
||||
|
||||
@ -920,6 +920,12 @@
|
||||
icon.classList.toggle('fa-chevron-up', !collapsed);
|
||||
icon.classList.toggle('fa-chevron-down', collapsed);
|
||||
}
|
||||
|
||||
// MSIN-4424 — Sommaire quantités : chargement à la première ouverture.
|
||||
if (!collapsed && block.id === 'bib-qty-summary-panel'
|
||||
&& block.getAttribute('data-bib-qty-summary-deferred') === '1') {
|
||||
refreshBibQtySummaryPanel();
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
@ -1065,6 +1071,64 @@
|
||||
});
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
let eveId = moduleBib.dataset.eveId || '';
|
||||
if (!eveId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let blnWasExpanded = panel && !panel.classList.contains('is-collapsed');
|
||||
|
||||
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;
|
||||
}
|
||||
mount.innerHTML = data.html;
|
||||
initModuleBibTippy(mount);
|
||||
if (blnWasExpanded) {
|
||||
let newPanel = document.getElementById('bib-qty-summary-panel');
|
||||
if (newPanel) {
|
||||
newPanel.classList.remove('is-collapsed');
|
||||
let btn = newPanel.querySelector('.epr-block-toggle');
|
||||
if (btn) {
|
||||
btn.setAttribute('aria-expanded', 'true');
|
||||
let icon = btn.querySelector('.fa');
|
||||
if (icon) {
|
||||
icon.classList.remove('fa-chevron-down');
|
||||
icon.classList.add('fa-chevron-up');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
@ -1084,6 +1148,9 @@
|
||||
if (!opts.skipAnomalies) {
|
||||
refreshBibAnomaliesPanel();
|
||||
}
|
||||
if (!opts.skipQtySummary && bibQtySummaryShouldRefresh()) {
|
||||
refreshBibQtySummaryPanel();
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
@ -2746,6 +2813,10 @@
|
||||
mount.innerHTML = data.anomalies_html;
|
||||
initModuleBibTippy(mount);
|
||||
}
|
||||
|
||||
if (bibQtySummaryShouldRefresh()) {
|
||||
refreshBibQtySummaryPanel();
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
chkAllowInterEpr.checked = !chkAllowInterEpr.checked;
|
||||
|
||||
@ -2997,6 +2997,18 @@ function fxBibStaticFallback($clef) {
|
||||
'bib_v4_js_global_no_seq' => ['fr' => 'Cochez au moins une séquence pour les épreuves sélectionnées.', 'en' => 'Check at least one sequence for the selected races.'],
|
||||
'bib_v4_global_batch_plan_invalid' => ['fr' => 'Sélection invalide : choisissez au moins une épreuve solo et des séquences.', 'en' => 'Invalid selection: pick at least one solo race and sequences.'],
|
||||
'bib_v4_global_batch_need_two' => ['fr' => "L'assignation globale nécessite au moins deux épreuves solo avec des séquences disponibles.", 'en' => 'Global assignment requires at least two solo races with available sequences.'],
|
||||
'bib_v4_event_config_title' => ['fr' => "Configuration globale pour l'assignation de dossard", 'en' => 'Global bib assignment settings'],
|
||||
'bib_v4_qty_summary_title' => ['fr' => 'Sommaire des quantités', 'en' => 'Quantity summary'],
|
||||
'bib_v4_qty_summary_a_assigner' => ['fr' => 'À assigner', 'en' => 'To assign'],
|
||||
'bib_v4_qty_summary_bib_restant' => ['fr' => 'Dossards restants', 'en' => 'Bibs remaining'],
|
||||
'bib_v4_qty_summary_orphelins' => ['fr' => 'Personnes orphelines', 'en' => 'Orphan participants'],
|
||||
'bib_v4_qty_summary_total' => ['fr' => 'Inscrits', 'en' => 'Registered'],
|
||||
'bib_v4_qty_summary_avec_bib' => ['fr' => 'Avec dossard', 'en' => 'With bib'],
|
||||
'bib_v4_qty_summary_sans_bib' => ['fr' => 'Sans dossard', 'en' => 'Without bib'],
|
||||
'bib_v4_qty_summary_places_dispo' => ['fr' => 'Places disponibles', 'en' => 'Places available'],
|
||||
'bib_v4_qty_summary_global' => ['fr' => 'Total événement', 'en' => 'Event total'],
|
||||
'bib_v4_qty_summary_by_epr' => ['fr' => 'Détail par épreuve', 'en' => 'Breakdown by race'],
|
||||
'bib_v4_qty_summary_col_epr' => ['fr' => 'Épreuve', 'en' => 'Race'],
|
||||
'bib_v4_ajax_global_sim_summary' => ['fr' => '%d épreuve(s) · %d dispo / %d à assigner → %d assignables (%d manque)', 'en' => '%d race(s) · %d avail. / %d to assign → %d assignable (%d short)'],
|
||||
];
|
||||
|
||||
@ -4226,7 +4238,11 @@ function fxShowBibTool4($str_code, $int_eve_id, $strLangue){
|
||||
|
||||
<div id="module-bib" class="epr-wrapper" data-csrf-token="<?php echo fxBibEsc(fxBibCsrfToken()); ?>" data-lang="<?php echo fxBibEsc($strLangue); ?>" data-eve-id="<?php echo (int)$int_eve_id; ?>" data-allow-inter-epr="<?php echo fxBibEventAllowsInterEprDuplicates((int)$int_eve_id) ? '1' : '0'; ?>"<?php echo fxBibModuleJsDataAttrs(); ?><?php echo fxAdminTextEditModeActive() ? ' data-bib-trad="1"' : ''; ?>>
|
||||
|
||||
<?php echo renderBibEventSettingsBanner((int)$int_eve_id, $strLangue); ?>
|
||||
<?php echo renderBibEventConfigPanel((int)$int_eve_id, $strLangue); ?>
|
||||
|
||||
<div id="bib-qty-summary-mount">
|
||||
<?php echo renderBibQtySummaryPanelShell((int)$int_eve_id, $strLangue); ?>
|
||||
</div>
|
||||
|
||||
<div id="bib-anomalies-mount">
|
||||
<?php echo renderBibAnomaliesPanelShell((int)$int_eve_id, $strLangue); ?>
|
||||
@ -5112,22 +5128,285 @@ function fxBibAnomalyTotalCount(array $tabAnomalies) {
|
||||
return $intTotal;
|
||||
}
|
||||
|
||||
/** MSIN-4424 — Bandeau réglages dossards (haut du module, au-dessus des épreuves). */
|
||||
function renderBibEventSettingsBanner($int_eve_id, $strLangue = 'fr') {
|
||||
/** MSIN-4424 — Corps du panneau configuration globale (réglages événement). */
|
||||
function renderBibEventConfigPanelContent($int_eve_id) {
|
||||
$int_eve_id = (int)$int_eve_id;
|
||||
$blnAllow = fxBibEventAllowsInterEprDuplicates($int_eve_id);
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div class="bib-event-settings" data-eve-id="<?php echo $int_eve_id; ?>">
|
||||
<label class="bib-event-settings__label">
|
||||
<input type="checkbox"
|
||||
class="bib-event-allow-inter-epr"
|
||||
value="1"
|
||||
<?php echo $blnAllow ? ' checked' : ''; ?>>
|
||||
<span class="bib-event-settings__text"><?php fxBibTexte('bib_v4_allow_inter_epr', 1); ?></span>
|
||||
<?php echo fxBibAideButton('bib_v4_allow_inter_epr', '', false); ?>
|
||||
</label>
|
||||
<label class="bib-event-settings__label">
|
||||
<input type="checkbox"
|
||||
class="bib-event-allow-inter-epr"
|
||||
value="1"
|
||||
<?php echo $blnAllow ? ' checked' : ''; ?>>
|
||||
<span class="bib-event-settings__text"><?php fxBibTexte('bib_v4_allow_inter_epr', 1); ?></span>
|
||||
<?php echo fxBibAideButton('bib_v4_allow_inter_epr', '', false); ?>
|
||||
</label>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/** MSIN-4424 — Panneau repliable : configuration globale assignation dossards (événement). */
|
||||
function renderBibEventConfigPanel($int_eve_id, $strLangue = 'fr') {
|
||||
$int_eve_id = (int)$int_eve_id;
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div id="bib-event-config-panel"
|
||||
class="bib-event-config-panel bib-anomalies-panel epr-block is-collapsed"
|
||||
data-eve-id="<?php echo $int_eve_id; ?>">
|
||||
<div class="epr-header bib-anomalies-header">
|
||||
<span class="epr-header-label bib-anomalies-header-label">
|
||||
<?php echo fxBibEsc(fxBibTexte('bib_v4_event_config_title', 0)); ?>
|
||||
<?php echo fxBibAideButton('bib_v4_event_config_title'); ?>
|
||||
</span>
|
||||
<?php echo fxBibBlockCollapseToggle($strLangue, true); ?>
|
||||
</div>
|
||||
<div class="epr-content bib-event-config-content">
|
||||
<?php echo renderBibEventConfigPanelContent($int_eve_id); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* MSIN-4424 — Agrège les quantités dossards / inscriptions pour tout l'événement.
|
||||
*
|
||||
* @return array{totals: array<string, int>, epreuves: array<int, array<string, mixed>>}
|
||||
*/
|
||||
function fxBibCollectEventQtySummary($int_eve_id, $strLangue = 'fr') {
|
||||
global $objDatabase;
|
||||
|
||||
$int_eve_id = (int)$int_eve_id;
|
||||
$tabTotals = [
|
||||
'a_assigner' => 0,
|
||||
'bib_restant' => 0,
|
||||
'orphelins' => 0,
|
||||
'total' => 0,
|
||||
'avec_bib' => 0,
|
||||
'sans_bib' => 0,
|
||||
'places_dispo' => 0,
|
||||
];
|
||||
$tabEpreuvesRows = [];
|
||||
|
||||
if ($int_eve_id <= 0) {
|
||||
return ['totals' => $tabTotals, 'epreuves' => $tabEpreuvesRows];
|
||||
}
|
||||
|
||||
$sqlEpreuves = "
|
||||
SELECT *
|
||||
FROM inscriptions_epreuves
|
||||
WHERE eve_id = $int_eve_id
|
||||
AND epr_actif = 1
|
||||
ORDER BY epr_id
|
||||
";
|
||||
$tabEpreuves = $objDatabase->fxGetResults($sqlEpreuves);
|
||||
if (!is_array($tabEpreuves)) {
|
||||
$tabEpreuves = [];
|
||||
}
|
||||
|
||||
$tabOrphans = fxBibAnomalyOrphanBibs($int_eve_id, $strLangue);
|
||||
$tabOrphansByEpr = [];
|
||||
foreach ($tabOrphans as $item) {
|
||||
$intEprId = (int)($item['epr_id'] ?? 0);
|
||||
if ($intEprId > 0) {
|
||||
$tabOrphansByEpr[$intEprId] = ($tabOrphansByEpr[$intEprId] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($tabEpreuves as $epr) {
|
||||
$epr_id = (int)$epr['epr_id'];
|
||||
$infoBib = fxInfosBibEpreuve($epr_id);
|
||||
$arrQte = fxGetQuantites($epr_id);
|
||||
|
||||
$intBibRestant = 0;
|
||||
$tabRanges = fxInfosBibRange($epr_id, 0, false);
|
||||
if (is_array($tabRanges)) {
|
||||
foreach ($tabRanges as $range) {
|
||||
if (is_array($range)) {
|
||||
$intBibRestant += fxBibRangeDispoFromRow($range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tabRow = [
|
||||
'epr_id' => $epr_id,
|
||||
'epr_label' => fxBibAnomalyEprLabel($epr, $strLangue),
|
||||
'total' => (int)($infoBib['total'] ?? 0),
|
||||
'avec_bib' => (int)($infoBib['avec_bib'] ?? 0),
|
||||
'sans_bib' => (int)($infoBib['sans_bib'] ?? 0),
|
||||
'a_assigner' => (int)($infoBib['a_assigner'] ?? 0),
|
||||
'bib_restant' => $intBibRestant,
|
||||
'orphelins' => (int)($tabOrphansByEpr[$epr_id] ?? 0),
|
||||
'places_dispo' => (int)($arrQte['qte_restante'] ?? 0),
|
||||
];
|
||||
$tabEpreuvesRows[] = $tabRow;
|
||||
|
||||
$tabTotals['a_assigner'] += $tabRow['a_assigner'];
|
||||
$tabTotals['bib_restant'] += $tabRow['bib_restant'];
|
||||
$tabTotals['total'] += $tabRow['total'];
|
||||
$tabTotals['avec_bib'] += $tabRow['avec_bib'];
|
||||
$tabTotals['sans_bib'] += $tabRow['sans_bib'];
|
||||
$tabTotals['places_dispo'] += $tabRow['places_dispo'];
|
||||
}
|
||||
|
||||
$tabTotals['orphelins'] = count($tabOrphans);
|
||||
|
||||
return ['totals' => $tabTotals, 'epreuves' => $tabEpreuvesRows];
|
||||
}
|
||||
|
||||
/** MSIN-4424 — Coquille sommaire quantités (détail chargé à la première ouverture). */
|
||||
function renderBibQtySummaryPanelShell($int_eve_id, $strLangue = 'fr') {
|
||||
global $vDomaine;
|
||||
|
||||
$int_eve_id = (int)$int_eve_id;
|
||||
$strWait = fxBibTexte('bib_v4_js_loader_wait', 0);
|
||||
if ($strWait === '' || $strWait === 'bib_v4_js_loader_wait') {
|
||||
$strWait = ($strLangue === 'en') ? 'Loading...' : 'Chargement...';
|
||||
}
|
||||
$strRunnerSrc = $vDomaine . '/images/ms1-runner-loader.gif?v=' . _VERSION_CODE;
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div id="bib-qty-summary-panel"
|
||||
class="bib-qty-summary-panel bib-anomalies-panel epr-block is-collapsed"
|
||||
data-eve-id="<?php echo $int_eve_id; ?>"
|
||||
data-bib-qty-summary-deferred="1">
|
||||
<div class="epr-header bib-anomalies-header">
|
||||
<span class="epr-header-label bib-anomalies-header-label">
|
||||
<?php echo fxBibEsc(fxBibTexte('bib_v4_qty_summary_title', 0)); ?>
|
||||
<?php echo fxBibAideButton('bib_v4_qty_summary_title'); ?>
|
||||
<span class="bib-qty-summary-badges bib-qty-summary-badges--pending" aria-hidden="true">…</span>
|
||||
</span>
|
||||
<?php echo fxBibBlockCollapseToggle($strLangue, true); ?>
|
||||
</div>
|
||||
<div class="epr-content bib-qty-summary-content">
|
||||
<div class="ms1-loader ms1-loader--inline" role="status" aria-live="polite" aria-busy="true">
|
||||
<img class="ms1-loader__runner"
|
||||
src="<?php echo fxBibEsc($strRunnerSrc); ?>"
|
||||
alt=""
|
||||
role="presentation"
|
||||
decoding="async">
|
||||
<span class="ms1-loader__label"><?php echo fxBibEsc($strWait); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/** MSIN-4424 — Panneau sommaire des quantités (HTML). */
|
||||
function renderBibQtySummaryPanel($int_eve_id, $strLangue = 'fr', $tabSummary = null) {
|
||||
$int_eve_id = (int)$int_eve_id;
|
||||
if ($tabSummary === null) {
|
||||
$tabSummary = fxBibCollectEventQtySummary($int_eve_id, $strLangue);
|
||||
}
|
||||
|
||||
$tabTotals = $tabSummary['totals'] ?? [];
|
||||
$tabEpreuves = $tabSummary['epreuves'] ?? [];
|
||||
$blnHasPending = (int)($tabTotals['a_assigner'] ?? 0) > 0;
|
||||
$blnHasOrphans = (int)($tabTotals['orphelins'] ?? 0) > 0;
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div id="bib-qty-summary-panel"
|
||||
class="bib-qty-summary-panel bib-anomalies-panel epr-block<?php echo ($blnHasPending || $blnHasOrphans) ? ' bib-qty-summary-panel--alert' : ''; ?> is-collapsed"
|
||||
data-eve-id="<?php echo $int_eve_id; ?>"
|
||||
data-bib-qty-summary-loaded="1">
|
||||
<div class="epr-header bib-anomalies-header">
|
||||
<span class="epr-header-label bib-anomalies-header-label">
|
||||
<?php echo fxBibEsc(fxBibTexte('bib_v4_qty_summary_title', 0)); ?>
|
||||
<?php echo fxBibAideButton('bib_v4_qty_summary_title'); ?>
|
||||
<span class="bib-qty-summary-badges">
|
||||
<span class="epr-header-summary epr-header-summary--bib bib-qty-summary-badge">
|
||||
<?php echo fxBibEsc(fxBibTexte('bib_v4_qty_summary_a_assigner', 0)); ?> :
|
||||
<strong><?php echo (int)($tabTotals['a_assigner'] ?? 0); ?></strong>
|
||||
</span>
|
||||
<span class="epr-header-summary epr-header-summary--dispo bib-qty-summary-badge">
|
||||
<?php echo fxBibEsc(fxBibTexte('bib_v4_qty_summary_bib_restant', 0)); ?> :
|
||||
<strong><?php echo (int)($tabTotals['bib_restant'] ?? 0); ?></strong>
|
||||
</span>
|
||||
<span class="epr-header-summary bib-qty-summary-badge<?php echo $blnHasOrphans ? ' bib-qty-summary-badge--warn' : ''; ?>">
|
||||
<?php echo fxBibEsc(fxBibTexte('bib_v4_qty_summary_orphelins', 0)); ?> :
|
||||
<strong><?php echo (int)($tabTotals['orphelins'] ?? 0); ?></strong>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<?php echo fxBibBlockCollapseToggle($strLangue, true); ?>
|
||||
</div>
|
||||
<div class="epr-content bib-qty-summary-content">
|
||||
<section class="bib-qty-summary-totals" aria-label="<?php echo fxBibEsc(fxBibTexte('bib_v4_qty_summary_global', 0)); ?>">
|
||||
<h3 class="bib-qty-summary-section-title"><?php fxBibTexteTrad('bib_v4_qty_summary_global', 1); ?></h3>
|
||||
<dl class="bib-qty-summary-dl">
|
||||
<div class="bib-qty-summary-dl__row">
|
||||
<dt><?php fxBibTexteTrad('bib_v4_qty_summary_a_assigner', 1); ?></dt>
|
||||
<dd><?php echo (int)($tabTotals['a_assigner'] ?? 0); ?></dd>
|
||||
</div>
|
||||
<div class="bib-qty-summary-dl__row">
|
||||
<dt><?php fxBibTexteTrad('bib_v4_qty_summary_bib_restant', 1); ?></dt>
|
||||
<dd><?php echo (int)($tabTotals['bib_restant'] ?? 0); ?></dd>
|
||||
</div>
|
||||
<div class="bib-qty-summary-dl__row">
|
||||
<dt><?php fxBibTexteTrad('bib_v4_qty_summary_orphelins', 1); ?></dt>
|
||||
<dd><?php echo (int)($tabTotals['orphelins'] ?? 0); ?></dd>
|
||||
</div>
|
||||
<div class="bib-qty-summary-dl__row">
|
||||
<dt><?php fxBibTexteTrad('bib_v4_qty_summary_total', 1); ?></dt>
|
||||
<dd><?php echo (int)($tabTotals['total'] ?? 0); ?></dd>
|
||||
</div>
|
||||
<div class="bib-qty-summary-dl__row">
|
||||
<dt><?php fxBibTexteTrad('bib_v4_qty_summary_avec_bib', 1); ?></dt>
|
||||
<dd><?php echo (int)($tabTotals['avec_bib'] ?? 0); ?></dd>
|
||||
</div>
|
||||
<div class="bib-qty-summary-dl__row">
|
||||
<dt><?php fxBibTexteTrad('bib_v4_qty_summary_sans_bib', 1); ?></dt>
|
||||
<dd><?php echo (int)($tabTotals['sans_bib'] ?? 0); ?></dd>
|
||||
</div>
|
||||
<div class="bib-qty-summary-dl__row">
|
||||
<dt><?php fxBibTexteTrad('bib_v4_qty_summary_places_dispo', 1); ?></dt>
|
||||
<dd><?php echo (int)($tabTotals['places_dispo'] ?? 0); ?></dd>
|
||||
</div>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<?php if (!empty($tabEpreuves)) { ?>
|
||||
<section class="bib-qty-summary-by-epr">
|
||||
<h3 class="bib-qty-summary-section-title"><?php fxBibTexteTrad('bib_v4_qty_summary_by_epr', 1); ?></h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered bib-qty-summary-table mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"><?php fxBibTexteTrad('bib_v4_qty_summary_col_epr', 1); ?></th>
|
||||
<th scope="col" class="text-right"><?php fxBibTexteTrad('bib_v4_qty_summary_a_assigner', 1); ?></th>
|
||||
<th scope="col" class="text-right"><?php fxBibTexteTrad('bib_v4_qty_summary_bib_restant', 1); ?></th>
|
||||
<th scope="col" class="text-right"><?php fxBibTexteTrad('bib_v4_qty_summary_orphelins', 1); ?></th>
|
||||
<th scope="col" class="text-right"><?php fxBibTexteTrad('bib_v4_qty_summary_total', 1); ?></th>
|
||||
<th scope="col" class="text-right"><?php fxBibTexteTrad('bib_v4_qty_summary_avec_bib', 1); ?></th>
|
||||
<th scope="col" class="text-right"><?php fxBibTexteTrad('bib_v4_qty_summary_sans_bib', 1); ?></th>
|
||||
<th scope="col" class="text-right"><?php fxBibTexteTrad('bib_v4_qty_summary_places_dispo', 1); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($tabEpreuves as $row) { ?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo fxBibEsc($row['epr_label'] ?? ''); ?></th>
|
||||
<td class="text-right"><?php echo (int)($row['a_assigner'] ?? 0); ?></td>
|
||||
<td class="text-right"><?php echo (int)($row['bib_restant'] ?? 0); ?></td>
|
||||
<td class="text-right"><?php echo (int)($row['orphelins'] ?? 0); ?></td>
|
||||
<td class="text-right"><?php echo (int)($row['total'] ?? 0); ?></td>
|
||||
<td class="text-right"><?php echo (int)($row['avec_bib'] ?? 0); ?></td>
|
||||
<td class="text-right"><?php echo (int)($row['sans_bib'] ?? 0); ?></td>
|
||||
<td class="text-right"><?php echo (int)($row['places_dispo'] ?? 0); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* Constantes *
|
||||
*
|
||||
**************/
|
||||
define('_VERSION_CODE', '4.72.750');
|
||||
define('_VERSION_CODE', '4.72.751');
|
||||
define('_DATE_CODE', '2026-07-08');
|
||||
//MSIN-4290
|
||||
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');
|
||||
|
||||
@ -33,6 +33,99 @@ INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_
|
||||
SELECT 'bib_v4_anomalies_inter_epr_dupes_title', 'fr', 'Dossards en double entre épreuves', 'Même numéro de dossard utilisé sur plus d''une épreuve alors que l''option n''est pas activée.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_anomalies_inter_epr_dupes_title' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_anomalies_inter_epr_dupes_title', 'en', 'Duplicate bibs across races', 'Same bib number used on more than one race while the option is disabled.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_anomalies_inter_epr_dupes_title' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
SELECT 'bib_v4_event_config_title', 'fr', 'Configuration globale pour l''assignation de dossard', 'Réglages applicables à tout l''événement (ex. autorisation des mêmes numéros entre épreuves).', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_event_config_title' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_event_config_title', 'en', 'Global bib assignment settings', 'Settings that apply to the whole event (e.g. allowing the same numbers across races).', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_event_config_title' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_title', 'fr', 'Sommaire des quantités', 'Vue d''ensemble des dossards à assigner, restants et orphelins pour toutes les épreuves.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_title' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_title', 'en', 'Quantity summary', 'Overview of bibs to assign, remaining and orphans across all races.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_title' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_a_assigner', 'fr', 'À assigner', 'Participants sans dossard, éligibles à l''assignation par lot.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_a_assigner' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_a_assigner', 'en', 'To assign', 'Participants without a bib, eligible for batch assignment.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_a_assigner' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_bib_restant', 'fr', 'Dossards restants', 'Numéros encore libres dans les séquences configurées.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_bib_restant' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_bib_restant', 'en', 'Bibs remaining', 'Numbers still free in configured sequences.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_bib_restant' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_orphelins', 'fr', 'Personnes orphelines', 'Dossards assignés à des participants annulés ou d''une autre épreuve.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_orphelins' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_orphelins', 'en', 'Orphan participants', 'Bibs assigned to cancelled participants or from another race.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_orphelins' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_total', 'fr', 'Inscrits', 'Nombre total de participants actifs.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_total' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_total', 'en', 'Registered', 'Total number of active participants.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_total' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_avec_bib', 'fr', 'Avec dossard', 'Participants ayant déjà un numéro de dossard.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_avec_bib' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_avec_bib', 'en', 'With bib', 'Participants who already have a bib number.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_avec_bib' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_sans_bib', 'fr', 'Sans dossard', 'Participants actifs sans numéro de dossard.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_sans_bib' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_sans_bib', 'en', 'Without bib', 'Active participants without a bib number.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_sans_bib' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_places_dispo', 'fr', 'Places disponibles', 'Places d''inscription encore disponibles par épreuve.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_places_dispo' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_places_dispo', 'en', 'Places available', 'Registration spots still available per race.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_places_dispo' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_global', 'fr', 'Total événement', 'Somme des quantités pour toutes les épreuves actives.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_global' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_global', 'en', 'Event total', 'Sum of quantities for all active races.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_global' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_by_epr', 'fr', 'Détail par épreuve', 'Répartition des quantités pour chaque épreuve.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_by_epr' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_by_epr', 'en', 'Breakdown by race', 'Quantity breakdown for each race.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_by_epr' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_col_epr', 'fr', 'Épreuve', 'Nom de l''épreuve.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_col_epr' AND info_langue = 'fr' AND info_prg = 'compte.php');
|
||||
|
||||
INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation)
|
||||
SELECT 'bib_v4_qty_summary_col_epr', 'en', 'Race', 'Race name.', 'compte.php', '', 0, 1, '', '', '', NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_qty_summary_col_epr' AND info_langue = 'en' AND info_prg = 'compte.php');
|
||||
|
||||
Reference in New Issue
Block a user