Files
ms1inscription-v5/php/inc_fx_inscriptions_mobile.php

963 lines
40 KiB
PHP

<?php
/**
* Liste inscriptions mobile — recherche, filtres, cartes, fiche.
*/
function fxInscrMobileIsEntry() {
return defined('MS1_INSCR_MOBILE_ENTRY') && MS1_INSCR_MOBILE_ENTRY;
}
function fxInscrMobileGetPromoteurEveIds($intComId) {
global $objDatabase;
$row = $objDatabase->fxGetRow(
'SELECT com_eve_promoteur FROM inscriptions_comptes WHERE com_id = ' . intval($intComId)
);
if ($row === null || trim((string)$row['com_eve_promoteur']) === '') {
return array();
}
$tab = array_map('intval', array_filter(explode(',', $row['com_eve_promoteur'])));
return array_values($tab);
}
function fxInscrMobileBaseUrl($strLangue, $blnMobileEntry = null) {
global $vDomaine;
if ($blnMobileEntry === null) {
$blnMobileEntry = fxInscrMobileIsEntry();
}
if ($blnMobileEntry) {
return $vDomaine . '/mobile';
}
return $vDomaine . ($strLangue === 'fr' ? '/compte/inc_tableau_inscriptions_mobile' : '/account/inc_tableau_inscriptions_mobile');
}
function fxInscrMobileEsc($str) {
return htmlspecialchars((string)$str, ENT_QUOTES, 'UTF-8');
}
/** Libellé i18n sans echo parasite. */
function fxInscrMobileT($clef) {
return afficheTexte($clef, 0);
}
function fxInscrMobileRenderNavBack($strUrl, $strLabel) {
echo '<a class="btn btn-primary rounded-pill inscr-mobile-nav-back" href="' . fxInscrMobileEsc($strUrl) . '">';
echo '<i class="fa fa-chevron-left mr-2" aria-hidden="true"></i>' . fxInscrMobileEsc($strLabel);
echo '</a>';
}
function fxInscrMobileRenderPageHead($strTitle, $strSub = '') {
echo '<div class="inscr-mobile-page-head">';
echo '<h1 class="inscr-mobile-page-title">' . fxInscrMobileEsc($strTitle) . '</h1>';
if (trim((string)$strSub) !== '') {
echo '<p class="inscr-mobile-page-sub text-muted mb-0">' . fxInscrMobileEsc($strSub) . '</p>';
}
echo '</div>';
}
function fxInscrMobileRenderSectionTitle($strLabel, $strIconClass) {
echo '<h2 class="inscr-mobile-fiche-section__title">';
echo '<i class="fa ' . fxInscrMobileEsc($strIconClass) . ' inscr-mobile-fiche-section__icon" aria-hidden="true"></i>';
echo '<span>' . fxInscrMobileEsc($strLabel) . '</span>';
echo '</h2>';
}
function fxInscrMobileRenderPanelSummary($strLabel, $strIconClass) {
echo '<i class="fa ' . fxInscrMobileEsc($strIconClass) . ' inscr-mobile-panel__icon" aria-hidden="true"></i>';
echo '<span>' . fxInscrMobileEsc($strLabel) . '</span>';
}
function fxInscrMobileParseEveId($strRaw) {
if ($strRaw === null || $strRaw === '') {
return 0;
}
$strDecoded = base64_decode(urldecode($strRaw), true);
if ($strDecoded === false || $strDecoded === '') {
return 0;
}
return (int)$strDecoded;
}
function fxInscrMobileParseRequest() {
$arr = array(
'rech_prenom' => isset($_GET['rech_prenom']) ? trim($_GET['rech_prenom']) : '',
'rech_nom' => isset($_GET['rech_nom']) ? trim($_GET['rech_nom']) : '',
'rech_no_commande' => isset($_GET['rech_no_commande']) ? trim($_GET['rech_no_commande']) : '',
'rech_nom_equipe' => isset($_GET['rech_nom_equipe']) ? trim($_GET['rech_nom_equipe']) : '',
'chk_bib' => !empty($_GET['chk_bib']) ? 1 : 0,
'chk_cancelled' => !empty($_GET['chk_cancelled']) ? 1 : 0,
'sel_rech_epreuve' => 0,
'pg' => isset($_GET['pg']) ? max(1, intval($_GET['pg'])) : 1,
'pec_id' => isset($_GET['pec_id']) ? intval($_GET['pec_id']) : 0,
);
if (!empty($_GET['sel_rech_epreuve'])) {
$decoded = base64_decode(urldecode($_GET['sel_rech_epreuve']), true);
if ($decoded !== false && $decoded !== '') {
$arr['sel_rech_epreuve'] = intval($decoded);
} else {
$arr['sel_rech_epreuve'] = intval($_GET['sel_rech_epreuve']);
}
}
return $arr;
}
function fxInscrMobileFilterActiveCount($arrReq) {
$int = 0;
if ($arrReq['sel_rech_epreuve'] > 0) {
$int++;
}
if ($arrReq['chk_bib']) {
$int++;
}
if ($arrReq['chk_cancelled']) {
$int++;
}
return $int;
}
function fxInscrMobileBuildWhere($intEveId, $arrReq) {
global $objDatabase;
$strWhere = ' e.eve_id = ' . intval($intEveId);
if ($arrReq['rech_nom'] !== '') {
$strWhere .= ' AND p.par_nom LIKE "%' . $objDatabase->fxEscape($arrReq['rech_nom']) . '%"';
}
if ($arrReq['rech_prenom'] !== '') {
$strWhere .= ' AND p.par_prenom LIKE "%' . $objDatabase->fxEscape($arrReq['rech_prenom']) . '%"';
}
if ($arrReq['rech_no_commande'] !== '') {
$strWhere .= ' AND p.no_commande LIKE "%' . $objDatabase->fxEscape($arrReq['rech_no_commande']) . '%"';
}
if ($arrReq['rech_nom_equipe'] !== '') {
$strWhere .= ' AND p.par_nom_equipe LIKE "%' . $objDatabase->fxEscape($arrReq['rech_nom_equipe']) . '%"';
}
if ($arrReq['sel_rech_epreuve'] > 0) {
$strWhere .= ' AND p.epr_id = ' . intval($arrReq['sel_rech_epreuve']) . ' AND p.epr_id = e.epr_id';
}
if ($arrReq['chk_bib']) {
$strWhere .= " AND TRIM(p.no_bib) = ''";
}
if ($arrReq['chk_cancelled']) {
$strWhere .= ' AND e.is_cancelled = 1';
} else {
$strWhere .= ' AND e.is_cancelled = 0 AND e.pec_actif = 1';
}
return $strWhere;
}
function fxInscrMobileFetchRows($intEveId, $arrReq) {
global $objDatabase;
$strWhere = fxInscrMobileBuildWhere($intEveId, $arrReq);
$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, p.rol_id,'
. ' e.no_commande, e.no_panier, e.no_equipe, e.pec_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'
. ' ORDER BY p.par_nom, p.par_prenom';
return $objDatabase->fxGetResults($sql);
}
function fxInscrMobileFetchRowByPec($intPecId, $intEveId) {
global $objDatabase;
$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, p.rol_id,'
. ' e.no_commande, e.no_panier, e.no_equipe, e.pec_equipe'
. ' FROM resultats_epreuves_commandees e, resultats_participants p'
. ' WHERE e.eve_id = ' . intval($intEveId)
. ' AND e.pec_id_original = ' . intval($intPecId)
. ' AND p.pec_id = e.pec_id_original'
. ' LIMIT 1';
return $objDatabase->fxGetRow($sql);
}
function fxInscrMobileEpreuveLabel($intEprId, $strLangue) {
$tab = fxGetEpreuve($intEprId);
if ($tab === null) {
return '';
}
$str = '';
if (trim($tab['epr_categorie_' . $strLangue]) !== '') {
$str .= $tab['epr_categorie_' . $strLangue] . ' — ';
}
$str .= $tab['epr_type_' . $strLangue];
if (trim($tab['epr_nom_' . $strLangue]) !== '') {
$str .= ' — ' . $tab['epr_nom_' . $strLangue];
}
return fxUnescape($str);
}
function fxInscrMobileBibDisplay($arrRow) {
if (intval($arrRow['pec_equipe']) === 1) {
return fxShowBibNumber($arrRow['no_equipe'], $arrRow['epr_id'], 'equipe');
}
return fxShowBibNumber($arrRow['no_bib'], $arrRow['epr_id'], 'participant');
}
function fxInscrMobileRenderKvListOpen() {
echo '<div class="inscr-mobile-kv-list">';
}
function fxInscrMobileRenderKvListClose() {
echo '</div>';
}
function fxInscrMobileRenderKvRow($strLabel, $strValue, $blnHtml = false, $strExtraClass = '') {
if (!$blnHtml && trim((string)$strValue) === '') {
return;
}
$strClass = 'inscr-mobile-kv-row';
if ($strExtraClass !== '') {
$strClass .= ' ' . $strExtraClass;
}
echo '<div class="' . fxInscrMobileEsc($strClass) . '">';
echo '<div class="inscr-mobile-kv-row__label">' . fxInscrMobileEsc($strLabel) . '</div>';
echo '<div class="inscr-mobile-kv-row__value">';
if ($blnHtml) {
echo $strValue;
} else {
echo fxInscrMobileEsc($strValue);
}
echo '</div></div>';
}
function fxInscrMobileFetchFicheProfile($arrRow, $strLangue) {
global $objDatabase;
$intParId = (int)$arrRow['par_id'];
$intPecId = (int)$arrRow['pec_id_original'];
$intEveId = (int)$arrRow['eve_id'];
$strLangCol = ($strLangue === 'en') ? 'en' : 'fr';
$tabProfile = $objDatabase->fxGetRow(
'SELECT p.par_courriel, p.par_naissance, p.par_sexe, p.par_nom, p.par_prenom, p.par_id_original,'
. ' r.rol_nom_' . $strLangCol . ' AS rol_nom'
. ' FROM resultats_participants p'
. ' LEFT JOIN inscriptions_roles r ON r.rol_id = p.rol_id'
. ' WHERE p.par_id = ' . $intParId
. ' LIMIT 1'
);
if ($tabProfile === null) {
return array(
'role' => '',
'name' => '',
'email' => '',
'birth_gender' => '',
'questions' => array(),
);
}
$strRole = trim((string)$tabProfile['rol_nom']);
$strName = trim(fxUnescape($tabProfile['par_nom']) . ', ' . fxUnescape($tabProfile['par_prenom']), ', ');
$strEmail = trim((string)$tabProfile['par_courriel']);
$strBirthGender = '';
$strNaissance = trim((string)$tabProfile['par_naissance']);
if ($strNaissance !== '' && $strNaissance !== '0000-00-00') {
$strBirthGender = fxShowDate($strNaissance, $strLangue)
. ' - '
. fxGetGender($tabProfile['par_sexe'], $strLangue);
}
$intParIdOriginal = (int)$tabProfile['par_id_original'];
$sqlQuestions = 'SELECT rq.que_choix_' . $strLangCol . ' AS que_choix,'
. ' iq.que_cart_label_' . $strLangCol . ' AS que_label,'
. ' rq.que_question_' . $strLangCol . ' AS que_question,'
. ' iq.que_tri, iq.que_id'
. ' FROM resultats_questions rq'
. ' INNER JOIN inscriptions_questions iq ON iq.que_id = rq.que_id'
. ' WHERE iq.que_cart_show = 1'
. ' AND iq.eve_id = ' . $intEveId
. ' AND rq.pec_id = ' . $intPecId
. ' AND (rq.par_id = ' . $intParId . ' OR rq.par_id = ' . $intParIdOriginal . ')'
. ' AND rq.que_actif = 1'
. " AND TRIM(COALESCE(rq.que_choix_" . $strLangCol . ", '')) <> ''"
. ' ORDER BY iq.que_tri, iq.que_id';
$tabQuestionsRaw = $objDatabase->fxGetResults($sqlQuestions);
$tabQuestions = array();
if ($tabQuestionsRaw !== null) {
for ($i = 1; $i <= count($tabQuestionsRaw); $i++) {
$tabQ = $tabQuestionsRaw[$i];
$strLabel = trim(fxUnescape($tabQ['que_label']));
if ($strLabel === '') {
$strLabel = trim(fxUnescape($tabQ['que_question']));
}
$strValue = trim(fxUnescape($tabQ['que_choix']));
if ($strLabel === '' || $strValue === '') {
continue;
}
$tabQuestions[] = array(
'label' => $strLabel,
'value' => $strValue,
);
}
}
return array(
'role' => $strRole,
'name' => $strName,
'email' => $strEmail,
'birth_gender' => $strBirthGender,
'questions' => $tabQuestions,
);
}
function fxInscrMobileRenderFicheProfileKvRows($arrRow, $strLangue) {
$tabProfile = fxInscrMobileFetchFicheProfile($arrRow, $strLangue);
$blnFirstProfile = true;
if ($tabProfile['role'] !== '' && $tabProfile['name'] !== '') {
fxInscrMobileRenderKvRow(
$tabProfile['role'],
$tabProfile['name'],
false,
$blnFirstProfile ? 'inscr-mobile-kv-row--profile' : ''
);
$blnFirstProfile = false;
}
if ($tabProfile['email'] !== '') {
fxInscrMobileRenderKvRow(
fxInscrMobileT('inscr_mobile_email'),
$tabProfile['email'],
false,
$blnFirstProfile ? 'inscr-mobile-kv-row--profile' : ''
);
$blnFirstProfile = false;
}
if ($tabProfile['birth_gender'] !== '') {
fxInscrMobileRenderKvRow(
fxInscrMobileT('inscr_mobile_birthdate'),
$tabProfile['birth_gender'],
false,
$blnFirstProfile ? 'inscr-mobile-kv-row--profile' : ''
);
$blnFirstProfile = false;
}
foreach ($tabProfile['questions'] as $tabQuestion) {
fxInscrMobileRenderKvRow(
$tabQuestion['label'],
$tabQuestion['value'],
false,
$blnFirstProfile ? 'inscr-mobile-kv-row--profile' : ''
);
$blnFirstProfile = false;
}
}
/** Code statut course par défaut (Confirmé). */
function fxInscrMobileParStatutCourseDefault() {
return 'CONF';
}
function fxInscrMobileResolveParStatutCourse($strCurrent) {
$strCurrent = trim((string)$strCurrent);
return $strCurrent !== '' ? $strCurrent : fxInscrMobileParStatutCourseDefault();
}
/** Options statut course depuis info (info_description = opt). */
function fxInscrMobileGetStatutCourseOptions($strLangue) {
global $objDatabase;
static $tabCache = array();
if (isset($tabCache[$strLangue])) {
return $tabCache[$strLangue];
}
$sql = "SELECT info_texte, info_option2 FROM info"
. " WHERE info_actif = 1 AND info_clef = 'inscr_statut_course'"
. " AND info_langue = '" . $objDatabase->fxEscape($strLangue) . "'"
. " AND info_description = 'opt'"
. " ORDER BY info_trie";
$tabRows = $objDatabase->fxGetResults($sql);
$tabCache[$strLangue] = ($tabRows !== null) ? $tabRows : array();
return $tabCache[$strLangue];
}
function fxInscrMobileRenderStatutField($intParId, $strCurrent, $intEveId, $strLangue) {
$tabOptions = fxInscrMobileGetStatutCourseOptions($strLangue);
if (count($tabOptions) === 0) {
echo '<div class="inscr-mobile-muted">' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_statut_label')) . '</div>';
return;
}
$strCurrent = fxInscrMobileResolveParStatutCourse($strCurrent);
$strSelectId = 'inscr_statut_' . (int)$intParId;
echo '<select class="form-control rounded-0 inscr-mobile-statut-select" id="' . fxInscrMobileEsc($strSelectId) . '"'
. ' data-par_id="' . (int)$intParId . '"'
. ' data-eve_id="' . rawurlencode(base64_encode((string)$intEveId)) . '">';
foreach ($tabOptions as $arrOpt) {
$strCode = trim((string)$arrOpt['info_option2']);
$strLabel = trim((string)$arrOpt['info_texte']);
if ($strCode === '') {
continue;
}
echo '<option value="' . fxInscrMobileEsc($strCode) . '"'
. ($strCurrent === $strCode ? ' selected' : '') . '>'
. fxInscrMobileEsc($strLabel) . '</option>';
}
echo '</select>';
}
/** Paramètres GET pour liens (sans double-encodage). */
function fxInscrMobileQueryParams($intEveId, $arrReq, $arrExtra = array()) {
$tab = array(
'promoteur_eve_id' => base64_encode((string)$intEveId),
);
if ($arrReq['rech_prenom'] !== '') {
$tab['rech_prenom'] = $arrReq['rech_prenom'];
}
if ($arrReq['rech_nom'] !== '') {
$tab['rech_nom'] = $arrReq['rech_nom'];
}
if ($arrReq['rech_no_commande'] !== '') {
$tab['rech_no_commande'] = $arrReq['rech_no_commande'];
}
if ($arrReq['rech_nom_equipe'] !== '') {
$tab['rech_nom_equipe'] = $arrReq['rech_nom_equipe'];
}
if ($arrReq['chk_bib']) {
$tab['chk_bib'] = 1;
}
if ($arrReq['chk_cancelled']) {
$tab['chk_cancelled'] = 1;
}
if ($arrReq['sel_rech_epreuve'] > 0) {
$tab['sel_rech_epreuve'] = base64_encode((string)$arrReq['sel_rech_epreuve']);
}
if (!empty($_GET['lng'])) {
$tab['lng'] = $_GET['lng'];
}
if (!empty($arrReq['pg']) && (int)$arrReq['pg'] > 1) {
$tab['pg'] = (int)$arrReq['pg'];
}
foreach ($arrExtra as $strKey => $mixVal) {
if ($mixVal === null || $mixVal === '' || ($strKey === 'pec_id' && (int)$mixVal === 0)) {
unset($tab[$strKey]);
} else {
$tab[$strKey] = $mixVal;
}
}
return $tab;
}
function fxInscrMobileBuildUrl($strBaseUrl, $intEveId, $arrReq, $arrExtra = array()) {
$tab = fxInscrMobileQueryParams($intEveId, $arrReq, $arrExtra);
$strQs = http_build_query($tab, '', '&');
return $strBaseUrl . ($strQs !== '' ? '?' . $strQs : '');
}
function fxInscrMobilePaginationUrl($strBaseUrl, $intEveId, $arrReq) {
$tab = fxInscrMobileQueryParams($intEveId, $arrReq, array('pec_id' => null));
unset($tab['pg'], $tab['pec_id']);
$strQs = http_build_query($tab, '', '&amp;');
return $strBaseUrl . ($strQs !== '' ? '?' . $strQs : '?promoteur_eve_id=' . rawurlencode(base64_encode((string)$intEveId)));
}
function fxInscrMobileRenderPagination($strBaseUrl, $intEveId, $arrReq, $intTotal, $intPerPage, $intPage) {
if ($intTotal <= $intPerPage) {
return '';
}
return '<div class="inscr-mobile-pager">'
. fxGetPagination(
fxInscrMobilePaginationUrl($strBaseUrl, $intEveId, $arrReq),
$intTotal,
$intPerPage,
$intPage
)
. '</div>';
}
function fxInscrMobileExtractQrToken($strRaw) {
$strRaw = trim((string)$strRaw);
if ($strRaw === '') {
return '';
}
if (preg_match('/[?&]t=([^&\s#]+)/', $strRaw, $tabMatch)) {
return urldecode($tabMatch[1]);
}
if (preg_match('/^https?:\/\//i', $strRaw)) {
$tabParts = parse_url($strRaw);
if (!empty($tabParts['query'])) {
parse_str($tabParts['query'], $tabQuery);
if (!empty($tabQuery['t'])) {
return trim((string)$tabQuery['t']);
}
}
}
if (preg_match('/^[a-zA-Z0-9_-]{6,64}$/', $strRaw)) {
return $strRaw;
}
return '';
}
function fxInscrMobileResolveQrScan($strRaw, $intEveId, $strLangue) {
global $objDatabase;
$strToken = fxInscrMobileExtractQrToken($strRaw);
if ($strToken === '') {
return array('state' => 'error', 'message' => fxInscrMobileT('inscr_mobile_qr_invalid'));
}
$tabToken = $objDatabase->fxGetRow(
'SELECT qr_public_id, pec_id_original, eve_id'
. ' FROM qr_tokens'
. " WHERE qr_public_id = '" . $objDatabase->fxEscape($strToken) . "'"
. ' LIMIT 1'
);
if ($tabToken === null) {
return array('state' => 'error', 'message' => fxInscrMobileT('inscr_mobile_qr_invalid'));
}
$intPecId = (int)$tabToken['pec_id_original'];
if ($intPecId <= 0) {
return array('state' => 'error', 'message' => fxInscrMobileT('inscr_mobile_qr_invalid'));
}
$tabPec = $objDatabase->fxGetRow(
'SELECT ec.pec_id_original'
. ' FROM resultats_epreuves_commandees ec'
. ' WHERE ec.pec_id_original = ' . $intPecId
. ' AND ec.eve_id = ' . intval($intEveId)
. ' AND ec.pec_actif = 1'
. ' LIMIT 1'
);
if ($tabPec !== null) {
$arrRow = fxInscrMobileFetchRowByPec($intPecId, $intEveId);
if ($arrRow === null) {
return array('state' => 'error', 'message' => fxInscrMobileT('inscr_mobile_qr_not_found'));
}
return array(
'state' => 'success',
'pec_id' => $intPecId,
);
}
$intQrEveId = (int)$tabToken['eve_id'];
if ($intQrEveId <= 0) {
$tabOther = $objDatabase->fxGetRow(
'SELECT ec.eve_id FROM resultats_epreuves_commandees ec'
. ' WHERE ec.pec_id_original = ' . $intPecId
. ' AND ec.pec_actif = 1'
. ' ORDER BY ec.pec_id_original DESC LIMIT 1'
);
if ($tabOther !== null) {
$intQrEveId = (int)$tabOther['eve_id'];
}
}
$strEveNom = '';
if ($intQrEveId > 0) {
$arrEv = fxGetEvenementsId($intQrEveId);
if (!empty($arrEv)) {
$strEveNom = fxUnescape($arrEv['eve_nom_' . $strLangue]);
}
}
if ($strEveNom === '') {
$strEveNom = '#' . $intQrEveId;
}
return array(
'state' => 'wrong_event',
'message' => str_replace('%s', $strEveNom, fxInscrMobileT('inscr_mobile_qr_wrong_event')),
'eve_nom' => $strEveNom,
);
}
function fxInscrMobileRenderEventPicker($tabEveIds, $strLangue, $strBaseUrl) {
global $objDatabase;
$strTitle = ($strLangue === 'fr') ? 'Choisir un événement' : 'Choose an event';
echo '<div id="module-inscr-mobile" class="inscr-mobile-shell">';
fxInscrMobileRenderPageHead($strTitle);
echo '<div class="inscr-mobile-event-list">';
foreach ($tabEveIds as $intEveId) {
$qry = 'SELECT e.* FROM inscriptions_evenements e WHERE e.eve_actif = 1 AND e.eve_id = ' . intval($intEveId);
$tabEv = $objDatabase->fxGetRow($qry);
if ($tabEv === null) {
continue;
}
$strUrl = fxInscrMobileBuildUrl($strBaseUrl, $intEveId, fxInscrMobileParseRequest(), array());
echo '<a class="inscr-mobile-event-item" href="' . fxInscrMobileEsc($strUrl) . '">';
echo '<span class="inscr-mobile-event-item__name">' . fxInscrMobileEsc(fxUnescape($tabEv['eve_nom_' . $strLangue])) . '</span>';
echo '<i class="fa fa-chevron-right" aria-hidden="true"></i>';
echo '</a>';
}
echo '</div></div>';
}
function fxInscrMobileRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq) {
global $vDomaine;
$arrEvenement = fxGetEvenementsId($intEveId);
$strEveNom = fxUnescape($arrEvenement['eve_nom_' . $strLangue]);
$intFilterCount = fxInscrMobileFilterActiveCount($arrReq);
$strBackUrl = fxInscrMobileIsEntry()
? $strBaseUrl
: ($vDomaine . ($strLangue === 'fr' ? '/compte/inc_tableau_promoteur' : '/account/inc_tableau_promoteur')
. '?promoteur_eve_id=' . rawurlencode(base64_encode((string)$intEveId)));
echo '<div id="module-inscr-mobile" class="inscr-mobile-shell" data-inscr-mobile="1">';
fxInscrMobileRenderNavBack($strBackUrl, afficheTexte('promoteur_back', 0));
fxInscrMobileRenderPageHead(fxInscrMobileT('inscr_mobile_title'), $strEveNom);
$strQrAjaxUrl = $vDomaine . '/ajax_inscr_mobile_qr.php';
echo '<details class="inscr-mobile-panel inscr-mobile-panel--qr" id="inscr-mobile-qr-panel"';
echo ' data-qr-resolve-url="' . fxInscrMobileEsc($strQrAjaxUrl) . '"';
echo ' data-qr-eve-id="' . fxInscrMobileEsc(base64_encode((string)$intEveId)) . '"';
echo ' data-qr-msg-invalid="' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_qr_invalid')) . '"';
echo ' data-qr-msg-wrong="' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_qr_wrong_event')) . '"';
echo ' data-qr-msg-camera="' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_qr_camera_error')) . '"';
echo ' data-qr-lang="' . fxInscrMobileEsc($strLangue) . '">';
echo '<summary class="inscr-mobile-panel__head">';
fxInscrMobileRenderPanelSummary(fxInscrMobileT('inscr_mobile_qr_title'), 'fa-qrcode');
echo '</summary>';
echo '<div class="inscr-mobile-panel__body">';
echo '<p class="inscr-mobile-qr-hint text-muted small mb-2">' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_qr_hint')) . '</p>';
echo '<div id="inscr-mobile-qr-feedback" class="alert d-none mb-2" role="alert"></div>';
echo '<div id="inscr-mobile-qr-reader-wrap" class="inscr-mobile-qr-reader-wrap">';
echo '<div id="inscr-mobile-qr-reader"></div>';
echo '</div></div></details>';
// Recherche (repliable — fermée par défaut pour montrer la liste d'abord)
echo '<details class="inscr-mobile-panel">';
echo '<summary class="inscr-mobile-panel__head">';
fxInscrMobileRenderPanelSummary(fxInscrMobileT('txt_recherche'), 'fa-search');
echo '</summary>';
echo '<div class="inscr-mobile-panel__body">';
echo '<form action="' . fxInscrMobileEsc($strBaseUrl) . '" method="get" class="inscr-mobile-form">';
echo '<input type="hidden" name="promoteur_eve_id" value="' . fxInscrMobileEsc(base64_encode((string)$intEveId)) . '">';
$arrFields = array(
'rech_prenom' => 'rech_prenom',
'rech_nom' => 'rech_nom',
'rech_no_commande' => 'rech_no_commande',
'rech_nom_equipe' => 'rech_equipe',
);
foreach ($arrFields as $strKey => $strLbl) {
echo '<label class="inscr-mobile-label" for="' . $strKey . '">' . fxInscrMobileEsc(fxInscrMobileT($strLbl)) . '</label>';
echo '<input class="form-control form-control-sm rounded-0" type="text" id="' . $strKey . '" name="' . $strKey . '" value="' . fxInscrMobileEsc($arrReq[$strKey]) . '">';
}
if ($arrReq['sel_rech_epreuve'] > 0) {
echo '<input type="hidden" name="sel_rech_epreuve" value="' . fxInscrMobileEsc(base64_encode((string)$arrReq['sel_rech_epreuve'])) . '">';
}
if ($arrReq['chk_bib']) {
echo '<input type="hidden" name="chk_bib" value="1">';
}
if ($arrReq['chk_cancelled']) {
echo '<input type="hidden" name="chk_cancelled" value="1">';
}
echo '<button class="btn btn-primary btn-sm rounded-0 btn-block mt-2" type="submit" name="btn_recherche" value="1">' . fxInscrMobileEsc(fxInscrMobileT('txt_recherche')) . '</button>';
echo '</form></div></details>';
// Filtres
global $objDatabase;
$tabEpreuves = $objDatabase->fxGetResults(
'SELECT * FROM inscriptions_epreuves e WHERE e.eve_id = ' . intval($intEveId) . ' AND epr_actif = 1 ORDER BY epr_id'
);
$strFilterLabel = fxInscrMobileT('inscr_mobile_filters');
if ($intFilterCount > 0) {
$strFilterLabel .= ' (' . $intFilterCount . ')';
}
echo '<details class="inscr-mobile-panel">';
echo '<summary class="inscr-mobile-panel__head">';
fxInscrMobileRenderPanelSummary($strFilterLabel, 'fa-filter');
echo '</summary>';
echo '<div class="inscr-mobile-panel__body">';
echo '<form action="' . fxInscrMobileEsc($strBaseUrl) . '" method="get" class="inscr-mobile-form">';
echo '<input type="hidden" name="promoteur_eve_id" value="' . fxInscrMobileEsc(base64_encode((string)$intEveId)) . '">';
foreach (array('rech_prenom', 'rech_nom', 'rech_no_commande', 'rech_nom_equipe') as $strKey) {
if ($arrReq[$strKey] !== '') {
echo '<input type="hidden" name="' . $strKey . '" value="' . fxInscrMobileEsc($arrReq[$strKey]) . '">';
}
}
echo '<label class="inscr-mobile-label" for="sel_rech_epreuve">' . fxInscrMobileEsc(fxInscrMobileT('sel_rech_epreuve')) . '</label>';
echo '<select class="form-control form-control-sm rounded-0" id="sel_rech_epreuve" name="sel_rech_epreuve">';
echo '<option value="">—</option>';
for ($i = 1; $i <= count($tabEpreuves); $i++) {
$strOpt = fxInscrMobileEpreuveLabel($tabEpreuves[$i]['epr_id'], $strLangue);
$strSel = ($arrReq['sel_rech_epreuve'] == $tabEpreuves[$i]['epr_id']) ? ' selected' : '';
$strVal = base64_encode((string)$tabEpreuves[$i]['epr_id']);
echo '<option value="' . fxInscrMobileEsc($strVal) . '"' . $strSel . '>' . fxInscrMobileEsc($strOpt) . '</option>';
}
echo '</select>';
echo '<label class="inscr-mobile-check mt-2"><input type="checkbox" name="chk_bib" value="1"' . ($arrReq['chk_bib'] ? ' checked' : '') . '> ' . fxInscrMobileEsc(fxInscrMobileT('chk_bib')) . '</label>';
echo '<label class="inscr-mobile-check"><input type="checkbox" name="chk_cancelled" value="1"' . ($arrReq['chk_cancelled'] ? ' checked' : '') . '> ' . fxInscrMobileEsc(fxInscrMobileT('chk_cancelled')) . '</label>';
echo '<div class="inscr-mobile-form-actions mt-2">';
$strResetUrl = fxInscrMobileBuildUrl($strBaseUrl, $intEveId, array(
'rech_prenom' => '', 'rech_nom' => '', 'rech_no_commande' => '', 'rech_nom_equipe' => '',
'chk_bib' => 0, 'chk_cancelled' => 0, 'sel_rech_epreuve' => 0, 'pg' => 1, 'pec_id' => 0,
), array('pg' => 1));
echo '<a class="btn btn-secondary btn-sm rounded-0" href="' . fxInscrMobileEsc($strResetUrl) . '">' . ($strLangue === 'fr' ? 'Réinitialiser' : 'Reset') . '</a>';
echo '<button class="btn btn-primary btn-sm rounded-0" type="submit" name="apply_filters" value="1">' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_apply_filters')) . '</button>';
echo '</div></form></div></details>';
// Liste complète dès l'ouverture
$tabRows = fxInscrMobileFetchRows($intEveId, $arrReq);
$intNbItemsParPage = 50;
$intNbTotal = ($tabRows !== null) ? count($tabRows) : 0;
$intPage = 1;
$intStart = 1;
$intEnd = $intNbItemsParPage;
if (!empty($_GET['pg'])) {
$intPage = max(1, intval($_GET['pg']));
}
if (intval($intPage) > 1) {
$intStart = ($intPage - 1) * $intNbItemsParPage + 1;
$intEnd = $intStart + $intNbItemsParPage - 1;
}
if ($intEnd > $intNbTotal) {
$intEnd = $intNbTotal;
}
echo '<div id="inscr-mobile-list" class="inscr-mobile-list-anchor">';
echo '<div class="inscr-mobile-list-head">';
if ($strLangue === 'fr') {
echo '<span>' . (int)$intNbTotal . ' inscription' . ($intNbTotal > 1 ? 's' : '') . '</span>';
} else {
echo '<span>' . (int)$intNbTotal . ' registration' . ($intNbTotal !== 1 ? 's' : '') . '</span>';
}
if ($intNbTotal > $intNbItemsParPage) {
$intNbPages = (int)ceil($intNbTotal / $intNbItemsParPage);
echo '<span class="inscr-mobile-list-head__pg">' . ($strLangue === 'fr' ? 'Page ' : 'Page ') . $intPage . ' / ' . $intNbPages . '</span>';
}
echo '</div>';
if ($intNbTotal > 0) {
echo '<div class="inscr-mobile-list">';
for ($j = $intStart; $j <= $intEnd; $j++) {
$row = $tabRows[$j];
$strFicheUrl = fxInscrMobileBuildUrl($strBaseUrl, $intEveId, $arrReq, array(
'pec_id' => (int)$row['pec_id_original'],
'pg' => $intPage,
));
$strBib = fxInscrMobileBibDisplay($row);
$strName = fxUnescape($row['par_nom']) . ', ' . fxUnescape($row['par_prenom']);
$strRace = fxInscrMobileEpreuveLabel($row['epr_id'], $strLangue);
$strCardClass = 'inscr-mobile-list-item';
if ($row['is_cancelled'] == '1') {
$strCardClass .= ' inscr-mobile-list-item--cancelled';
}
echo '<a class="' . $strCardClass . '" href="' . fxInscrMobileEsc($strFicheUrl) . '">';
echo '<span class="inscr-mobile-list-item__name">' . fxInscrMobileEsc($strName) . '</span>';
echo '<span class="inscr-mobile-list-item__race">' . fxInscrMobileEsc($strRace) . '</span>';
echo '<span class="inscr-mobile-list-item__order">' . fxInscrMobileEsc($row['no_commande']) . '</span>';
echo '<span class="inscr-mobile-list-item__bib">';
echo trim($strBib) !== '' ? fxInscrMobileEsc($strBib) : '—';
echo '</span>';
echo '<span class="inscr-mobile-list-item__check">';
if ($row['no_bib_remis'] == 1) {
echo '<span class="inscr-mobile-badge inscr-mobile-badge--ok">' . fxInscrMobileEsc(fxInscrMobileT('promoteur_bib_enregistre')) . '</span>';
}
echo '</span>';
echo '<i class="fa fa-chevron-right inscr-mobile-list-item__arrow" aria-hidden="true"></i>';
echo '</a>';
}
echo '</div>';
echo fxInscrMobileRenderPagination($strBaseUrl, $intEveId, $arrReq, $intNbTotal, $intNbItemsParPage, $intPage);
} else {
echo '<div class="alert alert-light border inscr-mobile-empty">' . fxInscrMobileEsc(fxInscrMobileT('txt_recherche_no_result')) . '</div>';
}
echo '</div>';
}
function fxInscrMobileRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, $arrRow) {
global $vDomaine;
$strListUrl = fxInscrMobileBuildUrl($strBaseUrl, $intEveId, $arrReq, array('pec_id' => null, 'pg' => $arrReq['pg']));
$strEveCode = fxGetEvenementsUrl($arrRow['eve_id']);
$strBib = fxInscrMobileBibDisplay($arrRow);
$intParId = $arrRow['par_id'];
$blnCancelled = ($arrRow['is_cancelled'] == '1');
$blnEquipe = (intval($arrRow['pec_equipe']) === 1);
$strBibAction = $blnEquipe ? 'no_equipe' : 'no_bib';
$strBibInputId = $blnEquipe ? 'txt_no_bib_e' : 'txt_no_bib_p';
if ($arrRow['no_bib_remis'] == 1) {
$strRemisClass = 'btn-success';
$strRemisIcon = '<i class="fa fa-check" aria-hidden="true"></i>';
$intRemisVal = 0;
} else {
$strRemisClass = 'btn-primary';
$strRemisIcon = '<i class="fa fa-sharp fa-regular fa-square fa-2xs" aria-hidden="true"></i>';
$intRemisVal = 1;
}
echo '<div id="module-inscr-mobile" class="inscr-mobile-shell inscr-mobile-fiche" data-inscr-mobile="1">';
fxInscrMobileRenderNavBack($strListUrl, fxInscrMobileT('inscr_mobile_back_list'));
echo '<div class="inscr-mobile-fiche-head">';
echo '<h1 class="inscr-mobile-page-title">' . fxInscrMobileEsc(fxUnescape($arrRow['par_nom']) . ', ' . fxUnescape($arrRow['par_prenom'])) . '</h1>';
echo '</div>';
$strDetailsType = $blnEquipe && fxIsParEquipe($arrRow['pec_id_original'], $arrRow['epr_id'])
? fxInscrMobileT('promoteur_bib_show_teamates')
: fxInscrMobileT('epreuve_individuelle');
echo '<div class="inscr-mobile-fiche-section inscr-mobile-fiche-section--details">';
fxInscrMobileRenderSectionTitle(fxInscrMobileT('inscr_mobile_details'), 'fa-info-circle');
fxInscrMobileRenderKvListOpen();
fxInscrMobileRenderKvRow(fxInscrMobileT('inscr_mobile_epreuve'), fxInscrMobileEpreuveLabel($arrRow['epr_id'], $strLangue));
fxInscrMobileRenderKvRow(fxInscrMobileT('inscr_mobile_type'), $strDetailsType);
fxInscrMobileRenderKvRow(fxInscrMobileT('inscr_mobile_modified'), fxCheckMAJ($arrRow['pec_id_original'], $intParId, $strLangue), true);
fxInscrMobileRenderFicheProfileKvRows($arrRow, $strLangue);
fxInscrMobileRenderKvListClose();
echo '</div>';
$strStyleEdit = $strStyleCancel = '';
$strStyleRetablir = ' d-none';
if ($blnCancelled) {
$strStyleEdit = $strStyleCancel = ' d-none';
$strStyleRetablir = '';
}
$strRenvoi = ($strLangue === 'fr') ? 'RENVOI' : 'RESEND';
echo '<div class="inscr-mobile-fiche-section inscr-mobile-fiche-section--gestion">';
fxInscrMobileRenderSectionTitle(fxInscrMobileT('inscr_mobile_section_management'), 'fa-cog');
echo '<div class="inscr-mobile-gestion-actions">';
echo '<a class="btn btn-primary btn-sm rounded-pill" href="' . $vDomaine . '/facture.php?no_panier=' . rawurlencode($arrRow['no_panier']) . '&amp;lang=' . $strLangue . '" target="_blank">' . fxInscrMobileEsc($arrRow['no_commande']) . '</a>';
echo '<button class="btn btn-primary btn-sm rounded-0 link_confirmation" type="button"'
. ' data-no_panier="' . fxInscrMobileEsc($arrRow['no_panier']) . '"'
. ' data-no_commande="' . fxInscrMobileEsc($arrRow['no_commande']) . '"'
. ' data-lng="' . $strLangue . '">' . fxInscrMobileEsc($strRenvoi) . '</button>';
echo '<button class="btn btn-primary btn-sm rounded-0 btn_edit_event_promo' . $strStyleEdit . '" type="button"'
. ' id="modifier_fiche" data-eve_code="' . fxInscrMobileEsc($strEveCode) . '"'
. ' data-epr_id="' . (int)$arrRow['epr_id'] . '" data-eve_id="' . (int)$arrRow['eve_id'] . '"'
. ' value="' . (int)$arrRow['pec_id_original'] . '">' . fxInscrMobileEsc(fxInscrMobileT('btn_modifierinscriptions')) . '</button>';
echo '<button class="btn btn-warning btn-sm rounded-0" type="button" data-inscr-field="remboursement">' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_remboursement')) . '</button>';
echo '<button class="btn btn-secondary btn-sm rounded-0 btn_cancel_event_promo' . $strStyleCancel . '" type="button"'
. ' id="annuler_fiche" data-eve_code="' . fxInscrMobileEsc($strEveCode) . '"'
. ' data-epr_id="' . (int)$arrRow['epr_id'] . '" data-eve_id="' . (int)$arrRow['eve_id'] . '"'
. ' value="' . (int)$arrRow['pec_id_original'] . '">' . fxInscrMobileEsc(fxInscrMobileT('btn_annulerinscriptions')) . '</button>';
echo '<button class="btn btn-secondary btn-sm rounded-0 btn_retablir_event_promo' . $strStyleRetablir . '" type="button"'
. ' id="retablir_fiche" data-eve_code="' . fxInscrMobileEsc($strEveCode) . '"'
. ' data-epr_id="' . (int)$arrRow['epr_id'] . '" data-eve_id="' . (int)$arrRow['eve_id'] . '"'
. ' value="' . (int)$arrRow['pec_id_original'] . '">' . fxInscrMobileEsc(fxInscrMobileT('btn_retablirinscriptions')) . '</button>';
echo '</div></div>';
echo '<div class="inscr-mobile-fiche-section inscr-mobile-fiche-section--editable">';
fxInscrMobileRenderSectionTitle(fxInscrMobileT('inscr_mobile_section_editable'), 'fa-pencil-square-o');
echo '<div class="inscr-mobile-field-block" data-inscr-field="bib">';
echo '<div class="inscr-mobile-field-block__label">' . fxInscrMobileEsc(fxInscrMobileT('promoteur_bib_number')) . '</div>';
echo '<div class="inscr-mobile-bib-row">';
echo '<input class="form-control rounded-0" type="text" id="' . $strBibInputId . $intParId . '" value="' . fxInscrMobileEsc($strBib) . '">';
echo '<button class="btn btn-primary rounded-0 btn_bib" type="button" data-action="' . $strBibAction . '"'
. ' data-eve_id="' . rawurlencode(base64_encode((string)$arrRow['eve_id'])) . '"'
. ' data-epr_id="' . (int)$arrRow['epr_id'] . '"'
. ' data-par_id="' . (int)$intParId . '"'
. ' data-pec_id="' . (int)$arrRow['pec_id_original'] . '">OK</button>';
echo '</div></div>';
echo '<div class="inscr-mobile-field-block inscr-mobile-field-block--statut" data-inscr-field="statut">';
echo '<div class="inscr-mobile-field-block__label">' . fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_statut_label')) . '</div>';
fxInscrMobileRenderStatutField($intParId, $arrRow['par_statut_course'] ?? '', $arrRow['eve_id'], $strLangue);
echo '</div>';
$strRemisDate = trim((string)$arrRow['no_bib_remis_date']);
if ($strRemisDate === '0000-00-00 00:00:00') {
$strRemisDate = '';
}
$strRemisPar = trim((string)$arrRow['no_bib_remis_par']);
echo '<div class="inscr-mobile-field-block" data-inscr-field="remis">';
echo '<div class="inscr-mobile-remis-row">';
echo '<div class="inscr-mobile-remis-row__left">';
echo '<div class="inscr-mobile-field-block__label inscr-mobile-field-block__label--inline">' . fxInscrMobileEsc(fxInscrMobileT('promoteur_bib_enregistre')) . '</div>';
echo '<span id="' . (int)$intParId . '">';
echo '<a class="btn btn-sm rounded-0 btn_remis ' . $strRemisClass . '" href="#" data-action="remis"'
. ' data-table="' . rawurlencode(base64_encode('resultats_participants')) . '"'
. ' data-field="no_bib_remis" data-key="par_id" data-valeur="' . $intRemisVal . '"'
. ' data-id="' . (int)$intParId . '">' . $strRemisIcon . '</a>';
echo '</span>';
echo '</div>';
echo '<div class="inscr-mobile-remis-row__meta inscr-mobile-muted">';
echo '<span id="date_' . (int)$intParId . '">' . fxInscrMobileEsc($strRemisDate) . '</span>';
if ($strRemisDate !== '' && $strRemisPar !== '') {
echo '<span class="inscr-mobile-remis-row__sep"> — </span>';
}
echo '<span id="par_' . (int)$intParId . '">' . fxInscrMobileEsc($strRemisPar) . '</span>';
echo '</div></div></div>';
echo '</div>';
echo '</div>';
}
function fxInscrMobileRun($intEveId, $strLangue) {
$strBaseUrl = fxInscrMobileBaseUrl($strLangue);
$arrReq = fxInscrMobileParseRequest();
if ($arrReq['pec_id'] > 0) {
$arrRow = fxInscrMobileFetchRowByPec($arrReq['pec_id'], $intEveId);
if ($arrRow === null) {
echo '<div class="alert alert-danger">' . fxInscrMobileEsc(fxInscrMobileT('txt_recherche_no_result')) . '</div>';
echo '<a class="btn btn-primary rounded-0" href="' . fxInscrMobileEsc(fxInscrMobileBuildUrl($strBaseUrl, $intEveId, $arrReq, array('pec_id' => null))) . '">';
echo fxInscrMobileEsc(fxInscrMobileT('inscr_mobile_back_list')) . '</a>';
return;
}
fxInscrMobileRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, $arrRow);
return;
}
fxInscrMobileRenderList($intEveId, $strLangue, $strBaseUrl, $arrReq);
}