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 '