diff --git a/css/style.css b/css/style.css index dc0e570..7d4a94b 100644 --- a/css/style.css +++ b/css/style.css @@ -3890,6 +3890,18 @@ a.ms1-trad-link.btn-aide-trad{ text-decoration:none; } +/* MSIN-4448 — Colonne dossard plus large quand edition inline active. */ +.inscr-gestion-list--can-edit-bib{ + --ig-list-cols: + minmax(9.5rem, 1.15fr) + minmax(11rem, 1.9fr) + minmax(6.75rem, 0.7fr) + minmax(6.5rem, 8.5rem) + minmax(5.5rem, 7.5rem) + 2.5rem + 1.15rem; +} + /* En-tete de colonnes : meme grille que les lignes pour un alignement parfait. */ .inscr-gestion-list-cols{ display:grid; @@ -3916,28 +3928,51 @@ a.ms1-trad-link.btn-aide-trad{ border-bottom:none; } -.inscr-gestion-list > a.inscr-gestion-list-item:nth-of-type(even){ +/* Zebra : en-tete = child 1 ; 1re ligne (child 2) blanche, 2e (child 3) alternee. */ +.inscr-gestion-list > .inscr-gestion-list-item:nth-child(odd){ background:#f7faff; } .inscr-gestion-list-item:hover, -.inscr-gestion-list-item:focus{ +.inscr-gestion-list-item:focus-within{ color:inherit; text-decoration:none; background:#eaf3ff; } +.inscr-gestion-list-item a.inscr-gestion-list-item__name, +.inscr-gestion-list-item a.inscr-gestion-list-item__race, +.inscr-gestion-list-item a.inscr-gestion-list-item__order, +.inscr-gestion-list-item a.inscr-gestion-list-item__statut{ + color:inherit; + text-decoration:none; + min-width:0; +} + +.inscr-gestion-list-item a.inscr-gestion-list-item__arrow{ + text-decoration:none; + min-width:0; +} + +.inscr-gestion-list-item a.inscr-gestion-list-item__name:hover, +.inscr-gestion-list-item a.inscr-gestion-list-item__race:hover, +.inscr-gestion-list-item a.inscr-gestion-list-item__order:hover, +.inscr-gestion-list-item a.inscr-gestion-list-item__statut:hover{ + color:inherit; + text-decoration:none; +} + .inscr-gestion-list-item--cancellation{ background:#fff5f5; border-color:#f1b0b7; } -.inscr-gestion-list-item--cancellation:nth-of-type(even){ +.inscr-gestion-list > .inscr-gestion-list-item--cancellation:nth-child(odd){ background:#fff0f0; } .inscr-gestion-list-item--cancellation:hover, -.inscr-gestion-list-item--cancellation:focus{ +.inscr-gestion-list-item--cancellation:focus-within{ background:#ffecec; } @@ -4010,6 +4045,57 @@ a.ms1-trad-link.btn-aide-trad{ min-width:0; } +/* MSIN-4448 — Saisie dossard compacte dans la liste (sans camera). */ +.inscr-gestion-list-bib-edit{ + display:inline-flex; + align-items:center; + gap:4px; + max-width:100%; + vertical-align:middle; +} + +.inscr-gestion-list-bib-input{ + width:4.25rem; + max-width:100%; + padding:2px 6px; + font-size:12px; + font-weight:700; + font-variant-numeric:tabular-nums; + text-align:center; + line-height:1.35; +} + +.inscr-gestion-list-bib-edit .btn_bib{ + padding:2px 7px; + font-size:11px; + line-height:1.35; + flex-shrink:0; +} + +button.inscr-gestion-list-remis{ + margin:0; + padding:0; + cursor:pointer; + appearance:none; + -webkit-appearance:none; + background:inherit; + border:none; +} + +button.inscr-gestion-list-remis.inscr-gestion-remis--no{ + background:#eef1f4; + border:1px solid #dee2e6; +} + +button.inscr-gestion-list-remis:focus{ + outline:2px solid #80bdff; + outline-offset:2px; +} + +button.inscr-gestion-list-remis:hover{ + filter:brightness(0.97); +} + .inscr-gestion-bib-pill{ display:inline-block; max-width:100%; @@ -4099,6 +4185,9 @@ a.ms1-trad-link.btn-aide-trad{ } .inscr-gestion-list-item__arrow{ + display:inline-flex; + align-items:center; + justify-content:center; color:#8aa8d4; flex-shrink:0; justify-self:end; @@ -4116,6 +4205,16 @@ a.ms1-trad-link.btn-aide-trad{ 1.15rem; } + .inscr-gestion-list--can-edit-bib{ + --ig-list-cols: + minmax(8.5rem, 1.2fr) + minmax(10rem, 2fr) + minmax(6rem, 8rem) + minmax(4.75rem, 6.5rem) + 2.5rem + 1.15rem; + } + .inscr-gestion-list-cols__order, .inscr-gestion-list-item__order{ display:none; @@ -4832,7 +4931,7 @@ a.ms1-trad-link.btn-aide-trad{ border-radius:0; } - .inscr-gestion-list > a.inscr-gestion-list-item:nth-of-type(even){ + .inscr-gestion-list > .inscr-gestion-list-item:nth-child(odd){ background:#f7faff; } diff --git a/js/v2/inscr-gestion.js b/js/v2/inscr-gestion.js index cb01d1c..d9af67c 100644 --- a/js/v2/inscr-gestion.js +++ b/js/v2/inscr-gestion.js @@ -54,6 +54,109 @@ var $preloader = $('#preloader'); var $preloader_text = $('#preloader_text'); + // MSIN-4448 — Remis inline liste (meme endpoint / confirmation que la fiche ; UI pastille). + (function () { + var remisOp = cfg.remisOperator || {}; + var remisTable = (typeof window.btoa === 'function') + ? window.btoa('resultats_participants') + : ''; + + function applyListRemisUi($btn, remisYes) { + $btn.toggleClass('inscr-gestion-remis--yes', remisYes); + $btn.toggleClass('inscr-gestion-remis--no', !remisYes); + $btn.attr('aria-pressed', remisYes ? 'true' : 'false'); + $btn.data('valeur', remisYes ? 0 : 1); + if (remisYes) { + $btn.html(''); + } else { + $btn.empty(); + } + } + + function doListRemis($btn) { + var intId = parseInt($btn.data('id'), 10) || 0; + var intValeur = parseInt($btn.data('valeur'), 10); + if (intId <= 0 || (intValeur !== 0 && intValeur !== 1)) { + return; + } + + $preloader_text.html(cfg.preloaderWait || ''); + $preloader.show(); + + $.post((cfg.domain || '') + '/superadm/enregistrer.php', { + action: 'remis', + table: remisTable, + field: 'no_bib_remis', + key: 'par_id', + valeur: intValeur, + id: intId, + par_id: remisOp.par_id || 0, + par: remisOp.par || '' + }, function (result) { + $preloader.fadeOut(); + if (fxInscrRedirectIfSessionExpired(result)) { + return; + } + if (result && result.state === 'success') { + applyListRemisUi($btn, intValeur === 1); + } else { + window.alert((result && (result.message || result.state)) || t('errNetwork') || 'Error'); + } + }, 'json').fail(function () { + $preloader.fadeOut(); + window.alert(t('errNetwork') || 'Error'); + }); + } + + $body.on('click', '.inscr-gestion-list-remis', function (event) { + event.preventDefault(); + event.stopPropagation(); + var $btn = $(this); + var intValeur = parseInt($btn.data('valeur'), 10); + + // Retrait (valeur 0) : confirmation — meme garde-fou que la fiche. + if (intValeur === 0) { + if (typeof window.bootbox === 'undefined') { + if (window.confirm(t('remisConfirmMsg'))) { + doListRemis($btn); + } + return; + } + window.bootbox.confirm({ + title: t('remisConfirmTitle') || 'Confirmation', + message: t('remisConfirmMsg'), + buttons: { + confirm: { + label: t('remisConfirmOk') || 'OK', + className: 'btn btn-danger rounded-0' + }, + cancel: { + label: t('remisConfirmCancel') || 'Cancel', + className: 'btn btn-secondary rounded-0' + } + }, + callback: function (ok) { + if (ok === true) { + doListRemis($btn); + } + } + }); + return; + } + + doListRemis($btn); + }); + + // Valider le dossard inline avec Entree (declenche le .btn_bib legacy). + $body.on('keydown', '.inscr-gestion-list-bib-input', function (event) { + if (event.which !== 13 && event.key !== 'Enter') { + return; + } + event.preventDefault(); + $(this).closest('.inscr-gestion-list-bib-edit').find('.btn_bib').trigger('click'); + }); + })(); + (function () { var pendingStatutXhr = null; var lastStatutParId = null; diff --git a/php/inc_fx_inscriptions_gestion.php b/php/inc_fx_inscriptions_gestion.php index 8a55af5..50ea99e 100644 --- a/php/inc_fx_inscriptions_gestion.php +++ b/php/inc_fx_inscriptions_gestion.php @@ -484,6 +484,14 @@ function fxInscrGestionFallbackTexte($strClef, $strLangue) { // MSIN-4399 — Colonne statut de course (entre dossard et remis). 'inscr_gestion_col_statut' => $blnFr ? 'Statut' : 'Status', 'inscr_gestion_col_remis' => $blnFr ? 'Remis' : 'Issued', + // MSIN-4448 — Edition inline liste (OK dossard + confirmation remis). + 'inscr_gestion_bib_ok' => 'OK', + 'inscr_gestion_remis_confirm_title' => $blnFr ? 'Confirmation' : 'Confirmation', + 'inscr_gestion_remis_confirm_msg' => $blnFr + ? 'Êtes-vous certain de vouloir retirer la mention « dossard récupéré » pour ce participant ?' + : 'Are you sure you want to remove the "bib retrieved" status for this participant?', + 'inscr_gestion_remis_confirm_ok' => $blnFr ? 'Retirer' : 'Remove', + 'inscr_gestion_remis_confirm_cancel' => $blnFr ? 'Annuler' : 'Cancel', // MSIN-4328 — bouton superadmin vers fiche ChronoTrack 'inscr_gestion_btn_chronotrack' => $blnFr ? 'Voir dans ChronoTrack' : 'View in ChronoTrack', 'inscr_gestion_list_count_one' => $blnFr ? '%d inscription' : '%d registration', @@ -2057,7 +2065,19 @@ function fxInscrGestionRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) { echo ''; if ($intNbTotal > 0) { - echo '
'; + // MSIN-4448 — Edition inline dossard / remis selon droits granulaires (sans camera). + $intComId = intval($_SESSION['com_id'] ?? 0); + $blnCanBib = fxInscrGestionCanDo($intComId, $intEveId, 'inscriptions_gestion.bib_edit'); + $blnCanRemis = fxInscrGestionCanDo($intComId, $intEveId, 'inscriptions_gestion.bib_remis'); + + $strListClass = 'inscr-gestion-list'; + if ($blnCanBib) { + $strListClass .= ' inscr-gestion-list--can-edit-bib'; + } + if ($blnCanRemis) { + $strListClass .= ' inscr-gestion-list--can-edit-remis'; + } + echo '
'; // En-tete de colonnes (memes colonnes que les lignes ; masque en vue cellulaire). // aria-hidden : purement visuel — libellés Info (pas de FR/EN en dur). @@ -2078,12 +2098,16 @@ function fxInscrGestionRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) { echo ''; echo '
'; + $strRemisLabel = fxInscrGestionT('promoteur_bib_enregistre'); + $strBibOkLabel = fxInscrGestionT('inscr_gestion_bib_ok'); + for ($j = $intStart; $j <= $intEnd; $j++) { $row = $tabRows[$j]; $strFicheUrl = fxInscrGestionBuildUrl($strBaseUrl, $intEveId, $arrReq, array( 'pec_id' => (int)$row['pec_id_original'], 'pg' => $intPage, )); + $strFicheHref = fxInscrGestionEsc($strFicheUrl); $strBib = fxInscrGestionBibDisplay($row); $strName = fxUnescape($row['par_nom']) . ', ' . fxUnescape($row['par_prenom']); @@ -2105,30 +2129,70 @@ function fxInscrGestionRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) { . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_statut_' . $strCause)) . ''; } - $strRemisLabel = fxInscrGestionT('promoteur_bib_enregistre'); $blnRemis = (intval($row['no_bib_remis']) === 1); + $intParId = (int)$row['par_id']; + $blnEquipe = (intval($row['pec_equipe']) === 1); + + // MSIN-4448 — Ligne en div : cellules nav (lien) vs dossard/remis editables. + echo '
'; + echo '' + . fxInscrGestionEsc($strName) . $strCancelBadge . ''; + echo '' . fxInscrGestionEsc($strRace) . ''; + echo '' + . fxInscrGestionEsc($row['no_commande']) . ''; - echo ''; - echo '' . fxInscrGestionEsc($strName) . $strCancelBadge . ''; - echo '' - . fxInscrGestionEsc($strRace) . ''; - echo '' . fxInscrGestionEsc($row['no_commande']) . ''; echo ''; - if (trim($strBib) !== '') { + if ($blnCanBib) { + // Meme ids / classes que la fiche → handlers footer (doublon + ajax_promoteur). + $strBibAction = $blnEquipe ? 'no_equipe' : 'no_bib'; + $strBibInputId = ($blnEquipe ? 'txt_no_bib_e' : 'txt_no_bib_p') . $intParId; + echo '
'; + echo ''; + echo ''; + echo '
'; + } elseif (trim($strBib) !== '') { echo '' . fxInscrGestionEsc($strBib) . ''; } else { echo ''; } echo '
'; - // MSIN-4399 — Affichage lecture seule (édition sur la fiche). + + // MSIN-4399 — Statut de course en lecture seule dans la liste (edition sur la fiche). $strStatutMod = preg_replace('/[^A-Za-z0-9_-]/', '', strtolower($strStatutCode)); - echo ''; + echo '
'; echo '' . fxInscrGestionEsc($strStatutLabel) . ''; - echo ''; + echo ''; + echo ''; - if ($blnRemis) { + if ($blnCanRemis) { + $intRemisVal = $blnRemis ? 0 : 1; + $strRemisMod = $blnRemis ? 'yes' : 'no'; + echo ''; + } elseif ($blnRemis) { echo ''; echo ''; @@ -2138,8 +2202,11 @@ function fxInscrGestionRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) { echo ''; } echo ''; - echo ''; - echo ''; + + echo '' + . ''; + echo '
'; } echo '
'; diff --git a/php/inc_settings.php b/php/inc_settings.php index b219fd5..5cfc3b6 100644 --- a/php/inc_settings.php +++ b/php/inc_settings.php @@ -7,8 +7,8 @@ * Constantes * * **************/ -define('_VERSION_CODE', '4.72.823'); -define('_DATE_CODE', '2026-07-14'); +define('_VERSION_CODE', '4.72.824'); +define('_DATE_CODE', '2026-07-15'); //MSIN-4290 define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe'); diff --git a/php/inc_v2_assets.php b/php/inc_v2_assets.php index c96d005..0a710bb 100644 --- a/php/inc_v2_assets.php +++ b/php/inc_v2_assets.php @@ -114,7 +114,21 @@ if (!function_exists('fxV2RegisterScript')) { 'bibScanCamera' => function_exists('fxInscrGestionScanLabel') ? fxInscrGestionScanLabel('inscr_gestion_qr_camera_error') : '', + // MSIN-4448 — Remis inline liste (confirmation retrait). + 'remisConfirmTitle' => fxInscrGestionT('inscr_gestion_remis_confirm_title'), + 'remisConfirmMsg' => fxInscrGestionT('inscr_gestion_remis_confirm_msg'), + 'remisConfirmOk' => fxInscrGestionT('inscr_gestion_remis_confirm_ok'), + 'remisConfirmCancel' => fxInscrGestionT('inscr_gestion_remis_confirm_cancel'), ] : [], + // MSIN-4448 — Operateur pour no_bib_remis_par (chemin superadm / usa_id). + 'remisOperator' => [ + 'par_id' => intval($_SESSION['com_info']['com_id'] ?? ($_SESSION['com_id'] ?? 0)), + 'par' => trim( + (string)($_SESSION['com_info']['com_prenom'] ?? '') + . ' ' + . (string)($_SESSION['com_info']['com_nom'] ?? '') + ), + ], ]; } diff --git a/sql/MSIN-4448-inscr-gestion-list-inline-bib-remis.sql b/sql/MSIN-4448-inscr-gestion-list-inline-bib-remis.sql new file mode 100644 index 0000000..b9d2492 --- /dev/null +++ b/sql/MSIN-4448-inscr-gestion-list-inline-bib-remis.sql @@ -0,0 +1,48 @@ +-- MSIN-4448 — Edition inline dossard / remis dans la liste + libelles droits / Info +-- Prefrequis : permissions inscriptions_gestion.bib_edit / bib_remis (phase 2 acces v2) +-- Idempotent (UPDATE permissions + DELETE/INSERT info) + +/* ------------------------------------------------------------------ + 1. Clarifier les droits kits : lecture seule = sans la case ; + lecture-ecriture = case cochee (liste + fiche). + ------------------------------------------------------------------ */ +UPDATE `inscriptions_eve_permissions` +SET + `perm_label_fr` = 'Gestion inscription : no dossard (liste + fiche)', + `perm_label_en` = 'Registration mgmt: bib number (list + sheet)', + `perm_description_fr` = 'Modifier le numero de dossard dans la liste et sur la fiche (lecture seule si non coche)', + `perm_description_en` = 'Edit bib number in the list and on the sheet (read-only if unchecked)' +WHERE `perm_key` = 'inscriptions_gestion.bib_edit'; + +UPDATE `inscriptions_eve_permissions` +SET + `perm_label_fr` = 'Gestion inscription : dossard remis (liste + fiche)', + `perm_label_en` = 'Registration mgmt: bib handed out (list + sheet)', + `perm_description_fr` = 'Marquer dossard remis dans la liste et sur la fiche (lecture seule si non coche)', + `perm_description_en` = 'Mark bib handed out in the list and on the sheet (read-only if unchecked)' +WHERE `perm_key` = 'inscriptions_gestion.bib_remis'; + +/* ------------------------------------------------------------------ + 2. Libelles Info (confirmation remis + OK) + ------------------------------------------------------------------ */ +DELETE FROM info +WHERE info_prg = 'compte.php' + AND info_clef IN ( + 'inscr_gestion_bib_ok', + 'inscr_gestion_remis_confirm_title', + 'inscr_gestion_remis_confirm_msg', + 'inscr_gestion_remis_confirm_ok', + 'inscr_gestion_remis_confirm_cancel' + ); + +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) VALUES +('inscr_gestion_bib_ok', 'fr', 'OK', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_bib_ok', 'en', 'OK', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_title', 'fr', 'Confirmation', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_title', 'en', 'Confirmation', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_msg', 'fr', 'Êtes-vous certain de vouloir retirer la mention « dossard récupéré » pour ce participant ?', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_msg', 'en', 'Are you sure you want to remove the "bib retrieved" status for this participant?', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_ok', 'fr', 'Retirer', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_ok', 'en', 'Remove', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_cancel', 'fr', 'Annuler', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW()), +('inscr_gestion_remis_confirm_cancel', 'en', 'Cancel', '', 'compte.php', 'MSIN-4448', 0, 1, '', '', '', NOW());