From 39fd1103886d499775e740224f71cab7a616feeb Mon Sep 17 00:00:00 2001 From: stephan Date: Mon, 20 Jul 2026 12:01:41 -0400 Subject: [PATCH] =?UTF-8?q?MSIN-4459=20=E2=80=94=20Implement=20team=20memb?= =?UTF-8?q?er=20display=20under=20captain=20in=20participant=20list.=20Upd?= =?UTF-8?q?ate=20CSS=20for=20layout=20adjustments=20and=20add=20new=20SQL?= =?UTF-8?q?=20query=20to=20fetch=20team=20members.=20Increment=20version?= =?UTF-8?q?=20code=20to=204.72.836.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/style.css | 52 ++++++++- php/inc_fx_inscriptions_gestion.php | 123 +++++++++++++++++++++- php/inc_settings.php | 4 +- sql/MSIN-4459-inscr-gestion-list-team.sql | 16 +++ 4 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 sql/MSIN-4459-inscr-gestion-list-team.sql diff --git a/css/style.css b/css/style.css index e411664..3dc3e3d 100644 --- a/css/style.css +++ b/css/style.css @@ -4048,6 +4048,15 @@ a.ms1-trad-link.btn-aide-trad{ display:contents; } +/* MSIN-4459 — cellule participant : capitaine + nom d'équipe + coéquipiers */ +.inscr-gestion-list-item__who{ + min-width:0; + display:flex; + flex-direction:column; + align-items:stretch; + gap:3px; +} + .inscr-gestion-list-item__name{ font-weight:700; font-size:14px; @@ -4059,6 +4068,46 @@ a.ms1-trad-link.btn-aide-trad{ gap:8px; } +.inscr-gestion-list-item__team{ + font-size:12px; + font-weight:500; + color:#495057; + line-height:1.35; +} + +.inscr-gestion-list-mates{ + list-style:none; + margin:2px 0 0; + padding:2px 0 0 10px; + border-left:3px solid #c5d8f0; + width:100%; +} + +.inscr-gestion-list-mates__item{ + font-size:12px; + font-weight:500; + color:#495057; + line-height:1.4; + padding:1px 0; +} + +.inscr-gestion-list-mates__link{ + color:inherit; + text-decoration:none; + display:inline-block; + max-width:100%; +} + +.inscr-gestion-list-mates__link:hover{ + color:#004085; + text-decoration:underline; +} + +.inscr-gestion-list-mates__role{ + color:#6c757d; + font-weight:400; +} + /* MSIN-4405 — la pastille de cause se colle au bord droit de la cellule du nom */ .inscr-gestion-list-item__name .inscr-gestion-cancel-badge{ margin-left:auto; @@ -5037,7 +5086,8 @@ button.inscr-gestion-list-remis:hover{ background:#f7faff; } - .inscr-gestion-list-item__name{ grid-area:name; } + .inscr-gestion-list-item__who{ grid-area:name; } + .inscr-gestion-list-item__name{ display:flex; } .inscr-gestion-list-item__race{ grid-area:race; white-space:normal; diff --git a/php/inc_fx_inscriptions_gestion.php b/php/inc_fx_inscriptions_gestion.php index 063a9cb..97aa501 100644 --- a/php/inc_fx_inscriptions_gestion.php +++ b/php/inc_fx_inscriptions_gestion.php @@ -542,6 +542,9 @@ function fxInscrGestionFallbackTexte($strClef, $strLangue) { : 'Bib search mode', 'chk_bib' => $blnFr ? 'Sans numéro de dossard' : 'Without bib number', 'inscr_gestion_reset_search' => $blnFr ? 'Réinitialiser la recherche' : 'Reset search', + // MSIN-4459 — Nom d'équipe + coéquipiers sous le capitaine en liste. + 'inscr_gestion_list_team_name' => $blnFr ? 'Nom d\'équipe : %s' : 'Team name: %s', + 'inscr_gestion_list_teammate' => $blnFr ? 'Coéquipier' : 'Teammate', ); } @@ -979,9 +982,10 @@ function fxInscrGestionFetchRows($intEveId, $arrReq) { global $objDatabase; $strWhere = fxInscrGestionBuildWhere($intEveId, $arrReq); + // MSIN-4459 — pec_nom_equipe pour affichage du nom d'équipe en liste (1 ligne = 1 commande). $sql = 'SELECT p.no_bib, p.no_bib_remis, p.no_bib_remis_date, p.no_bib_remis_par, p.par_statut_course, p.par_id, p.par_equipe,' . ' p.par_prenom, p.par_nom, e.pec_id_original, e.epr_id, e.eve_id, e.pec_id, e.is_cancelled, e.pec_actif, p.rol_id,' - . ' e.no_commande, e.no_panier, e.no_equipe, e.pec_equipe' + . ' e.no_commande, e.no_panier, e.no_equipe, e.pec_equipe, e.pec_nom_equipe' . ' FROM resultats_epreuves_commandees e, resultats_participants p' . ' WHERE ' . $strWhere . ' AND p.pec_id = e.pec_id_original' . ' GROUP BY e.pec_id_original' @@ -990,6 +994,53 @@ function fxInscrGestionFetchRows($intEveId, $arrReq) { return $objDatabase->fxGetResults($sql); } +/** + * MSIN-4459 — Membres d'équipe pour enrichir la liste (sous le capitaine). + * Une requête batch par page ; exclut rol_id 3/4 (comme promoteur). + * + * @param array $arrPecIds pec_id_original + * @return array map pec_id => liste de participants (capitaine en premier si present) + */ +function fxInscrGestionFetchTeamMembersByPecs($arrPecIds) { + global $objDatabase; + + $arrIds = array(); + if (is_array($arrPecIds)) { + foreach ($arrPecIds as $intPec) { + $intPec = intval($intPec); + if ($intPec > 0) { + $arrIds[$intPec] = $intPec; + } + } + } + if (count($arrIds) === 0) { + return array(); + } + + $sql = 'SELECT pec_id, par_id, par_nom, par_prenom, rol_id, no_bib_remis, par_statut_course' + . ' FROM resultats_participants' + . ' WHERE pec_id IN (' . implode(',', $arrIds) . ')' + . ' AND rol_id NOT IN (3, 4)' + . ' ORDER BY pec_id, CASE WHEN rol_id = 1 THEN 0 ELSE 1 END, par_nom, par_prenom'; + + $tab = $objDatabase->fxGetResults($sql); + $map = array(); + if (!is_array($tab) || count($tab) === 0) { + return $map; + } + + $intNb = count($tab); + for ($i = 1; $i <= $intNb; $i++) { + $intPec = intval($tab[$i]['pec_id']); + if (!isset($map[$intPec])) { + $map[$intPec] = array(); + } + $map[$intPec][] = $tab[$i]; + } + + return $map; +} + function fxInscrGestionFetchRowByPec($intPecId, $intEveId) { global $objDatabase; @@ -2133,6 +2184,16 @@ function fxInscrGestionRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) { $strRemisLabel = fxInscrGestionT('promoteur_bib_enregistre'); $strBibOkLabel = fxInscrGestionT('inscr_gestion_bib_ok'); + $strTeammateLabel = fxInscrGestionT('inscr_gestion_list_teammate'); + + // MSIN-4459 — Membres d'équipe de la page courante (1 requête batch). + $arrTeamPecs = array(); + for ($jTeam = $intStart; $jTeam <= $intEnd; $jTeam++) { + if (!empty($tabRows[$jTeam]) && intval($tabRows[$jTeam]['pec_equipe']) === 1) { + $arrTeamPecs[] = (int)$tabRows[$jTeam]['pec_id_original']; + } + } + $tabTeamMembersByPec = fxInscrGestionFetchTeamMembersByPecs($arrTeamPecs); for ($j = $intStart; $j <= $intEnd; $j++) { $row = $tabRows[$j]; @@ -2142,6 +2203,42 @@ function fxInscrGestionRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) { )); $strFicheHref = fxInscrGestionEsc($strFicheUrl); + $blnEquipe = (intval($row['pec_equipe']) === 1); + $intPecId = (int)$row['pec_id_original']; + $tabMates = array(); + $strTeamName = ''; + + // MSIN-4459 — Ligne parente = capitaine ; coéquipiers en sous-liste. + if ($blnEquipe) { + $strTeamName = trim(fxUnescape(isset($row['pec_nom_equipe']) ? $row['pec_nom_equipe'] : '')); + $tabMembers = isset($tabTeamMembersByPec[$intPecId]) ? $tabTeamMembersByPec[$intPecId] : array(); + $arrCaptain = null; + foreach ($tabMembers as $arrMem) { + if ((int)$arrMem['rol_id'] === 1 && $arrCaptain === null) { + $arrCaptain = $arrMem; + } else { + $tabMates[] = $arrMem; + } + } + if ($arrCaptain !== null) { + $row['par_nom'] = $arrCaptain['par_nom']; + $row['par_prenom'] = $arrCaptain['par_prenom']; + $row['par_id'] = $arrCaptain['par_id']; + $row['no_bib_remis'] = $arrCaptain['no_bib_remis']; + $row['par_statut_course'] = $arrCaptain['par_statut_course']; + $row['rol_id'] = 1; + } else { + // Pas de capitaine : garder la ligne GROUP BY ; exclure ce par_id des mates. + $intMainPar = (int)$row['par_id']; + $tabMates = array(); + foreach ($tabMembers as $arrMem) { + if ((int)$arrMem['par_id'] !== $intMainPar) { + $tabMates[] = $arrMem; + } + } + } + } + $strBib = fxInscrGestionBibDisplay($row); $strName = fxUnescape($row['par_nom']) . ', ' . fxUnescape($row['par_prenom']); $strRace = fxInscrGestionEpreuveLabel($row['epr_id'], $strLangue); @@ -2157,19 +2254,39 @@ function fxInscrGestionRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) { if ($row['is_cancelled'] == '1') { // MSIN-4405 — Cause derivee en lecture seule (aucune ecriture en base). $strCause = fxGetAnnulationCause($row['pec_id_original'], $row['pec_actif']); - $strCardClass .= ' inscr-gestion-list-item--cancelled inscr-gestion-list-item--' . $strCause; + $strCardClass .= ' inscr-gestion-list-item--cancellation inscr-gestion-list-item--' . $strCause; $strCancelBadge = ' ' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_statut_' . $strCause)) . ''; } $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 '
'; + // MSIN-4459 — Bloc nom : capitaine + nom d'équipe + coéquipiers. + echo '
'; echo '' . fxInscrGestionEsc($strName) . $strCancelBadge . ''; + if ($blnEquipe && $strTeamName !== '') { + echo '' + . fxInscrGestionEsc(sprintf(fxInscrGestionT('inscr_gestion_list_team_name'), $strTeamName)) + . ''; + } + if ($blnEquipe && count($tabMates) > 0) { + echo ''; + } + echo '
'; echo '' . fxInscrGestionEsc($strRace) . ''; echo '' diff --git a/php/inc_settings.php b/php/inc_settings.php index 97848e8..7edf56a 100644 --- a/php/inc_settings.php +++ b/php/inc_settings.php @@ -7,8 +7,8 @@ * Constantes * * **************/ -define('_VERSION_CODE', '4.72.835'); -define('_DATE_CODE', '2026-07-16'); +define('_VERSION_CODE', '4.72.836'); +define('_DATE_CODE', '2026-07-20'); //MSIN-4290 define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe'); diff --git a/sql/MSIN-4459-inscr-gestion-list-team.sql b/sql/MSIN-4459-inscr-gestion-list-team.sql new file mode 100644 index 0000000..e106b85 --- /dev/null +++ b/sql/MSIN-4459-inscr-gestion-list-team.sql @@ -0,0 +1,16 @@ +-- MSIN-4459 — Liste inscriptions : nom d'équipe + libellé coéquipier +-- Prérequis : aucun +-- Idempotent (DELETE + INSERT). Compte.php (contexte AJAX / fiche gestion). + +DELETE FROM info +WHERE info_prg = 'compte.php' + AND info_clef IN ( + 'inscr_gestion_list_team_name', + 'inscr_gestion_list_teammate' + ); + +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_list_team_name', 'fr', 'Nom d\'équipe : %s', '', 'compte.php', '', 0, 1, '', '', '', NOW()), +('inscr_gestion_list_team_name', 'en', 'Team name: %s', '', 'compte.php', '', 0, 1, '', '', '', NOW()), +('inscr_gestion_list_teammate', 'fr', 'Coéquipier', '', 'compte.php', '', 0, 1, '', '', '', NOW()), +('inscr_gestion_list_teammate', 'en', 'Teammate', '', 'compte.php', '', 0, 1, '', '', '', NOW());