' . '' . '' . $strMsg . '' . ''; } function fxChronotrackApiAdminRenderLoaderAssets($vDomaine) { echo ''; echo ''; } function fxChronotrackApiAdminRenderEventLinkPicker($blnClosed) { echo ''; } function fxChronotrackApiAdminRenderEventPage($intEveId, $strLangue = 'fr', $blnInlineOnEventForm = false) { global $vDomaine; $arrEvent = fxChronotrackApiMs1EventRow($intEveId, $strLangue); if ($arrEvent === null) { echo '
Événement MS1 introuvable.
'; return; } $arrConfig = fxChronotrackApiConfigGet($intEveId); $blnConfigured = fxChronotrackApiSettingsConfigured(); $strStatus = $arrConfig['sync_status'] ?? ''; $blnClosed = ($strStatus === MSIN_API_CHRONOTRACK_SYNC_FERME); $strWrapperId = ''; echo '
'; if ($blnInlineOnEventForm) { echo '

MSIN API ChronoTrack

'; } else { echo '

MSIN API ChronoTrack

'; } echo '

Configuration du lien pour l\'événement MS1 ' . fxChronotrackApiAdminEsc($arrEvent['eve_nom']) . ' (eve_id ' . intval($arrEvent['eve_id']) . ').

'; if (!$blnConfigured) { echo '
' . fxChronotrackApiAdminEsc(fxChronotrackApiSettingsErrorMessage()) . '
'; } if ($arrConfig !== null) { echo '
'; echo 'Statut : ' . fxChronotrackApiAdminEsc(fxChronotrackApiConfigStatusLabel($strStatus)) . ''; echo ' — ChronoTrack : ' . fxChronotrackApiAdminEsc($arrConfig['ct_event_name']) . ''; echo ' (ID ' . intval($arrConfig['ct_event_id']) . ')'; echo '
'; } if ($blnClosed) { echo '
Statut fermé : plus de sync auto ni modification du lien/mapping. '; echo 'Le push manuel reste disponible ci-dessous.
'; } $blnEventLinked = ($arrConfig !== null && intval($arrConfig['ct_event_id'] ?? 0) > 0); if (!$blnEventLinked) { fxChronotrackApiAdminRenderEventLinkPicker($blnClosed); } if ($arrConfig !== null) { fxChronotrackApiAdminRenderStatusActions($intEveId, $strStatus, $blnEventLinked); } if ($arrConfig !== null) { fxChronotrackApiAdminRenderRaceMapping($intEveId, $arrConfig, $strLangue, $blnClosed, $blnEventLinked); } if ($arrConfig !== null && $blnEventLinked && $blnConfigured) { fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed); } if ($blnEventLinked && $blnConfigured) { fxChronotrackApiAdminRenderDiagnosticPanel(intval($arrConfig['ct_event_id'])); } if (!$blnInlineOnEventForm) { echo '

← Retour fiche événement

'; } echo '
'; fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed, $vDomaine); } function fxChronotrackApiAdminRenderStatusActions($intEveId, $strStatus, $blnEventLinked = true) { $strStep = $blnEventLinked ? '1' : '2'; echo '
' . $strStep . '. Cycle de vie sync
'; echo '

Activer avant la course ; Terminer après la course pour bloquer la sync auto et les changements de config.

'; echo '
'; if ($strStatus === MSIN_API_CHRONOTRACK_SYNC_LIE) { echo ''; } if ($strStatus === MSIN_API_CHRONOTRACK_SYNC_ACTIF) { echo 'Sync active'; echo ''; } if ($strStatus === MSIN_API_CHRONOTRACK_SYNC_FERME) { echo 'Fermé'; echo ''; } echo '
'; } function fxChronotrackApiAdminRenderRaceMapping($intEveId, $arrConfig, $strLangue, $blnClosed, $blnEventLinked = true) { $arrEpreuves = fxChronotrackApiMs1EpreuvesForEvent($intEveId, $strLangue); $arrMap = fxChronotrackApiRaceMapGetForEvent($intEveId); $blnHasSavedMapping = false; if ($arrEpreuves !== null) { for ($i = 1; $i <= count($arrEpreuves); $i++) { $intEprId = intval($arrEpreuves[$i]['epr_id']); if (intval($arrMap[$intEprId]['ct_race_id'] ?? 0) > 0) { $blnHasSavedMapping = true; break; } } } $strStep = $blnEventLinked ? '2' : '3'; echo '
' . $strStep . '. Mapping épreuves MS1 → races ChronoTrack
'; if ($arrEpreuves === null || count($arrEpreuves) === 0) { echo '

Aucune épreuve MS1 pour cet événement.

