This commit enhances the `fxPromoteurHubGetEpreuveStats` function to improve the aggregation and presentation of event statistics, including sold tickets and check-ins. Additionally, it refines the CSS styles for the promoteur hub, ensuring a more cohesive and visually appealing layout for statistics and event tiles. These updates aim to provide users with clearer insights and a more organized interface for event management.
1108 lines
43 KiB
PHP
1108 lines
43 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Hub promoteur — comptes migres acces evenement v2 uniquement.
|
|
* Legacy (com_eve_promoteur) : comportement inchange, pas de hub.
|
|
*/
|
|
|
|
require_once __DIR__ . '/inc_fx_eve_acces.php';
|
|
|
|
function fxPromoteurHubComUsesV2($intComId)
|
|
{
|
|
return fxEveAccesComHasV2(intval($intComId));
|
|
}
|
|
|
|
/** La page compte_promoteur_hub est-elle installee (SQL applique) ? */
|
|
function fxPromoteurHubPageExists()
|
|
{
|
|
global $objDatabase;
|
|
|
|
static $blnExists = null;
|
|
|
|
if ($blnExists !== null) {
|
|
return $blnExists;
|
|
}
|
|
|
|
if (!isset($objDatabase)) {
|
|
$blnExists = false;
|
|
return $blnExists;
|
|
}
|
|
|
|
$intNb = $objDatabase->fxGetVar(
|
|
"SELECT COUNT(*) FROM inscriptions_pages WHERE pag_code = 'compte_promoteur_hub' AND pag_actif = 1"
|
|
);
|
|
|
|
$blnExists = ($intNb !== null && intval($intNb) > 0);
|
|
|
|
return $blnExists;
|
|
}
|
|
|
|
/** Le compte doit-il atterrir sur le hub v2 ? (acces v2 + page installee) */
|
|
function fxPromoteurHubShouldUse($intComId)
|
|
{
|
|
return fxPromoteurHubComUsesV2(intval($intComId)) && fxPromoteurHubPageExists();
|
|
}
|
|
|
|
function fxPromoteurHubUrl($strLangue = 'fr')
|
|
{
|
|
global $vDomaine;
|
|
|
|
return $vDomaine . ($strLangue === 'fr' ? '/compte/promoteur_hub' : '/account/promoteur_hub');
|
|
}
|
|
|
|
function fxPromoteurHubParticipantUrl($strLangue = 'fr')
|
|
{
|
|
global $vDomaine;
|
|
|
|
return $vDomaine . ($strLangue === 'fr' ? '/compte/accueil' : '/account/accueil');
|
|
}
|
|
|
|
function fxPromoteurHubPromoteurTableUrl($intEveId, $strLangue = 'fr')
|
|
{
|
|
global $vDomaine;
|
|
|
|
$strBase = ($strLangue === 'fr') ? '/compte/inc_tableau_promoteur' : '/account/inc_tableau_promoteur';
|
|
|
|
return $vDomaine . $strBase . '?promoteur_eve_id=' . urlencode(base64_encode(intval($intEveId)));
|
|
}
|
|
|
|
function fxPromoteurHubPermKeysWeb()
|
|
{
|
|
return array(
|
|
'inscriptions.view',
|
|
'inscriptions.edit',
|
|
'dossards.view',
|
|
'dossards.manage',
|
|
'epreuves.view',
|
|
'epreuves.edit_qte',
|
|
'rabais.view',
|
|
'rabais.manage',
|
|
'emails.send',
|
|
'reports.chrono',
|
|
'reports.finances',
|
|
'reports.finances_membership',
|
|
'reports.finances_events',
|
|
'reports.payments',
|
|
'reports.adhesions',
|
|
'reports.adhesions_sales',
|
|
'reports.finances_captains',
|
|
'reports.custom',
|
|
'team.view',
|
|
'team.invite',
|
|
'team.manage',
|
|
);
|
|
}
|
|
|
|
function fxPromoteurHubCanAccessPromoteurWeb($intComId, $intEveId)
|
|
{
|
|
if (!function_exists('fxIsPromoteur')) {
|
|
require_once __DIR__ . '/inc_fonctions.php';
|
|
}
|
|
|
|
if (fxIsPromoteur(intval($intComId), intval($intEveId))) {
|
|
return true;
|
|
}
|
|
|
|
if (!fxEveAccesComHasV2ForEvent(intval($intComId), intval($intEveId))) {
|
|
return false;
|
|
}
|
|
|
|
return fxEveAccesHasAnyPermission(intval($intComId), intval($intEveId), fxPromoteurHubPermKeysWeb());
|
|
}
|
|
|
|
function fxPromoteurHubParseDateTs($strDate)
|
|
{
|
|
$strDate = trim((string)$strDate);
|
|
|
|
if ($strDate === '' || strpos($strDate, '0000-00-00') === 0) {
|
|
return 0;
|
|
}
|
|
|
|
return strtotime(substr($strDate, 0, 10));
|
|
}
|
|
|
|
function fxPromoteurHubHighlightUntilTs($strDateDebut, $strDateFin)
|
|
{
|
|
$intDebut = fxPromoteurHubParseDateTs($strDateDebut);
|
|
$intFin = fxPromoteurHubParseDateTs($strDateFin);
|
|
$intRef = ($intFin > 0) ? max($intDebut, $intFin) : $intDebut;
|
|
|
|
if ($intRef <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
return strtotime('+14 days', $intRef);
|
|
}
|
|
|
|
function fxPromoteurHubFormatEventDate($arrEvent, $strLangue)
|
|
{
|
|
$strDebut = trim($arrEvent['eve_date_debut'] ?? '');
|
|
$strFin = trim($arrEvent['eve_date_fin'] ?? '');
|
|
|
|
if ($strDebut === '' || strpos($strDebut, '0000-00-00') === 0) {
|
|
return '';
|
|
}
|
|
|
|
$strFmtDebut = date('Y-m-d', fxPromoteurHubParseDateTs($strDebut));
|
|
$intFin = fxPromoteurHubParseDateTs($strFin);
|
|
|
|
if ($intFin <= 0 || $strFmtDebut === date('Y-m-d', $intFin)) {
|
|
return $strFmtDebut;
|
|
}
|
|
|
|
return $strFmtDebut . ' — ' . date('Y-m-d', $intFin);
|
|
}
|
|
|
|
function fxPromoteurHubGetRoleLabelsByEvent($intComId)
|
|
{
|
|
global $objDatabase;
|
|
|
|
$arrByEve = array();
|
|
$tabRows = fxEveAccesListByComId(intval($intComId));
|
|
|
|
if (!is_array($tabRows)) {
|
|
return $arrByEve;
|
|
}
|
|
|
|
for ($i = 1; $i <= count($tabRows); $i++) {
|
|
$row = $tabRows[$i];
|
|
if (($row['ea_statut'] ?? '') !== 'actif') {
|
|
continue;
|
|
}
|
|
|
|
$intEveId = intval($row['eve_id'] ?? 0);
|
|
if ($intEveId <= 0) {
|
|
continue;
|
|
}
|
|
|
|
$strLabel = trim($row['role_label_fr'] ?? '');
|
|
if ($strLabel === '') {
|
|
$strLabel = trim($row['role_code'] ?? '');
|
|
}
|
|
|
|
if ($strLabel === '') {
|
|
continue;
|
|
}
|
|
|
|
if (!isset($arrByEve[$intEveId])) {
|
|
$arrByEve[$intEveId] = array();
|
|
}
|
|
|
|
if (!in_array($strLabel, $arrByEve[$intEveId], true)) {
|
|
$arrByEve[$intEveId][] = $strLabel;
|
|
}
|
|
}
|
|
|
|
return $arrByEve;
|
|
}
|
|
|
|
/** Evenements promoteur legacy (com_eve_promoteur) pour ce compte. */
|
|
function fxPromoteurHubGetLegacyEventIds($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();
|
|
}
|
|
|
|
return array_map('trim', explode(',', $row['com_eve_promoteur']));
|
|
}
|
|
|
|
function fxPromoteurHubGetEvents($intComId, $strLangue = 'fr')
|
|
{
|
|
global $objDatabase, $vDomaine, $vRepertoireFichiers;
|
|
|
|
$arrHighlight = array();
|
|
$arrArchived = array();
|
|
|
|
// Union : evenements legacy (com_eve_promoteur) + acces v2
|
|
$arrEventIds = array_merge(
|
|
fxPromoteurHubGetLegacyEventIds(intval($intComId)),
|
|
fxEveAccesGetEventIds(intval($intComId))
|
|
);
|
|
|
|
if (empty($arrEventIds)) {
|
|
return array('highlight' => $arrHighlight, 'archived' => $arrArchived);
|
|
}
|
|
|
|
$arrIds = array_values(array_unique(array_filter(array_map('intval', $arrEventIds), function ($v) {
|
|
return $v > 0;
|
|
})));
|
|
|
|
if (empty($arrIds)) {
|
|
return array('highlight' => $arrHighlight, 'archived' => $arrArchived);
|
|
}
|
|
|
|
$strLang = in_array($strLangue, array('fr', 'en'), true) ? $strLangue : 'fr';
|
|
$strAlt = ($strLang === 'fr') ? 'en' : 'fr';
|
|
$arrRoles = fxPromoteurHubGetRoleLabelsByEvent(intval($intComId));
|
|
$intToday = strtotime(date('Y-m-d'));
|
|
|
|
$sql = "
|
|
SELECT e.eve_id, e.eve_nom_fr, e.eve_nom_en, e.eve_date_debut, e.eve_date_fin,
|
|
e.eve_lieu_fr, e.eve_lieu_en, e.eve_photo_fr, e.eve_photo_en,
|
|
e.te_id, e.eve_qte_modifiable, e.eve_rapport_finances_capitaines,
|
|
t.te_icone
|
|
FROM inscriptions_evenements e
|
|
JOIN inscriptions_types_evenements t ON t.te_id = e.te_id
|
|
WHERE e.eve_actif = 1
|
|
AND e.eve_id IN (" . implode(',', $arrIds) . ")
|
|
ORDER BY e.eve_date_debut ASC, e.eve_nom_fr ASC
|
|
";
|
|
$tabEvents = $objDatabase->fxGetResults($sql);
|
|
|
|
if (!is_array($tabEvents)) {
|
|
return array('highlight' => $arrHighlight, 'archived' => $arrArchived);
|
|
}
|
|
|
|
for ($i = 1; $i <= count($tabEvents); $i++) {
|
|
$row = $tabEvents[$i];
|
|
$intEveId = intval($row['eve_id']);
|
|
$strNom = trim($row['eve_nom_' . $strLang] ?? '');
|
|
|
|
if ($strNom === '') {
|
|
$strNom = trim($row['eve_nom_' . $strAlt] ?? '');
|
|
}
|
|
|
|
$strLieu = trim($row['eve_lieu_' . $strLang] ?? '');
|
|
if ($strLieu === '') {
|
|
$strLieu = trim($row['eve_lieu_' . $strAlt] ?? '');
|
|
}
|
|
|
|
if (intval($row['eve_id']) === 175 && trim($row['eve_photo_' . $strLang] ?? '') !== '') {
|
|
$strIcon = $vDomaine . $vRepertoireFichiers . '/images/evenements/' . $row['eve_photo_' . $strLang];
|
|
} else {
|
|
$strIcon = $vDomaine . '/images/' . ($row['te_icone'] ?? '');
|
|
}
|
|
|
|
$intHighlightUntil = fxPromoteurHubHighlightUntilTs($row['eve_date_debut'] ?? '', $row['eve_date_fin'] ?? '');
|
|
$blnHighlight = ($intHighlightUntil <= 0) || ($intToday <= $intHighlightUntil);
|
|
|
|
$arrItem = array(
|
|
'eve_id' => $intEveId,
|
|
'nom' => $strNom,
|
|
'lieu' => $strLieu,
|
|
'date_label' => fxPromoteurHubFormatEventDate($row, $strLang),
|
|
'ts_debut' => fxPromoteurHubParseDateTs($row['eve_date_debut'] ?? ''),
|
|
'icon' => $strIcon,
|
|
'roles' => $arrRoles[$intEveId] ?? array(),
|
|
'te_id' => intval($row['te_id'] ?? 0),
|
|
'qte_modifiable' => intval($row['eve_qte_modifiable'] ?? 0),
|
|
'rapport_capitaines' => intval($row['eve_rapport_finances_capitaines'] ?? 0),
|
|
'com_id' => intval($intComId),
|
|
'url_promoteur' => fxPromoteurHubCanAccessPromoteurWeb($intComId, $intEveId)
|
|
? fxPromoteurHubPromoteurTableUrl($intEveId, $strLang)
|
|
: '',
|
|
'url_mobile' => '',
|
|
);
|
|
|
|
if (!function_exists('fxInscrGestionCanAccess')) {
|
|
require_once __DIR__ . '/inc_fx_inscriptions_gestion.php';
|
|
}
|
|
|
|
if (fxInscrGestionCanAccess(intval($intComId), $intEveId)) {
|
|
$arrItem['url_mobile'] = fxInscrGestionBaseUrl($strLang, false)
|
|
. '?promoteur_eve_id=' . urlencode(base64_encode($intEveId));
|
|
}
|
|
|
|
if ($blnHighlight) {
|
|
$arrHighlight[] = $arrItem;
|
|
} else {
|
|
$arrArchived[] = $arrItem;
|
|
}
|
|
}
|
|
|
|
usort($arrHighlight, function ($a, $b) {
|
|
$ta = intval($a['ts_debut'] ?? 0);
|
|
$tb = intval($b['ts_debut'] ?? 0);
|
|
if ($ta === $tb) {
|
|
return strcasecmp($a['nom'], $b['nom']);
|
|
}
|
|
if ($ta <= 0) {
|
|
return 1;
|
|
}
|
|
if ($tb <= 0) {
|
|
return -1;
|
|
}
|
|
return $ta <=> $tb;
|
|
});
|
|
|
|
usort($arrArchived, function ($a, $b) {
|
|
$ta = intval($a['ts_debut'] ?? 0);
|
|
$tb = intval($b['ts_debut'] ?? 0);
|
|
if ($ta === $tb) {
|
|
return strcasecmp($b['nom'], $a['nom']);
|
|
}
|
|
return $tb <=> $ta;
|
|
});
|
|
|
|
return array('highlight' => $arrHighlight, 'archived' => $arrArchived);
|
|
}
|
|
|
|
function fxPromoteurHubEsc($str)
|
|
{
|
|
return htmlspecialchars((string)$str, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Liste des fonctions d'un evenement (groupes : rapports + gestion),
|
|
* fidele a inc_tableau_promoteur.php.
|
|
*/
|
|
function fxPromoteurHubGetEventLinks($arrItem, $strLangue)
|
|
{
|
|
global $vDomaine, $objDatabase;
|
|
|
|
$intEveId = intval($arrItem['eve_id']);
|
|
$intComId = intval($arrItem['com_id'] ?? ($_SESSION['com_id'] ?? 0));
|
|
$intTeId = intval($arrItem['te_id'] ?? 0);
|
|
$blnDon = ($intTeId == 9);
|
|
$strE = urlencode(base64_encode($intEveId));
|
|
$strRapport = $vDomaine . '/superadm/rapport_new.php?r=';
|
|
$strCompte = $vDomaine . ($strLangue === 'fr' ? '/compte/' : '/account/');
|
|
$year = date('Y');
|
|
$strDateTq = $year . '-04-01 00:00:00';
|
|
|
|
$arrRapports = array();
|
|
$arrGestion = array();
|
|
|
|
// ---- Rapports ----
|
|
if ($intTeId != 9) {
|
|
$arrRapports[] = array('label' => 'chrono + questions', 'url' => $strRapport . 'chrono&e=' . $strE . '&lng=' . $strLangue, 'target' => '_blank');
|
|
}
|
|
|
|
if ($intTeId == 13) {
|
|
$arrRapports[] = array('label' => 'Transactions-Finances-Tout', 'url' => $strRapport . 'finances-membership&e=' . $strE . '&lng=' . $strLangue . '&a-ach_maj_from=' . urlencode($strDateTq) . '&btn_search=', 'target' => '_blank');
|
|
} else {
|
|
$arrRapports[] = array('label' => 'Transactions-Finances', 'url' => $strRapport . 'finances&e=' . $strE . '&lng=' . $strLangue, 'target' => '_blank');
|
|
}
|
|
|
|
if ($intTeId == 13) {
|
|
$arrRapports[] = array('label' => 'Transactions-Finances-Adhésions Seul', 'url' => $strRapport . 'finances-membership-tq&e=' . $strE . '&lng=' . $strLangue . '&a-ach_maj_from=' . urlencode($strDateTq) . '&btn_search=', 'target' => '_blank');
|
|
$arrRapports[] = array('label' => 'Transactions-Finances-Événements Seul', 'url' => $strRapport . 'finances-membership-autre&e=' . $strE . '&lng=' . $strLangue . '&a-ach_maj_from=' . urlencode($strDateTq) . '&btn_search=', 'target' => '_blank');
|
|
$arrRapports[] = array('label' => 'adhésions actives', 'url' => $strRapport . 'adhesions&e=' . $strE . '&lng=' . $strLangue, 'target' => '_blank');
|
|
$arrRapports[] = array('label' => "liste d'adhésions annuelles", 'url' => $strRapport . 'adhesions-ventes&e=' . $strE . '&lng=' . $strLangue, 'target' => '_blank');
|
|
}
|
|
|
|
if (intval($arrItem['rapport_capitaines'] ?? 0) == 1) {
|
|
$arrRapports[] = array('label' => 'Transactions-Finances (capitaines seulement)', 'url' => $strRapport . 'finances-pnq&e=' . $strE . '&lng=' . $strLangue, 'target' => '_blank');
|
|
}
|
|
|
|
$arrRapports[] = array('label' => ($strLangue === 'fr' ? 'Paiements' : 'Payments'), 'url' => $strRapport . 'remboursements&e=' . $strE . '&lng=' . $strLangue, 'target' => '_blank');
|
|
|
|
if (function_exists('fxGetMenussuperadm')) {
|
|
$tabRapports = fxGetMenussuperadm(0, 0, 1, $intEveId);
|
|
if (is_array($tabRapports)) {
|
|
for ($intCtr = 1; $intCtr <= count($tabRapports); $intCtr++) {
|
|
$arrRapports[] = array(
|
|
'label' => fxUnescape($tabRapports[$intCtr]['men_nom']),
|
|
'url' => $vDomaine . '/superadm/index.php?t=' . urlencode(base64_encode(fxUnescape($tabRapports[$intCtr]['men_id']))) . '&a=report&lng=' . $strLangue,
|
|
'target' => '_blank',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- Gestion ----
|
|
if (!$blnDon) {
|
|
$arrGestion[] = array('label' => afficheTexte('tableau_promoteur_menudossard', 0), 'url' => $strCompte . 'inc_tableau_dossards?promoteur_eve_id=' . $strE . '&lng=' . $strLangue, 'icon' => 'fa-id-card-o');
|
|
|
|
if (intval($arrItem['qte_modifiable'] ?? 0) == 1) {
|
|
$arrGestion[] = array('label' => afficheTexte('tableau_promoteur_menuepreuves', 0), 'url' => $strCompte . 'inc_tableau_epreuves?promoteur_eve_id=' . $strE . '&lng=' . $strLangue, 'icon' => 'fa-pencil-square-o');
|
|
}
|
|
|
|
if (!empty($_SESSION['usa_id'])
|
|
|| fxEveAccesHasAnyPermission($intComId, $intEveId, array('dossards.manage', 'epreuves.edit_qte'))) {
|
|
$strMenuQte = afficheTexte('tableau_promoteur_menu_gestion_qte_dossards', 0, 0);
|
|
if (strpos($strMenuQte, '*tableau_promoteur_menu_gestion_qte_dossards*') !== false) {
|
|
$strMenuQte = 'Gestion des quantités et dossards';
|
|
}
|
|
$arrGestion[] = array('label' => $strMenuQte, 'url' => $strCompte . 'inc_tableau_gestion_epreuves?promoteur_eve_id=' . $strE . '&lng=' . $strLangue, 'icon' => 'fa-pencil-square-o');
|
|
}
|
|
}
|
|
|
|
$arrGestion[] = array('label' => afficheTexte('tableau_promoteur_menueinscription', 0), 'url' => $strCompte . 'inc_tableau_inscriptions?promoteur_eve_id=' . $strE . '&lng=' . $strLangue, 'icon' => 'fa-users');
|
|
|
|
if (function_exists('fxInscrGestionCanAccess') && fxInscrGestionCanAccess($intComId, $intEveId)) {
|
|
$arrGestion[] = array('label' => fxInscrGestionPromoteurMenuLabel(), 'url' => $strCompte . 'inc_tableau_inscriptions_gestion?promoteur_eve_id=' . $strE . '&lng=' . $strLangue, 'icon' => 'fa-users');
|
|
}
|
|
|
|
$arrGestion[] = array('label' => afficheTexte('tableau_promoteur_rabais', 0), 'url' => $strCompte . 'inc_tableau_rabais?promoteur_eve_id=' . $strE . '&lng=' . $strLangue, 'icon' => 'fa-money');
|
|
|
|
if ($intTeId == 13) {
|
|
$arrGestion[] = array('label' => afficheTexte('tableau_promoteur_envoie_email_questions', 0), 'url' => $strCompte . 'inc_tableau_mail_questions?promoteur_eve_id=' . $strE . '&lng=' . $strLangue, 'icon' => 'fa-paper-plane');
|
|
}
|
|
|
|
return array('rapports' => $arrRapports, 'gestion' => $arrGestion);
|
|
}
|
|
|
|
function fxPromoteurHubRenderLinkList($arrLinks, $strDefaultIcon)
|
|
{
|
|
if (empty($arrLinks)) {
|
|
return '';
|
|
}
|
|
|
|
$html = '<ul class="list-unstyled mb-0">';
|
|
|
|
foreach ($arrLinks as $arrLink) {
|
|
$strIcon = !empty($arrLink['icon']) ? $arrLink['icon'] : $strDefaultIcon;
|
|
$strTarget = !empty($arrLink['target']) ? ' target="' . fxPromoteurHubEsc($arrLink['target']) . '"' : '';
|
|
|
|
$html .= '<li class="mb-2">';
|
|
$html .= '<a class="btn btn-outline-primary btn-block text-left rounded-0" href="' . fxPromoteurHubEsc($arrLink['url']) . '"' . $strTarget . '>';
|
|
$html .= '<i class="fa ' . fxPromoteurHubEsc($strIcon) . ' mr-2" aria-hidden="true"></i>' . fxPromoteurHubEsc($arrLink['label']);
|
|
$html .= '</a></li>';
|
|
}
|
|
|
|
$html .= '</ul>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
function fxPromoteurHubRenderEventPanel($arrItem, $strLangue)
|
|
{
|
|
$strPanelId = 'hub-fn-' . intval($arrItem['eve_id']);
|
|
$arrLinks = fxPromoteurHubGetEventLinks($arrItem, $strLangue);
|
|
|
|
$html = '<div class="collapse promoteur-hub-functions mt-3" id="' . fxPromoteurHubEsc($strPanelId) . '">';
|
|
$html .= '<div class="row">';
|
|
|
|
// Colonne gauche : Gestion (promoteur). Colonne droite : Rapports.
|
|
$html .= '<div class="col-12 col-lg-6 mb-3">';
|
|
$html .= '<h6 class="text-uppercase text-muted mb-2"><i class="fa fa-cogs mr-2" aria-hidden="true"></i>' . fxPromoteurHubEsc(afficheTexte('promoteur_hub_section_gestion', 0)) . '</h6>';
|
|
$html .= fxPromoteurHubRenderLinkList($arrLinks['gestion'], 'fa-list');
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="col-12 col-lg-6 mb-3">';
|
|
$html .= '<h6 class="text-uppercase text-muted mb-2"><i class="fa fa-file mr-2" aria-hidden="true"></i>' . fxPromoteurHubEsc(afficheTexte('tableau_promoteur_menurapports', 0)) . '</h6>';
|
|
$html .= fxPromoteurHubRenderLinkList($arrLinks['rapports'], 'fa-bar-chart');
|
|
$html .= '</div>';
|
|
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Statistiques par epreuve pour un evenement (vendus / restant / max,
|
|
* check-in, liste d'attente, prix courant + date du prochain palier).
|
|
* Requetes agregees (1 par metrique) plutot qu'une boucle fxGetQuantites,
|
|
* pour rester rapide dans le hub.
|
|
*
|
|
* Retourne array('epreuves' => [...], 'flash' => [...]) ou null si aucune epreuve.
|
|
*/
|
|
function fxPromoteurHubGetEpreuveStats($intEveId, $strLangue = 'fr')
|
|
{
|
|
global $objDatabase;
|
|
|
|
$intEveId = intval($intEveId);
|
|
if ($intEveId <= 0 || !isset($objDatabase)) {
|
|
return null;
|
|
}
|
|
|
|
$strLang = in_array($strLangue, array('fr', 'en'), true) ? $strLangue : 'fr';
|
|
$strAlt = ($strLang === 'fr') ? 'en' : 'fr';
|
|
|
|
// ---- Liste des epreuves ----
|
|
$sqlEpreuves = "
|
|
SELECT epr_id, epr_categorie_fr, epr_categorie_en, epr_type_fr, epr_type_en,
|
|
epr_nom_fr, epr_nom_en, epr_date, epr_heure, epr_date_limite,
|
|
epr_qte, epr_qte_origine, epr_qte_limitee, epr_equipe, epr_nb_participants
|
|
FROM inscriptions_epreuves
|
|
WHERE eve_id = " . $intEveId . " AND epr_actif = 1
|
|
ORDER BY epr_tri, epr_type_" . $strLang . ", epr_nom_" . $strLang . "
|
|
";
|
|
$tabEpreuves = $objDatabase->fxGetResults($sqlEpreuves);
|
|
|
|
if (!is_array($tabEpreuves) || count($tabEpreuves) === 0) {
|
|
return null;
|
|
}
|
|
|
|
$arrIds = array();
|
|
for ($i = 1; $i <= count($tabEpreuves); $i++) {
|
|
$arrIds[] = intval($tabEpreuves[$i]['epr_id']);
|
|
}
|
|
$strIds = implode(',', $arrIds);
|
|
|
|
// ---- Vendus / inscrits (confirmes, non annules) ----
|
|
$arrVendus = array();
|
|
$sqlVendus = "
|
|
SELECT p.epr_id AS epr_id, COUNT(DISTINCT e.pec_id_original) AS nb
|
|
FROM resultats_epreuves_commandees e
|
|
JOIN resultats_participants p
|
|
ON p.epr_id = e.epr_id AND p.pec_id = e.pec_id_original
|
|
WHERE p.is_cancelled = 0 AND p.epr_id IN (" . $strIds . ")
|
|
GROUP BY p.epr_id
|
|
";
|
|
$tabVendus = $objDatabase->fxGetResults($sqlVendus);
|
|
if (is_array($tabVendus)) {
|
|
for ($i = 1; $i <= count($tabVendus); $i++) {
|
|
$arrVendus[intval($tabVendus[$i]['epr_id'])] = intval($tabVendus[$i]['nb']);
|
|
}
|
|
}
|
|
|
|
// ---- Check-in (dossards remis) ----
|
|
$arrCheckin = array();
|
|
$sqlCheckin = "
|
|
SELECT epr_id, COUNT(*) AS nb
|
|
FROM resultats_participants
|
|
WHERE no_bib_remis = 1 AND epr_id IN (" . $strIds . ")
|
|
GROUP BY epr_id
|
|
";
|
|
$tabCheckin = $objDatabase->fxGetResults($sqlCheckin);
|
|
if (is_array($tabCheckin)) {
|
|
for ($i = 1; $i <= count($tabCheckin); $i++) {
|
|
$arrCheckin[intval($tabCheckin[$i]['epr_id'])] = intval($tabCheckin[$i]['nb']);
|
|
}
|
|
}
|
|
|
|
// ---- Liste d'attente : nombre + statut actif ----
|
|
$arrAttenteNb = array();
|
|
$sqlAttente = "
|
|
SELECT epr_id, COUNT(1) AS nb
|
|
FROM inscriptions_liste_attente_participants
|
|
WHERE (lispar_statut = 1 OR lispar_statut = 2) AND epr_id IN (" . $strIds . ")
|
|
GROUP BY epr_id
|
|
";
|
|
$tabAttente = $objDatabase->fxGetResults($sqlAttente);
|
|
if (is_array($tabAttente)) {
|
|
for ($i = 1; $i <= count($tabAttente); $i++) {
|
|
$arrAttenteNb[intval($tabAttente[$i]['epr_id'])] = intval($tabAttente[$i]['nb']);
|
|
}
|
|
}
|
|
|
|
$arrAttenteActive = array();
|
|
$sqlAttenteActive = "
|
|
SELECT epr_id, lis_active
|
|
FROM inscriptions_liste_attente
|
|
WHERE epr_id IN (" . $strIds . ")
|
|
";
|
|
$tabAttenteActive = $objDatabase->fxGetResults($sqlAttenteActive);
|
|
if (is_array($tabAttenteActive)) {
|
|
for ($i = 1; $i <= count($tabAttenteActive); $i++) {
|
|
$arrAttenteActive[intval($tabAttenteActive[$i]['epr_id'])] = intval($tabAttenteActive[$i]['lis_active']);
|
|
}
|
|
}
|
|
|
|
// ---- Prix (paliers publics) : prix courant + date du prochain palier ----
|
|
$arrTiers = array();
|
|
$sqlPrix = "
|
|
SELECT epr_id, ep_montant, ep_montant_affiche, ep_date_limite
|
|
FROM inscriptions_epreuves_prix
|
|
WHERE ep_prive = 0 AND epr_id IN (" . $strIds . ")
|
|
ORDER BY epr_id, ep_date_limite ASC
|
|
";
|
|
$tabPrix = $objDatabase->fxGetResults($sqlPrix);
|
|
if (is_array($tabPrix)) {
|
|
for ($i = 1; $i <= count($tabPrix); $i++) {
|
|
$intEpr = intval($tabPrix[$i]['epr_id']);
|
|
$fltMontant = (floatval($tabPrix[$i]['ep_montant_affiche']) > 0)
|
|
? floatval($tabPrix[$i]['ep_montant_affiche'])
|
|
: floatval($tabPrix[$i]['ep_montant']);
|
|
if (!isset($arrTiers[$intEpr])) {
|
|
$arrTiers[$intEpr] = array();
|
|
}
|
|
$arrTiers[$intEpr][] = array(
|
|
'montant' => $fltMontant,
|
|
'date_limite' => trim((string)($tabPrix[$i]['ep_date_limite'] ?? '')),
|
|
);
|
|
}
|
|
}
|
|
|
|
$strToday = date('Y-m-d');
|
|
|
|
// ---- Assemblage par epreuve + agregat flash ----
|
|
$arrEpreuves = array();
|
|
$intFlashVendus = 0;
|
|
$intFlashMax = 0;
|
|
$intFlashAttente = 0;
|
|
$intFlashCompletes = 0;
|
|
$intFlashPresque = 0;
|
|
$fltFlashRevenus = 0.0;
|
|
$strFlashProchaineLimite = '';
|
|
|
|
for ($i = 1; $i <= count($tabEpreuves); $i++) {
|
|
$row = $tabEpreuves[$i];
|
|
$intEpr = intval($row['epr_id']);
|
|
|
|
$strTitre = trim((string)($row['epr_type_' . $strLang] ?? ''));
|
|
if ($strTitre === '') {
|
|
$strTitre = trim((string)($row['epr_type_' . $strAlt] ?? ''));
|
|
}
|
|
$strNom = trim((string)($row['epr_nom_' . $strLang] ?? ''));
|
|
if ($strNom === '') {
|
|
$strNom = trim((string)($row['epr_nom_' . $strAlt] ?? ''));
|
|
}
|
|
$strCategorie = trim((string)($row['epr_categorie_' . $strLang] ?? ''));
|
|
if ($strTitre === '') {
|
|
$strTitre = ($strNom !== '') ? $strNom : ('#' . $intEpr);
|
|
}
|
|
|
|
$intVendus = $arrVendus[$intEpr] ?? 0;
|
|
$intRestant = intval($row['epr_qte']);
|
|
$blnIllimitee = (intval($row['epr_qte_limitee']) !== 1);
|
|
// Max courant = places vendues + restantes ; origine = max initial fixe.
|
|
$intMax = $intVendus + $intRestant;
|
|
$intOrigine = intval($row['epr_qte_origine']);
|
|
|
|
$fltPct = ($blnIllimitee || $intMax <= 0) ? 0 : round(($intVendus / $intMax) * 100);
|
|
if ($fltPct > 100) {
|
|
$fltPct = 100;
|
|
}
|
|
|
|
// Etat de remplissage : complete / presque / ok / illimitee
|
|
if ($blnIllimitee) {
|
|
$strEtat = 'illimitee';
|
|
} elseif ($intRestant <= 0) {
|
|
$strEtat = 'complete';
|
|
$intFlashCompletes++;
|
|
} elseif ($fltPct >= 90) {
|
|
$strEtat = 'presque';
|
|
$intFlashPresque++;
|
|
} elseif ($fltPct >= 75) {
|
|
$strEtat = 'attention';
|
|
} else {
|
|
$strEtat = 'ok';
|
|
}
|
|
|
|
// Prix courant + date du prochain palier
|
|
$fltPrixCourant = null;
|
|
$strPrixDateFin = '';
|
|
$fltPrixProchain = null;
|
|
if (!empty($arrTiers[$intEpr])) {
|
|
$arrEprTiers = $arrTiers[$intEpr];
|
|
$intIdxCourant = -1;
|
|
foreach ($arrEprTiers as $intIdx => $arrTier) {
|
|
if ($arrTier['date_limite'] !== '' && $arrTier['date_limite'] >= $strToday) {
|
|
$intIdxCourant = $intIdx;
|
|
break;
|
|
}
|
|
}
|
|
if ($intIdxCourant === -1) {
|
|
// Tous les paliers sont passes : on prend le dernier (prix final), pas de prochain.
|
|
$intIdxCourant = count($arrEprTiers) - 1;
|
|
}
|
|
$fltPrixCourant = $arrEprTiers[$intIdxCourant]['montant'];
|
|
$strPrixDateFin = $arrEprTiers[$intIdxCourant]['date_limite'];
|
|
if (isset($arrEprTiers[$intIdxCourant + 1])) {
|
|
$fltPrixProchain = $arrEprTiers[$intIdxCourant + 1]['montant'];
|
|
}
|
|
}
|
|
|
|
$intAttenteNb = $arrAttenteNb[$intEpr] ?? 0;
|
|
$blnAttenteActive = !empty($arrAttenteActive[$intEpr]);
|
|
|
|
// Agregat flash
|
|
$intFlashVendus += $intVendus;
|
|
if (!$blnIllimitee) {
|
|
$intFlashMax += $intMax;
|
|
}
|
|
$intFlashAttente += $intAttenteNb;
|
|
if ($fltPrixCourant !== null) {
|
|
$fltFlashRevenus += $fltPrixCourant * $intVendus;
|
|
}
|
|
// Prochaine date limite d'inscription (la plus proche, dans le futur)
|
|
$strLimiteInscr = trim((string)($row['epr_date_limite'] ?? ''));
|
|
if ($strLimiteInscr !== '' && strpos($strLimiteInscr, '0000') !== 0 && $strLimiteInscr >= $strToday) {
|
|
if ($strFlashProchaineLimite === '' || $strLimiteInscr < $strFlashProchaineLimite) {
|
|
$strFlashProchaineLimite = $strLimiteInscr;
|
|
}
|
|
}
|
|
|
|
$arrEpreuves[] = array(
|
|
'epr_id' => $intEpr,
|
|
'titre' => $strTitre,
|
|
'nom' => $strNom,
|
|
'categorie' => $strCategorie,
|
|
'date' => trim((string)($row['epr_date'] ?? '')),
|
|
'heure' => trim((string)($row['epr_heure'] ?? '')),
|
|
'date_limite_inscr' => $strLimiteInscr,
|
|
'equipe' => (intval($row['epr_equipe']) === 1),
|
|
'nb_participants' => intval($row['epr_nb_participants']),
|
|
'vendus' => $intVendus,
|
|
'restant' => $intRestant,
|
|
'max' => $intMax,
|
|
'origine' => $intOrigine,
|
|
'illimitee' => $blnIllimitee,
|
|
'pct' => $fltPct,
|
|
'etat' => $strEtat,
|
|
'checkin' => $arrCheckin[$intEpr] ?? 0,
|
|
'attente_nb' => $intAttenteNb,
|
|
'attente_active' => $blnAttenteActive,
|
|
'prix_courant' => $fltPrixCourant,
|
|
'prix_date_fin' => $strPrixDateFin,
|
|
'prix_prochain' => $fltPrixProchain,
|
|
);
|
|
}
|
|
|
|
$intPctGlobal = ($intFlashMax > 0) ? round(($intFlashVendus / $intFlashMax) * 100) : 0;
|
|
if ($intPctGlobal > 100) {
|
|
$intPctGlobal = 100;
|
|
}
|
|
|
|
$arrFlash = array(
|
|
'total_vendus' => $intFlashVendus,
|
|
'total_max' => $intFlashMax,
|
|
'total_restant' => max(0, $intFlashMax - $intFlashVendus),
|
|
'pct_global' => $intPctGlobal,
|
|
'revenus' => $fltFlashRevenus,
|
|
'nb_epreuves' => count($arrEpreuves),
|
|
'nb_completes' => $intFlashCompletes,
|
|
'nb_presque' => $intFlashPresque,
|
|
'total_attente' => $intFlashAttente,
|
|
'prochaine_date_limite' => $strFlashProchaineLimite,
|
|
);
|
|
|
|
return array('epreuves' => $arrEpreuves, 'flash' => $arrFlash);
|
|
}
|
|
|
|
/**
|
|
* Rendu de la ligne resume (bande flash + badges d'alerte). Toujours visible.
|
|
*/
|
|
function fxPromoteurHubRenderFlash($arrStats, $strLangue = 'fr')
|
|
{
|
|
if (empty($arrStats) || empty($arrStats['epreuves'])) {
|
|
return '';
|
|
}
|
|
|
|
$blnFr = ($strLangue !== 'en');
|
|
$arrFlash = $arrStats['flash'];
|
|
|
|
$lbl = function ($fr, $en) use ($blnFr) {
|
|
return $blnFr ? $fr : $en;
|
|
};
|
|
|
|
$html = '';
|
|
|
|
// ---- Bande flash ----
|
|
$html .= '<div class="promoteur-hub-flash">';
|
|
|
|
$html .= '<div class="phub-flash-item phub-flash-main">';
|
|
$html .= '<span class="phub-flash-num">' . intval($arrFlash['total_vendus']) . '</span>';
|
|
$html .= '<span class="phub-flash-lbl">' . fxPromoteurHubEsc($lbl('inscrits', 'registered')) . '</span>';
|
|
$html .= '</div>';
|
|
|
|
if (intval($arrFlash['total_max']) > 0) {
|
|
$html .= '<div class="phub-flash-item">';
|
|
$html .= '<span class="phub-flash-num">' . intval($arrFlash['pct_global']) . '%</span>';
|
|
$html .= '<span class="phub-flash-lbl">' . fxPromoteurHubEsc($lbl('rempli', 'filled')) . '</span>';
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="phub-flash-item">';
|
|
$html .= '<span class="phub-flash-num">' . intval($arrFlash['total_restant']) . '</span>';
|
|
$html .= '<span class="phub-flash-lbl">' . fxPromoteurHubEsc($lbl('places restantes', 'spots left')) . '</span>';
|
|
$html .= '</div>';
|
|
}
|
|
|
|
if (floatval($arrFlash['revenus']) > 0) {
|
|
$html .= '<div class="phub-flash-item">';
|
|
$html .= '<span class="phub-flash-num">' . fxPromoteurHubEsc(fxShowPrix($arrFlash['revenus'], $strLangue)) . '</span>';
|
|
$html .= '<span class="phub-flash-lbl">' . fxPromoteurHubEsc($lbl('revenus est.', 'est. revenue')) . '</span>';
|
|
$html .= '</div>';
|
|
}
|
|
|
|
$html .= '</div>'; // .promoteur-hub-flash
|
|
|
|
// ---- Badges d'alerte ----
|
|
$arrBadges = array();
|
|
if (intval($arrFlash['nb_completes']) > 0) {
|
|
$arrBadges[] = array('cls' => 'phub-badge-danger', 'icon' => 'fa-ban',
|
|
'txt' => intval($arrFlash['nb_completes']) . ' ' . $lbl('complète(s)', 'sold out'));
|
|
}
|
|
if (intval($arrFlash['nb_presque']) > 0) {
|
|
$arrBadges[] = array('cls' => 'phub-badge-warn', 'icon' => 'fa-exclamation-triangle',
|
|
'txt' => intval($arrFlash['nb_presque']) . ' ' . $lbl('presque pleine(s)', 'almost full'));
|
|
}
|
|
if (intval($arrFlash['total_attente']) > 0) {
|
|
$arrBadges[] = array('cls' => 'phub-badge-info', 'icon' => 'fa-hourglass-half',
|
|
'txt' => intval($arrFlash['total_attente']) . ' ' . $lbl('en attente', 'waiting'));
|
|
}
|
|
if ($arrFlash['prochaine_date_limite'] !== '') {
|
|
$arrBadges[] = array('cls' => 'phub-badge-soft', 'icon' => 'fa-clock-o',
|
|
'txt' => $lbl('limite', 'deadline') . ' ' . fxShowDate($arrFlash['prochaine_date_limite'], $strLangue, 1));
|
|
}
|
|
if (!empty($arrBadges)) {
|
|
$html .= '<div class="promoteur-hub-badges">';
|
|
foreach ($arrBadges as $arrBadge) {
|
|
$html .= '<span class="phub-badge ' . $arrBadge['cls'] . '"><i class="fa ' . $arrBadge['icon'] . ' mr-1" aria-hidden="true"></i>'
|
|
. fxPromoteurHubEsc($arrBadge['txt']) . '</span>';
|
|
}
|
|
$html .= '</div>';
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Rendu de la grille de tuiles par epreuve (contenu du collapse « Tableau de bord »).
|
|
*/
|
|
function fxPromoteurHubRenderEpreuvesGrid($arrStats, $strLangue = 'fr')
|
|
{
|
|
if (empty($arrStats) || empty($arrStats['epreuves'])) {
|
|
return '';
|
|
}
|
|
|
|
$blnFr = ($strLangue !== 'en');
|
|
|
|
// ---- Tuiles par epreuve ----
|
|
$html = '<div class="promoteur-hub-epreuves-grid">';
|
|
|
|
foreach ($arrStats['epreuves'] as $arrEpr) {
|
|
$strEtat = $arrEpr['etat'];
|
|
$html .= '<div class="phub-epr-tile phub-etat-' . fxPromoteurHubEsc($strEtat) . '">';
|
|
|
|
// En-tete : titre + categorie
|
|
$html .= '<div class="phub-epr-head">';
|
|
$html .= '<span class="phub-epr-titre">' . fxPromoteurHubEsc($arrEpr['titre']) . '</span>';
|
|
if ($arrEpr['categorie'] !== '') {
|
|
$html .= '<span class="phub-epr-cat">' . fxPromoteurHubEsc($arrEpr['categorie']) . '</span>';
|
|
}
|
|
if ($arrEpr['nom'] !== '' && $arrEpr['nom'] !== $arrEpr['titre']) {
|
|
$html .= '<span class="phub-epr-sub">' . fxPromoteurHubEsc($arrEpr['nom']) . '</span>';
|
|
}
|
|
$html .= '</div>';
|
|
|
|
// Gros chiffre : nombre de dossards vendus
|
|
$html .= '<div class="phub-epr-big">';
|
|
$html .= '<span class="phub-epr-bignum">' . intval($arrEpr['vendus']) . '</span>';
|
|
if (!$arrEpr['illimitee']) {
|
|
$html .= '<span class="phub-epr-max">/ ' . intval($arrEpr['max']) . '</span>';
|
|
}
|
|
$html .= '<span class="phub-epr-biglbl">' . fxPromoteurHubEsc($blnFr ? 'dossards vendus' : 'bibs sold') . '</span>';
|
|
$html .= '</div>';
|
|
|
|
// Barre de progression
|
|
if (!$arrEpr['illimitee'] && intval($arrEpr['max']) > 0) {
|
|
$html .= '<div class="phub-epr-bar"><span style="width:' . intval($arrEpr['pct']) . '%"></span></div>';
|
|
$html .= '<div class="phub-epr-barlbl">' . intval($arrEpr['pct']) . '% · '
|
|
. intval($arrEpr['restant']) . ' ' . fxPromoteurHubEsc($blnFr ? 'restant' : 'left') . '</div>';
|
|
} else {
|
|
$html .= '<div class="phub-epr-barlbl phub-epr-illimite"><span class="phub-infini mr-1" aria-hidden="true">∞</span>'
|
|
. fxPromoteurHubEsc($blnFr ? 'illimité' : 'unlimited') . '</div>';
|
|
}
|
|
|
|
// Pastilles secondaires
|
|
$html .= '<div class="phub-epr-chips">';
|
|
|
|
if ($arrEpr['prix_courant'] !== null) {
|
|
$html .= '<span class="phub-chip phub-chip-prix" title="' . fxPromoteurHubEsc($blnFr ? 'Prix courant' : 'Current price') . '">'
|
|
. '<i class="fa fa-tag mr-1" aria-hidden="true"></i>' . fxPromoteurHubEsc(fxShowPrix($arrEpr['prix_courant'], $strLangue)) . '</span>';
|
|
|
|
if ($arrEpr['prix_prochain'] !== null && $arrEpr['prix_date_fin'] !== '' && $arrEpr['prix_date_fin'] >= date('Y-m-d')) {
|
|
$html .= '<span class="phub-chip phub-chip-next" title="' . fxPromoteurHubEsc($blnFr ? 'Prochain prix' : 'Next price') . '">'
|
|
. '<i class="fa fa-arrow-up mr-1" aria-hidden="true"></i>'
|
|
. fxPromoteurHubEsc(fxShowPrix($arrEpr['prix_prochain'], $strLangue))
|
|
. ' ' . fxPromoteurHubEsc($blnFr ? 'dès' : 'on') . ' '
|
|
. fxShowDate($arrEpr['prix_date_fin'], $strLangue, 1) . '</span>';
|
|
}
|
|
}
|
|
|
|
if (intval($arrEpr['checkin']) > 0) {
|
|
$html .= '<span class="phub-chip phub-chip-checkin" title="' . fxPromoteurHubEsc($blnFr ? 'Dossards remis' : 'Bibs handed out') . '">'
|
|
. '<i class="fa fa-check mr-1" aria-hidden="true"></i>' . intval($arrEpr['checkin']) . '</span>';
|
|
}
|
|
|
|
if (intval($arrEpr['attente_nb']) > 0 || $arrEpr['attente_active']) {
|
|
$strAtt = $arrEpr['attente_active'] && intval($arrEpr['attente_nb']) === 0
|
|
? ($blnFr ? 'liste active' : 'list active')
|
|
: intval($arrEpr['attente_nb']) . ' ' . ($blnFr ? 'en attente' : 'waiting');
|
|
$html .= '<span class="phub-chip phub-chip-attente" title="' . fxPromoteurHubEsc($blnFr ? 'Liste d\'attente' : 'Waiting list') . '">'
|
|
. '<i class="fa fa-hourglass-half mr-1" aria-hidden="true"></i>' . fxPromoteurHubEsc($strAtt) . '</span>';
|
|
}
|
|
|
|
if ($arrEpr['date'] !== '' && strpos($arrEpr['date'], '0000') !== 0) {
|
|
$html .= '<span class="phub-chip phub-chip-date"><i class="fa fa-calendar-o mr-1" aria-hidden="true"></i>'
|
|
. fxShowDate($arrEpr['date'], $strLangue, 1) . '</span>';
|
|
}
|
|
|
|
$html .= '</div>'; // .phub-epr-chips
|
|
|
|
$html .= '</div>'; // .phub-epr-tile
|
|
}
|
|
|
|
$html .= '</div>'; // .promoteur-hub-epreuves-grid
|
|
|
|
return $html;
|
|
}
|
|
|
|
function fxPromoteurHubRenderEventCard($arrItem, $strLangue, $blnArchived = false)
|
|
{
|
|
$strCardClass = 'card promoteur-hub-card mb-3' . ($blnArchived ? ' promoteur-hub-card-archived' : '');
|
|
|
|
$blnFr = ($strLangue !== 'en');
|
|
$intEveId = intval($arrItem['eve_id']);
|
|
|
|
// Stats par epreuve : flash (resume, toujours visible) + grille (dans le collapse).
|
|
$arrStats = fxPromoteurHubGetEpreuveStats($intEveId, $strLangue);
|
|
$strFlash = fxPromoteurHubRenderFlash($arrStats, $strLangue);
|
|
$strGrid = fxPromoteurHubRenderEpreuvesGrid($arrStats, $strLangue);
|
|
$blnHasStats = ($strGrid !== '');
|
|
$blnFonctions = ($arrItem['url_promoteur'] !== '');
|
|
$strEprId = 'hub-epr-' . $intEveId;
|
|
$strFnId = 'hub-fn-' . $intEveId;
|
|
|
|
$html = '<div class="' . fxPromoteurHubEsc($strCardClass) . '">';
|
|
$html .= '<div class="card-body">';
|
|
|
|
// ---- Haut : identite (gauche) + resume flash (droite) ----
|
|
$html .= '<div class="row promoteur-hub-card-row">';
|
|
$html .= '<div class="' . ($strFlash !== '' ? 'col-12 col-lg-5' : 'col-12') . ' promoteur-hub-card-main">';
|
|
$html .= '<div class="d-flex align-items-center flex-wrap">';
|
|
$html .= '<div class="promoteur-hub-card-icon mr-3"><img src="' . fxPromoteurHubEsc($arrItem['icon']) . '" width="64" alt=""></div>';
|
|
$html .= '<div class="flex-grow-1">';
|
|
$html .= '<h2 class="h5 mb-1 promoteur-hub-event-title">' . fxPromoteurHubEsc($arrItem['nom']) . '</h2>';
|
|
|
|
if ($arrItem['date_label'] !== '') {
|
|
$html .= '<div class="text-muted small"><i class="fa fa-calendar-o mr-1" aria-hidden="true"></i>' . fxPromoteurHubEsc($arrItem['date_label']) . '</div>';
|
|
}
|
|
|
|
if ($arrItem['lieu'] !== '') {
|
|
$html .= '<div class="text-muted small"><i class="fa fa-map-marker mr-1" aria-hidden="true"></i>' . fxPromoteurHubEsc($arrItem['lieu']) . '</div>';
|
|
}
|
|
|
|
if (!empty($arrItem['roles'])) {
|
|
$html .= '<div class="small mt-1 text-muted">' . fxPromoteurHubEsc(implode(' · ', $arrItem['roles'])) . '</div>';
|
|
}
|
|
|
|
$html .= '</div></div>';
|
|
$html .= '</div>'; // .promoteur-hub-card-main
|
|
|
|
if ($strFlash !== '') {
|
|
$html .= '<div class="col-12 col-lg-7 promoteur-hub-card-flash">' . $strFlash . '</div>';
|
|
}
|
|
|
|
$html .= '</div>'; // .promoteur-hub-card-row
|
|
|
|
// ---- Boutons d'action (pleine largeur) ----
|
|
if ($blnHasStats || $blnFonctions) {
|
|
$html .= '<div class="promoteur-hub-actions mt-3">';
|
|
|
|
if ($blnHasStats) {
|
|
$html .= '<button type="button" class="btn btn-primary rounded-pill mr-2 mb-2 promoteur-hub-toggle collapsed" data-toggle="collapse" data-target="#' . fxPromoteurHubEsc($strEprId) . '" aria-expanded="false" aria-controls="' . fxPromoteurHubEsc($strEprId) . '">';
|
|
$html .= '<i class="fa fa-tachometer mr-2" aria-hidden="true"></i>' . fxPromoteurHubEsc(afficheTexte('promoteur_hub_btn_tableau', 0));
|
|
$html .= '<i class="fa fa-chevron-down ml-2 promoteur-hub-toggle-caret" aria-hidden="true"></i>';
|
|
$html .= '</button>';
|
|
}
|
|
|
|
if ($blnFonctions) {
|
|
$html .= '<button type="button" class="btn btn-outline-primary rounded-pill mb-2 promoteur-hub-toggle collapsed" data-toggle="collapse" data-target="#' . fxPromoteurHubEsc($strFnId) . '" aria-expanded="false" aria-controls="' . fxPromoteurHubEsc($strFnId) . '">';
|
|
$html .= '<i class="fa fa-bars mr-2" aria-hidden="true"></i>' . fxPromoteurHubEsc($blnFr ? 'Menu des fonctionnalités' : 'Features menu');
|
|
$html .= '<i class="fa fa-chevron-down ml-2 promoteur-hub-toggle-caret" aria-hidden="true"></i>';
|
|
$html .= '</button>';
|
|
}
|
|
|
|
$html .= '</div>'; // .promoteur-hub-actions
|
|
}
|
|
|
|
// ---- Collapse : tuiles par epreuve (pleine largeur) ----
|
|
if ($blnHasStats) {
|
|
$html .= '<div class="collapse promoteur-hub-epreuves-collapse mt-2" id="' . fxPromoteurHubEsc($strEprId) . '">' . $strGrid . '</div>';
|
|
}
|
|
|
|
// ---- Collapse : menu des fonctionnalites (gestion + rapports) ----
|
|
if ($blnFonctions) {
|
|
$html .= fxPromoteurHubRenderEventPanel($arrItem, $strLangue);
|
|
}
|
|
|
|
$html .= '</div></div>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
function fxPromoteurHubRenderEventSection($arrItems, $strTitleClef, $strLangue, $blnArchived = false)
|
|
{
|
|
if (empty($arrItems)) {
|
|
return '';
|
|
}
|
|
|
|
$html = '<h2 class="h4 mt-4 mb-3 promoteur-hub-section-title">' . fxPromoteurHubEsc(afficheTexte($strTitleClef, 0)) . '</h2>';
|
|
$html .= '<div class="promoteur promoteur-hub-events">';
|
|
|
|
foreach ($arrItems as $arrItem) {
|
|
$html .= fxPromoteurHubRenderEventCard($arrItem, $strLangue, $blnArchived);
|
|
}
|
|
|
|
$html .= '</div>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
function fxShowPromoteurHub($intComId, $strLangue = 'fr')
|
|
{
|
|
$arrBuckets = fxPromoteurHubGetEvents(intval($intComId), $strLangue);
|
|
$html = '';
|
|
|
|
$html .= '<div class="promoteur-hub-toolbar mb-4 d-flex flex-wrap align-items-center justify-content-between">';
|
|
$html .= '<p class="mb-2 mb-md-0 text-muted">' . fxPromoteurHubEsc(afficheTexte('promoteur_hub_intro', 0)) . '</p>';
|
|
$html .= '<a class="btn btn-outline-secondary rounded-pill" href="' . fxPromoteurHubEsc(fxPromoteurHubParticipantUrl($strLangue)) . '">';
|
|
$html .= '<i class="fa fa-user mr-2" aria-hidden="true"></i>' . fxPromoteurHubEsc(afficheTexte('promoteur_hub_link_participant', 0));
|
|
$html .= '</a>';
|
|
$html .= '</div>';
|
|
|
|
// Annonces : uniquement si le module doc a reellement des pages (sinon pas de "?" mort)
|
|
if (function_exists('fxDocRenderModule')) {
|
|
$strDocModule = fxDocRenderModule('promoteur_hub_annonces');
|
|
if ($strDocModule !== '') {
|
|
$html .= '<div class="promoteur-hub-annonces alert alert-info d-flex align-items-center mb-4">';
|
|
$html .= '<div class="flex-grow-1 mr-2">' . fxPromoteurHubEsc(afficheTexte('promoteur_hub_annonces_titre', 0)) . '</div>';
|
|
$html .= fxDocRenderTrigger('promoteur_hub_annonces');
|
|
$html .= $strDocModule;
|
|
$html .= '</div>';
|
|
}
|
|
}
|
|
|
|
$html .= fxPromoteurHubRenderEventSection($arrBuckets['highlight'], 'promoteur_hub_section_highlight', $strLangue, false);
|
|
$html .= fxPromoteurHubRenderEventSection($arrBuckets['archived'], 'promoteur_hub_section_archived', $strLangue, true);
|
|
|
|
if (empty($arrBuckets['highlight']) && empty($arrBuckets['archived'])) {
|
|
$html .= '<div class="alert alert-warning">' . fxPromoteurHubEsc(afficheTexte('promoteur_hub_empty', 0)) . '</div>';
|
|
}
|
|
|
|
// Accordeon par carte : ouvrir « Tableau de bord » ferme « Menu des fonctionnalites » et vice versa.
|
|
$html .= '<script>(function ($) {'
|
|
. 'if (!$) { return; }'
|
|
. '$(document).on("show.bs.collapse", ".promoteur-hub-epreuves-collapse, .promoteur-hub-functions", function () {'
|
|
. 'var $card = $(this).closest(".promoteur-hub-card");'
|
|
. '$card.find(".promoteur-hub-epreuves-collapse.show, .promoteur-hub-functions.show").not(this).collapse("hide");'
|
|
. '});'
|
|
. '})(window.jQuery);</script>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
function fxShowPromoteurHubMenuLink($arrCompteClient, $strLangue)
|
|
{
|
|
global $vDomaine;
|
|
|
|
if (!fxPromoteurHubShouldUse(intval($arrCompteClient['com_id'] ?? 0))) {
|
|
return '';
|
|
}
|
|
|
|
$arrIds = array_unique(array_filter(array_map('intval', array_merge(
|
|
fxPromoteurHubGetLegacyEventIds(intval($arrCompteClient['com_id'])),
|
|
fxEveAccesGetEventIds(intval($arrCompteClient['com_id']))
|
|
)), function ($v) {
|
|
return $v > 0;
|
|
}));
|
|
$intNb = count($arrIds);
|
|
$strNb = '';
|
|
|
|
if ($intNb > 0) {
|
|
$strNb = '<small>(' . $intNb . ' ';
|
|
$strNb .= ($intNb > 1) ? afficheTexte('compte_evenement_pluriel', 0) : afficheTexte('compte_evenement_singulier', 0);
|
|
$strNb .= ')</small>';
|
|
}
|
|
|
|
return '
|
|
<li class="nav-item">
|
|
<a class="nav-list" href="' . fxPromoteurHubEsc(fxPromoteurHubUrl($strLangue)) . '">
|
|
<i class="fa fa-tachometer" aria-hidden="true"></i> ' . fxPromoteurHubEsc(afficheTexte('promoteur_hub_menu', 0)) . $strNb . '
|
|
</a>
|
|
</li>
|
|
';
|
|
}
|