'; return; } if ($blnHasSavedMapping) { echo '
'; echo ''; for ($i = 1; $i <= count($arrEpreuves); $i++) { $intEprId = intval($arrEpreuves[$i]['epr_id']); $strLabel = trim($arrEpreuves[$i]['epr_type'] . ' — ' . $arrEpreuves[$i]['epr_nom']); $intCtRaceId = intval($arrMap[$intEprId]['ct_race_id'] ?? 0); $strCtRaceName = trim((string)($arrMap[$intEprId]['ct_race_name'] ?? '')); echo ''; } echo '
Épreuve MS1Race ChronoTrack
' . fxChronotrackApiAdminEsc($strLabel) . ' (epr_id ' . $intEprId . ')'; if ($intCtRaceId > 0) { echo fxChronotrackApiAdminEsc($strCtRaceName !== '' ? $strCtRaceName : ('Race ID ' . $intCtRaceId)); echo ' (ID ' . $intCtRaceId . ')'; } else { echo '— Non mappé —'; } echo '
'; if (!$blnClosed) { echo ''; } echo '
'; } $strEditStyle = $blnHasSavedMapping ? ' style="display:none;"' : ''; echo '
'; echo '

ChronoTrack event ID : ' . intval($arrConfig['ct_event_id']) . ' — courses CT Live (race_name via GET event/{id}/race).

'; echo '
'; if (!$blnClosed) { echo ''; } echo ''; for ($i = 1; $i <= count($arrEpreuves); $i++) { $intEprId = intval($arrEpreuves[$i]['epr_id']); $strLabel = trim($arrEpreuves[$i]['epr_type'] . ' — ' . $arrEpreuves[$i]['epr_nom']); echo ''; } echo '
Épreuve MS1Race ChronoTrack
' . fxChronotrackApiAdminEsc($strLabel) . ' (epr_id ' . $intEprId . ')'; echo '
'; if (!$blnClosed) { echo ''; if ($blnHasSavedMapping) { echo ' '; } } echo '
'; } function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false) { global $vDomaine; echo '
'; echo '
3. Synchronisation manuelle (participants)
'; echo '
'; if ($blnClosed) { echo '
Événement fermé — push manuel autorisé pour tests ou rattrapage.
'; } echo '

Lit resultats_participants (comme le rapport chrono). '; echo 'External ID = par_id_original. Dossard obligatoire ; sexe vide → NOT SPECIFIED côté CT ; '; echo 'doublon de dossard MS1 = aucun des inscrits concernés n\'est transféré.

'; echo '
' . fxChronotrackApiAdminRenderWaitHtml('Chargement…', $vDomaine) . '
'; echo '
'; echo ' '; echo ' '; echo ''; echo '
'; echo '
'; } function fxChronotrackApiAdminRenderDiagnosticPanel($intCtEventId) { echo '
'; echo '
'; echo '
'; echo '

Utilise les credentials MS1 déjà configurés (OAuth en cache). '; echo 'Sonde event/{id}/race, entry (5 premières inscriptions), '; echo 'event et reg_choice. Copie le rapport pour le développement.

'; echo ' '; echo ''; echo '
Cliquez sur « Lancer le diagnostic API ».
'; echo '
'; } function fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed, $vDomaine) { $intCtEventId = ($arrConfig !== null) ? intval($arrConfig['ct_event_id']) : 0; $arrMapCurrent = array(); $blnHasSavedMapping = false; if ($arrConfig !== null) { $arrMapRows = fxChronotrackApiRaceMapGetForEvent($intEveId); foreach ($arrMapRows as $intEprId => $arrRow) { $intCtRaceId = intval($arrRow['ct_race_id']); $arrMapCurrent[intval($intEprId)] = $intCtRaceId; if ($intCtRaceId > 0) { $blnHasSavedMapping = true; } } } ?> MSIN API ChronoTrack — Courses connectées'; echo '

Événements liés ou sync active. Le dashboard détaillé (diff, push) viendra en Phase 2.

'; if ($arrRows === null || count($arrRows) === 0) { echo '
Aucune course connectée.
'; return; } echo ''; for ($i = 1; $i <= count($arrRows); $i++) { $arr = $arrRows[$i]; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; } echo '
Événement MS1ChronoTrackStatut
' . fxChronotrackApiAdminEsc($arr['eve_nom']) . ' (' . intval($arr['eve_id']) . ')' . fxChronotrackApiAdminEsc($arr['ct_event_name']) . ' (' . intval($arr['ct_event_id']) . ')' . fxChronotrackApiAdminEsc(fxChronotrackApiConfigStatusLabel($arr['sync_status'])) . 'Configurer
'; }